blob: d29365c89c603110db69f05ac5d28b00c111279b [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>
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -070069#include "cds_reg_service.h"
70
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071/* MCS Based rate table */
72/* HT MCS parameters with Nss = 1 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080073static struct index_data_rate_type mcs_nss1[] = {
74 /* MCS L20 S20 L40 S40 */
75 {0, {65, 72}, {135, 150 } },
76 {1, {130, 144}, {270, 300 } },
77 {2, {195, 217}, {405, 450 } },
78 {3, {260, 289}, {540, 600 } },
79 {4, {390, 433}, {815, 900 } },
80 {5, {520, 578}, {1080, 1200} },
81 {6, {585, 650}, {1215, 1350} },
82 {7, {650, 722}, {1350, 1500} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083};
84
85/* HT MCS parameters with Nss = 2 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080086static struct index_data_rate_type mcs_nss2[] = {
87 /* MCS L20 S20 L40 S40 */
88 {0, {130, 144}, {270, 300 } },
89 {1, {260, 289}, {540, 600 } },
90 {2, {390, 433}, {810, 900 } },
91 {3, {520, 578}, {1080, 1200} },
92 {4, {780, 867}, {1620, 1800} },
93 {5, {1040, 1156}, {2160, 2400} },
94 {6, {1170, 1300}, {2430, 2700} },
95 {7, {1300, 1440}, {2700, 3000} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096};
97
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098/* MCS Based VHT rate table */
99/* MCS parameters with Nss = 1*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800100static struct index_vht_data_rate_type vht_mcs_nss1[] = {
101 /* MCS L20 S20 L40 S40 L80 S80 */
102 {0, {65, 72 }, {135, 150}, {293, 325} },
103 {1, {130, 144}, {270, 300}, {585, 650} },
104 {2, {195, 217}, {405, 450}, {878, 975} },
105 {3, {260, 289}, {540, 600}, {1170, 1300} },
106 {4, {390, 433}, {810, 900}, {1755, 1950} },
107 {5, {520, 578}, {1080, 1200}, {2340, 2600} },
108 {6, {585, 650}, {1215, 1350}, {2633, 2925} },
109 {7, {650, 722}, {1350, 1500}, {2925, 3250} },
110 {8, {780, 867}, {1620, 1800}, {3510, 3900} },
111 {9, {865, 960}, {1800, 2000}, {3900, 4333} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112};
113
114/*MCS parameters with Nss = 2*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800115static struct index_vht_data_rate_type vht_mcs_nss2[] = {
116 /* MCS L20 S20 L40 S40 L80 S80 */
117 {0, {130, 144}, {270, 300}, { 585, 650} },
118 {1, {260, 289}, {540, 600}, {1170, 1300} },
119 {2, {390, 433}, {810, 900}, {1755, 1950} },
120 {3, {520, 578}, {1080, 1200}, {2340, 2600} },
121 {4, {780, 867}, {1620, 1800}, {3510, 3900} },
122 {5, {1040, 1156}, {2160, 2400}, {4680, 5200} },
123 {6, {1170, 1300}, {2430, 2700}, {5265, 5850} },
124 {7, {1300, 1444}, {2700, 3000}, {5850, 6500} },
125 {8, {1560, 1733}, {3240, 3600}, {7020, 7800} },
126 {9, {1730, 1920}, {3600, 4000}, {7800, 8667} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128
129#ifdef BIG_ENDIAN_HOST
130
131/* ############# function definitions ############ */
132
133/**
134 * wma_swap_bytes() - swap bytes
135 * @pv: buffer
136 * @n: swap bytes
137 *
138 * Return: none
139 */
140void wma_swap_bytes(void *pv, uint32_t n)
141{
142 int32_t no_words;
143 int32_t i;
144 uint32_t *word_ptr;
145
146 no_words = n / sizeof(uint32_t);
147 word_ptr = (uint32_t *) pv;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700148 for (i = 0; i < no_words; i++)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149 *(word_ptr + i) = __cpu_to_le32(*(word_ptr + i));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150}
151
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700152#define SWAPME(x, len) wma_swap_bytes(&x, len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153#endif /* BIG_ENDIAN_HOST */
154
155/**
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800156 * wma_mcs_rate_match() - find the match mcs rate
157 * @match_rate: the rate to look up
158 * @is_sgi: return if the SGI rate is found
159 * @nss: the nss in use
160 * @nss1_rate: the nss1 rate
161 * @nss1_srate: the nss1 SGI rate
162 * @nss2_rate: the nss2 rate
163 * @nss2_srate: the nss2 SGI rate
164 *
165 * This is a helper function to find the match of the tx_rate
166 * in terms of the nss1/nss2 rate with non-SGI/SGI.
167 *
168 * Return: the found rate or 0 otherwise
169 */
170static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi,
171 uint8_t nss, uint16_t nss1_rate,
172 uint16_t nss1_srate,
173 uint16_t nss2_rate,
174 uint16_t nss2_srate)
175{
176 WMA_LOGD("%s match_rate: %d, %d %d %d %d",
177 __func__, match_rate, nss1_rate, nss1_srate, nss2_rate,
178 nss2_srate);
179
180 if (match_rate == nss1_rate) {
181 return nss1_rate;
182 } else if (match_rate == nss1_srate) {
183 *is_sgi = true;
184 return nss1_srate;
185 } else if (nss == 2 && match_rate == nss2_rate)
186 return nss2_rate;
187 else if (nss == 2 && match_rate == nss2_srate) {
188 *is_sgi = true;
189 return nss2_srate;
190 } else
191 return 0;
192}
193
194/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 * wma_get_mcs_idx() - get mcs index
196 * @maxRate: max rate
197 * @rate_flags: rate flags
198 * @nss: number of nss
199 * @mcsRateFlag: mcs rate flag
200 *
201 * Return: return mcs index
202 */
203static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
204 uint8_t nss, uint8_t *mcsRateFlag)
205{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800206 uint8_t index = 0;
Arif Hussainb8fef842016-07-19 09:43:13 -0700207 uint16_t match_rate = 0;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800208 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800210 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
211 __func__, maxRate, rate_flags, nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212
213 *mcsRateFlag = rate_flags;
214 *mcsRateFlag &= ~eHAL_TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800215 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 if (rate_flags & eHAL_TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800217 /* check for vht80 nss1/2 rate set */
218 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
219 vht_mcs_nss1[index].ht80_rate[0],
220 vht_mcs_nss1[index].ht80_rate[1],
221 vht_mcs_nss2[index].ht80_rate[0],
222 vht_mcs_nss2[index].ht80_rate[1]);
223 if (match_rate)
224 goto rate_found;
225 }
226 if ((rate_flags & eHAL_TX_RATE_VHT40) |
227 (rate_flags & eHAL_TX_RATE_VHT80)) {
228 /* check for vht40 nss1/2 rate set */
229 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
230 vht_mcs_nss1[index].ht40_rate[0],
231 vht_mcs_nss1[index].ht40_rate[1],
232 vht_mcs_nss2[index].ht40_rate[0],
233 vht_mcs_nss2[index].ht40_rate[1]);
234 if (match_rate) {
235 *mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
236 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237 }
238 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800239 if ((rate_flags & eHAL_TX_RATE_VHT20) |
240 (rate_flags & eHAL_TX_RATE_VHT40) |
241 (rate_flags & eHAL_TX_RATE_VHT80)) {
242 /* check for vht20 nss1/2 rate set */
243 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
244 vht_mcs_nss1[index].ht20_rate[0],
245 vht_mcs_nss1[index].ht20_rate[1],
246 vht_mcs_nss2[index].ht20_rate[0],
247 vht_mcs_nss2[index].ht20_rate[1]);
248 if (match_rate) {
249 *mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 |
250 eHAL_TX_RATE_VHT40);
251 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 }
253 }
254 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800255 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800257 /* check for ht40 nss1/2 rate set */
258 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
259 mcs_nss1[index].ht40_rate[0],
260 mcs_nss1[index].ht40_rate[1],
261 mcs_nss2[index].ht40_rate[0],
262 mcs_nss2[index].ht40_rate[1]);
263 if (match_rate) {
264 *mcsRateFlag = eHAL_TX_RATE_HT40;
265 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 }
267 }
wadesongbf665542017-02-28 14:30:51 +0800268 if ((rate_flags & eHAL_TX_RATE_HT20) ||
269 (rate_flags & eHAL_TX_RATE_HT40)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800270 /* check for ht20 nss1/2 rate set */
271 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
272 mcs_nss1[index].ht20_rate[0],
273 mcs_nss1[index].ht20_rate[1],
274 mcs_nss2[index].ht20_rate[0],
275 mcs_nss2[index].ht20_rate[1]);
276 if (match_rate) {
277 *mcsRateFlag = eHAL_TX_RATE_HT20;
278 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 }
280 }
281 }
282
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800283rate_found:
284 /* set SGI flag only if this is SGI rate */
285 if (match_rate && is_sgi == true)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 *mcsRateFlag |= eHAL_TX_RATE_SGI;
287
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800288 WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
289 __func__, match_rate, index, *mcsRateFlag, is_sgi);
290
291 return match_rate ? index : INVALID_MCS_IDX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292}
293
294/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530295 * wma_peek_vdev_req() - peek what request message is queued for response.
296 * the function does not delete the node after found
297 * @wma: WMA handle
298 * @vdev_id: vdev ID
299 * @type: request message type
300 *
301 * Return: the request message found
302 */
303static struct wma_target_req *wma_peek_vdev_req(tp_wma_handle wma,
304 uint8_t vdev_id, uint8_t type)
305{
306 struct wma_target_req *req_msg = NULL;
307 bool found = false;
308 qdf_list_node_t *node1 = NULL, *node2 = NULL;
309
310 qdf_spin_lock_bh(&wma->vdev_respq_lock);
311 if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&wma->vdev_resp_queue,
312 &node2)) {
313 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530314 return NULL;
315 }
316
317 do {
318 node1 = node2;
319 req_msg = qdf_container_of(node1, struct wma_target_req, node);
320 if (req_msg->vdev_id != vdev_id)
321 continue;
322 if (req_msg->type != type)
323 continue;
324
325 found = true;
326 break;
327 } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&wma->vdev_resp_queue,
328 node1, &node2));
329 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
330 if (!found) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800331 WMA_LOGE(FL("target request not found for vdev_id %d type %d"),
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530332 vdev_id, type);
333 return NULL;
334 }
335 WMA_LOGD(FL("target request found for vdev id: %d type %d msg %d"),
336 vdev_id, type, req_msg->msg_type);
337 return req_msg;
338}
339
340void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id,
341 int32_t rssi)
342{
343 struct sir_lost_link_info *lost_link_info;
344 QDF_STATUS qdf_status;
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800345 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530346
347 /* report lost link information only for STA mode */
Mukul Sharmaf9047232017-03-02 16:58:56 +0530348 if (wma_is_vdev_up(vdev_id) &&
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530349 (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) &&
350 (0 == wma->interfaces[vdev_id].sub_type)) {
351 lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
352 if (NULL == lost_link_info) {
353 WMA_LOGE("%s: failed to allocate memory", __func__);
354 return;
355 }
356 lost_link_info->vdev_id = vdev_id;
357 lost_link_info->rssi = rssi;
358 sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
359 sme_msg.bodyptr = lost_link_info;
360 sme_msg.bodyval = 0;
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800361 WMA_LOGD("%s: post msg to SME, bss_idx %d, rssi %d", __func__,
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530362 lost_link_info->vdev_id, lost_link_info->rssi);
363
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800364 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530365 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
366 WMA_LOGE("%s: fail to post msg to SME", __func__);
367 qdf_mem_free(lost_link_info);
368 }
369 }
370}
371
372/**
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700373 * host_map_smps_mode() - map fw smps mode to enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374 * @fw_smps_mode: fw smps mode
375 *
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700376 * Return: return enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700378enum eSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700380 enum eSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800382 switch (fw_smps_mode) {
383 case WMI_SMPS_FORCED_MODE_STATIC:
384 smps_mode = STATIC_SMPS_MODE;
385 break;
386 case WMI_SMPS_FORCED_MODE_DYNAMIC:
387 smps_mode = DYNAMIC_SMPS_MODE;
388 break;
389 default:
390 smps_mode = SMPS_MODE_DISABLED;
391 }
392
393 return smps_mode;
394}
395
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800396/**
397 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
398 * mode commmand param
399 * @smps_mode: SMPS mode according to the protocol
400 *
401 * Return: int > 0 for success else failure
402 */
403int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
404{
405 int param = -EINVAL;
406
407 switch (smps_mode) {
408 case STATIC_SMPS_MODE:
409 param = WMI_SMPS_FORCED_MODE_STATIC;
410 break;
411 case DYNAMIC_SMPS_MODE:
412 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
413 break;
414 case SMPS_MODE_DISABLED:
415 param = WMI_SMPS_FORCED_MODE_DISABLED;
416 break;
417 default:
418 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
419 smps_mode);
420 }
421 return param;
422}
423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424#ifdef WLAN_FEATURE_STATS_EXT
425/**
426 * wma_stats_ext_event_handler() - extended stats event handler
427 * @handle: wma handle
428 * @event_buf: event buffer received from fw
429 * @len: length of data
430 *
431 * Return: 0 for success or error code
432 */
433int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
434 uint32_t len)
435{
436 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
437 tSirStatsExtEvent *stats_ext_event;
438 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530439 QDF_STATUS status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -0700440 struct scheduler_msg cds_msg = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 uint8_t *buf_ptr;
442 uint32_t alloc_len;
443
444 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
445
446 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
447 if (!param_buf) {
448 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
449 return -EINVAL;
450 }
451
452 stats_ext_info = param_buf->fixed_param;
453 buf_ptr = (uint8_t *) stats_ext_info;
454
455 alloc_len = sizeof(tSirStatsExtEvent);
456 alloc_len += stats_ext_info->data_len;
457
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700458 if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE -
459 sizeof(*stats_ext_info))) {
460 WMA_LOGE("Excess data_len:%d", stats_ext_info->data_len);
461 QDF_ASSERT(0);
462 return -EINVAL;
463 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530464 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465 if (NULL == stats_ext_event) {
466 WMA_LOGE("%s: Memory allocation failure", __func__);
467 return -ENOMEM;
468 }
469
470 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
471
472 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
473 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530474 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 buf_ptr, stats_ext_event->event_data_len);
476
477 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
478 cds_msg.bodyptr = (void *)stats_ext_event;
479 cds_msg.bodyval = 0;
480
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800481 status = scheduler_post_msg(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530482 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530484 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485 return -EFAULT;
486 }
487
488 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
489 return 0;
490}
491#endif /* WLAN_FEATURE_STATS_EXT */
492
Nirav Shah93e789e2016-04-14 19:47:43 +0530493
Govind Singha471e5e2015-10-12 17:11:14 +0530494/**
495 * wma_profile_data_report_event_handler() - fw profiling handler
496 * @handle: wma handle
497 * @event_buf: event buffer received from fw
498 * @len: length of data
499 *
500 * Return: 0 for success or error code
501 */
502int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
503 uint32_t len)
504{
505 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
506 wmi_wlan_profile_ctx_t *profile_ctx;
507 wmi_wlan_profile_t *profile_data;
508 uint32_t i = 0;
509 uint32_t entries;
510 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530511 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530512
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700513 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
Govind Singha471e5e2015-10-12 17:11:14 +0530514 if (!param_buf) {
515 WMA_LOGE("%s: Invalid profile data event buf", __func__);
516 return -EINVAL;
517 }
518 profile_ctx = param_buf->profile_ctx;
519 buf_ptr = (uint8_t *)profile_ctx;
520 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
521 profile_data = (wmi_wlan_profile_t *) buf_ptr;
522 entries = profile_ctx->bin_count;
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 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530525 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530526 "TOT: %d\n"
527 "tx_msdu_cnt: %d\n"
528 "tx_mpdu_cnt: %d\n"
529 "tx_ppdu_cnt: %d\n"
530 "rx_msdu_cnt: %d\n"
531 "rx_mpdu_cnt: %d\n"
532 "bin_count: %d\n",
533 profile_ctx->tot,
534 profile_ctx->tx_msdu_cnt,
535 profile_ctx->tx_mpdu_cnt,
536 profile_ctx->tx_ppdu_cnt,
537 profile_ctx->rx_msdu_cnt,
538 profile_ctx->rx_mpdu_cnt,
539 profile_ctx->bin_count);
540
Nirav Shah93e789e2016-04-14 19:47:43 +0530541 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
542 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
543
Govind Singha471e5e2015-10-12 17:11:14 +0530544 for (i = 0; i < entries; i++) {
545 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
546 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530547 snprintf(temp_str, sizeof(temp_str),
548 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530549 profile_data[i].id,
550 profile_data[i].cnt,
551 profile_data[i].tot,
552 profile_data[i].min,
553 profile_data[i].max,
554 profile_data[i].hist_intvl,
555 profile_data[i].hist[0],
556 profile_data[i].hist[1],
557 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530558 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
559 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530560 }
561
562 return 0;
563}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564
565#ifdef WLAN_FEATURE_LINK_LAYER_STATS
566
Zhang Qian73c348a2017-03-13 16:15:55 +0800567#define WMA_FILL_TX_STATS(eve, msg) do {\
568 (msg)->msdus = (eve)->tx_msdu_cnt;\
569 (msg)->mpdus = (eve)->tx_mpdu_cnt;\
570 (msg)->ppdus = (eve)->tx_ppdu_cnt;\
571 (msg)->bytes = (eve)->tx_bytes;\
572 (msg)->drops = (eve)->tx_msdu_drop_cnt;\
573 (msg)->drop_bytes = (eve)->tx_drop_bytes;\
574 (msg)->retries = (eve)->tx_mpdu_retry_cnt;\
575 (msg)->failed = (eve)->tx_mpdu_fail_cnt;\
576} while (0)
577
578#define WMA_FILL_RX_STATS(eve, msg) do {\
579 (msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
580 (msg)->bytes = (eve)->mac_rx_bytes;\
581 (msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
582 (msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
583 (msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
584 (msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
585 (msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
586} while (0)
587
588/**
589 * wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
590 * @len: buffer length output
591 * @peer_num: peer number
592 * @fixed_param: fixed parameters in WMI event
593 *
594 * Structure of the stats message
595 * LL_EXT_STATS
596 * |
597 * |--Channel stats[1~n]
598 * |--Peer[1~n]
599 * |
600 * +---Signal
601 * +---TX
602 * | +---BE
603 * | +---BK
604 * | +---VI
605 * | +---VO
606 * |
607 * +---RX
608 * +---BE
609 * +---BK
610 * +---VI
611 * +---VO
612 * For each Access Category, the arregation and mcs
613 * stats are as this:
614 * TX
615 * +-BE/BK/VI/VO
616 * +----tx_mpdu_aggr_array
617 * +----tx_succ_mcs_array
618 * +----tx_fail_mcs_array
619 * +----tx_delay_array
620 * RX
621 * +-BE/BK/VI/VO
622 * +----rx_mpdu_aggr_array
623 * +----rx_mcs_array
624 *
625 * return: Address for result buffer.
626 */
627static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
628 uint32_t peer_num,
629 wmi_report_stats_event_fixed_param *fixed_param)
630{
631 tSirLLStatsResults *buf;
632 uint32_t buf_len;
633
634 if (!len || !fixed_param) {
635 WMA_LOGE(FL("Invalid input parameters."));
636 return NULL;
637 }
638
639 /*
640 * Result buffer has a structure like this:
641 * ---------------------------------
642 * | trigger_cond_i |
643 * +-------------------------------+
644 * | cca_chgd_bitmap |
645 * +-------------------------------+
646 * | sig_chgd_bitmap |
647 * +-------------------------------+
648 * | tx_chgd_bitmap |
649 * +-------------------------------+
650 * | rx_chgd_bitmap |
651 * +-------------------------------+
652 * | peer_num |
653 * +-------------------------------+
654 * | channel_num |
655 * +-------------------------------+
656 * | tx_mpdu_aggr_array_len |
657 * +-------------------------------+
658 * | tx_succ_mcs_array_len |
659 * +-------------------------------+
660 * | tx_fail_mcs_array_len |
661 * +-------------------------------+
662 * | tx_delay_array_len |
663 * +-------------------------------+
664 * | rx_mpdu_aggr_array_len |
665 * +-------------------------------+
666 * | rx_mcs_array_len |
667 * +-------------------------------+
668 * | pointer to CCA stats |
669 * +-------------------------------+
670 * | CCA stats |
671 * +-------------------------------+
672 * | peer_stats |----+
673 * +-------------------------------+ |
674 * | TX aggr/mcs parameters array | |
675 * | Length of this buffer is | |
676 * | not fixed. |<-+ |
677 * +-------------------------------+ | |
678 * | per peer tx stats |--+ |
679 * | BE | <--+
680 * | BK | |
681 * | VI | |
682 * | VO | |
683 * +-------------------------------+ |
684 * | TX aggr/mcs parameters array | |
685 * | Length of this buffer is | |
686 * | not fixed. |<-+ |
687 * +-------------------------------+ | |
688 * | peer peer rx stats |--+ |
689 * | BE | <--+
690 * | BK |
691 * | VI |
692 * | VO |
693 * ---------------------------------
694 */
695 buf_len = sizeof(tSirLLStatsResults) +
696 sizeof(struct sir_wifi_ll_ext_stats) +
697 fixed_param->num_chan_cca_stats *
698 sizeof(struct sir_wifi_chan_cca_stats) +
699 peer_num *
700 (sizeof(struct sir_wifi_ll_ext_peer_stats) +
701 WLAN_MAX_AC *
702 (sizeof(struct sir_wifi_tx) +
703 sizeof(struct sir_wifi_rx)) +
704 sizeof(uint32_t) * WLAN_MAX_AC *
705 (fixed_param->tx_mpdu_aggr_array_len +
706 fixed_param->tx_succ_mcs_array_len +
707 fixed_param->tx_fail_mcs_array_len +
708 fixed_param->tx_ppdu_delay_array_len +
709 fixed_param->rx_mpdu_aggr_array_len +
710 fixed_param->rx_mcs_array_len));
711
712 buf = (tSirLLStatsResults *)qdf_mem_malloc(buf_len);
713 if (buf == NULL) {
714 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
715 buf_len = 0;
716 return NULL;
717 }
718
719 *len = buf_len;
720 return buf;
721}
722
723/**
724 * wma_fill_tx_stats() - Fix TX stats into result buffer
725 * @ll_stats: LL stats buffer
726 * @fix_param: parameters with fixed length in WMI event
727 * @param_buf: parameters without fixed length in WMI event
728 * @buf: buffer for TLV parameters
729 *
730 * Return: None
731 */
732static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
733 wmi_report_stats_event_fixed_param *fix_param,
734 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
735 uint8_t **buf, uint32_t *buf_length)
736{
737 uint8_t *result;
738 uint32_t i, j, k;
739 wmi_peer_ac_tx_stats *wmi_peer_tx;
740 wmi_tx_stats *wmi_tx;
741 struct sir_wifi_tx *tx_stats;
742 struct sir_wifi_ll_ext_peer_stats *peer_stats;
743 uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
744 uint32_t len, dst_len, tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
745 tx_fail_mcs_array_len, tx_delay_array_len;
746
747 result = *buf;
748 dst_len = *buf_length;
749 tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
750 ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
751 tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
752 ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
753 tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
754 ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
755 tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
756 ll_stats->tx_delay_array_len = tx_delay_array_len;
757 wmi_peer_tx = param_buf->peer_ac_tx_stats;
758 wmi_tx = param_buf->tx_stats;
759
760 len = fix_param->num_peer_ac_tx_stats *
761 WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
762 if (len <= dst_len) {
763 tx_mpdu_aggr = (uint32_t *)result;
764 qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
765 result += len;
766 dst_len -= len;
767 } else {
768 WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong."));
769 tx_mpdu_aggr = NULL;
770 }
771
772 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
773 tx_succ_mcs_array_len * sizeof(uint32_t);
774 if (len <= dst_len) {
775 tx_succ_mcs = (uint32_t *)result;
776 qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
777 result += len;
778 dst_len -= len;
779 } else {
780 WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong."));
781 tx_succ_mcs = NULL;
782 }
783
784 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
785 tx_fail_mcs_array_len * sizeof(uint32_t);
786 if (len <= dst_len) {
787 tx_fail_mcs = (uint32_t *)result;
788 qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
789 result += len;
790 dst_len -= len;
791 } else {
792 WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong."));
793 tx_fail_mcs = NULL;
794 }
795
796 len = fix_param->num_peer_ac_tx_stats *
797 WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
798 if (len <= dst_len) {
799 tx_delay = (uint32_t *)result;
800 qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
801 result += len;
802 dst_len -= len;
803 } else {
804 WMA_LOGE(FL("TX_DELAY buffer length is wrong."));
805 tx_delay = NULL;
806 }
807
808 /* per peer tx stats */
809 peer_stats = ll_stats->peer_stats;
810
811 for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
812 uint32_t peer_id = wmi_peer_tx[i].peer_id;
813 struct sir_wifi_tx *ac;
814 wmi_tx_stats *wmi_tx_stats;
815
816 for (j = 0; j < ll_stats->peer_num; j++) {
817 peer_stats += j;
818 if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
819 peer_stats->peer_id == peer_id)
820 break;
821 }
822
823 if (j < ll_stats->peer_num) {
824 peer_stats->peer_id = wmi_peer_tx[i].peer_id;
825 peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
826 tx_stats = (struct sir_wifi_tx *)result;
827 for (k = 0; k < WLAN_MAX_AC; k++) {
828 wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
829 ac = &tx_stats[k];
830 WMA_FILL_TX_STATS(wmi_tx_stats, ac);
831 ac->mpdu_aggr_size = tx_mpdu_aggr;
832 ac->aggr_len = tx_mpdu_aggr_array_len *
833 sizeof(uint32_t);
834 ac->success_mcs_len = tx_succ_mcs_array_len *
835 sizeof(uint32_t);
836 ac->success_mcs = tx_succ_mcs;
837 ac->fail_mcs = tx_fail_mcs;
838 ac->fail_mcs_len = tx_fail_mcs_array_len *
839 sizeof(uint32_t);
840 ac->delay = tx_delay;
841 ac->delay_len = tx_delay_array_len *
842 sizeof(uint32_t);
843 peer_stats->ac_stats[k].tx_stats = ac;
844 peer_stats->ac_stats[k].type = k;
845 tx_mpdu_aggr += tx_mpdu_aggr_array_len;
846 tx_succ_mcs += tx_succ_mcs_array_len;
847 tx_fail_mcs += tx_fail_mcs_array_len;
848 tx_delay += tx_delay_array_len;
849 }
850 result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
851 } else {
852 /*
853 * Buffer for Peer TX counter overflow.
854 * There is peer ID mismatch between TX, RX,
855 * signal counters.
856 */
857 WMA_LOGE(FL("One peer TX info is dropped."));
858
859 tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
860 tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
861 tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
862 tx_delay += tx_delay_array_len * WLAN_MAX_AC;
863 }
864 }
865 *buf = result;
866 *buf_length = dst_len;
867}
868
869/**
870 * wma_fill_rx_stats() - Fix RX stats into result buffer
871 * @ll_stats: LL stats buffer
872 * @fix_param: parameters with fixed length in WMI event
873 * @param_buf: parameters without fixed length in WMI event
874 * @buf: buffer for TLV parameters
875 *
876 * Return: None
877 */
878static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
879 wmi_report_stats_event_fixed_param *fix_param,
880 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
881 uint8_t **buf, uint32_t *buf_length)
882{
883 uint8_t *result;
884 uint32_t i, j, k;
885 uint32_t *rx_mpdu_aggr, *rx_mcs;
886 wmi_rx_stats *wmi_rx;
887 wmi_peer_ac_rx_stats *wmi_peer_rx;
888 struct sir_wifi_rx *rx_stats;
889 struct sir_wifi_ll_ext_peer_stats *peer_stats;
890 uint32_t len, dst_len, rx_mpdu_aggr_array_len, rx_mcs_array_len;
891
892 rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
893 ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
894 rx_mcs_array_len = fix_param->rx_mcs_array_len;
895 ll_stats->rx_mcs_array_len = rx_mcs_array_len;
896 wmi_peer_rx = param_buf->peer_ac_rx_stats;
897 wmi_rx = param_buf->rx_stats;
898
899 result = *buf;
900 dst_len = *buf_length;
901 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
902 WLAN_MAX_AC * rx_mpdu_aggr_array_len);
903 if (len <= dst_len) {
904 rx_mpdu_aggr = (uint32_t *)result;
905 qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
906 result += len;
907 dst_len -= len;
908 } else {
909 WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong."));
910 rx_mpdu_aggr = NULL;
911 }
912
913 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
914 WLAN_MAX_AC * rx_mcs_array_len);
915 if (len <= dst_len) {
916 rx_mcs = (uint32_t *)result;
917 qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len);
918 result += len;
919 dst_len -= len;
920 } else {
921 WMA_LOGE(FL("RX_MCS array length is wrong."));
922 rx_mcs = NULL;
923 }
924
925 /* per peer rx stats */
926 peer_stats = ll_stats->peer_stats;
927 for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) {
928 uint32_t peer_id = wmi_peer_rx[i].peer_id;
929 struct sir_wifi_rx *ac;
930 wmi_rx_stats *wmi_rx_stats;
931
932 for (j = 0; j < ll_stats->peer_num; j++) {
933 peer_stats += j;
934 if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
935 (peer_stats->peer_id == peer_id))
936 break;
937 }
938
939 if (j < ll_stats->peer_num) {
940 peer_stats->peer_id = wmi_peer_rx[i].peer_id;
941 peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
942 peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
943 peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
944 peer_stats->rx_probe_reqs =
945 wmi_peer_rx[i].rx_probe_reqs;
946 peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
947 rx_stats = (struct sir_wifi_rx *)result;
948
949 for (k = 0; k < WLAN_MAX_AC; k++) {
950 wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
951 ac = &rx_stats[k];
952 WMA_FILL_RX_STATS(wmi_rx_stats, ac);
953 ac->mpdu_aggr = rx_mpdu_aggr;
954 ac->aggr_len = rx_mpdu_aggr_array_len *
955 sizeof(uint32_t);
956 ac->mcs = rx_mcs;
957 ac->mcs_len = rx_mcs_array_len *
958 sizeof(uint32_t);
959 peer_stats->ac_stats[k].rx_stats = ac;
960 peer_stats->ac_stats[k].type = k;
961 rx_mpdu_aggr += rx_mpdu_aggr_array_len;
962 rx_mcs += rx_mcs_array_len;
963 }
964 result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
965 } else {
966 /*
967 * Buffer for Peer RX counter overflow.
968 * There is peer ID mismatch between TX, RX,
969 * signal counters.
970 */
971 WMA_LOGE(FL("One peer RX info is dropped."));
972 rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
973 rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
974 }
975 }
976 *buf = result;
977 *buf_length = dst_len;
978}
979
980/**
981 * wma_ll_stats_evt_handler() - handler for MAC layer counters.
982 * @handle - wma handle
983 * @event - FW event
984 * @len - length of FW event
985 *
986 * return: 0 success.
987 */
988static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
989 u_int32_t len)
990{
991 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
992 wmi_report_stats_event_fixed_param *fixed_param;
993 tSirLLStatsResults *link_stats_results;
994 wmi_chan_cca_stats *wmi_cca_stats;
995 wmi_peer_signal_stats *wmi_peer_signal;
996 wmi_peer_ac_rx_stats *wmi_peer_rx;
997 struct sir_wifi_ll_ext_stats *ll_stats;
998 struct sir_wifi_ll_ext_peer_stats *peer_stats;
999 struct sir_wifi_chan_cca_stats *cca_stats;
1000 struct sir_wifi_peer_signal_stats *peer_signal;
1001 uint8_t *result;
1002 uint32_t i, peer_num, result_size, dst_len;
1003 tpAniSirGlobal mac;
1004 struct scheduler_msg sme_msg = { 0 };
1005 QDF_STATUS qdf_status;
1006
1007 mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
1008 if (!mac) {
1009 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1010 return -EINVAL;
1011 }
1012
1013 if (!mac->sme.link_layer_stats_ext_cb) {
1014 WMA_LOGD("%s: HDD callback is null", __func__);
1015 return -EINVAL;
1016 }
1017
1018 WMA_LOGD("%s: Posting MAC counters event to HDD", __func__);
1019
1020 param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
1021 fixed_param = param_buf->fixed_param;
1022 wmi_cca_stats = param_buf->chan_cca_stats;
1023 wmi_peer_signal = param_buf->peer_signal_stats;
1024 wmi_peer_rx = param_buf->peer_ac_rx_stats;
1025
1026 /* Get the MAX of three peer numbers */
1027 peer_num = fixed_param->num_peer_signal_stats >
1028 fixed_param->num_peer_ac_tx_stats ?
1029 fixed_param->num_peer_signal_stats :
1030 fixed_param->num_peer_ac_tx_stats;
1031 peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
1032 peer_num : fixed_param->num_peer_ac_rx_stats;
1033
1034 if (peer_num == 0)
1035 return -EINVAL;
1036
1037 link_stats_results = wma_get_ll_stats_ext_buf(&result_size,
1038 peer_num,
1039 fixed_param);
1040 if (!link_stats_results) {
1041 WMA_LOGE("%s: Fail to allocate stats buffer", __func__);
1042 return -EINVAL;
1043 }
1044 link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
1045 link_stats_results->num_peers = peer_num;
1046 link_stats_results->peer_event_number = 1;
1047 link_stats_results->moreResultToFollow = 0;
1048
1049 ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
1050 ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
1051 ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
1052 ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
1053 ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
1054 ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
1055 ll_stats->channel_num = fixed_param->num_chan_cca_stats;
1056 ll_stats->peer_num = peer_num;
1057
1058 result = (uint8_t *)ll_stats->stats;
1059 peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
1060 ll_stats->peer_stats = peer_stats;
1061
1062 for (i = 0; i < peer_num; i++) {
1063 peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
1064 peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
1065 }
1066
1067 /* Per peer signal */
1068 result_size -= sizeof(struct sir_wifi_ll_ext_stats);
1069 dst_len = sizeof(struct sir_wifi_peer_signal_stats);
1070 for (i = 0; i < fixed_param->num_peer_signal_stats; i++) {
1071 peer_stats[i].peer_id = wmi_peer_signal->peer_id;
1072 peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
1073 peer_signal = &peer_stats[i].peer_signal_stats;
1074
Zhang Qian303ebe92017-05-18 13:59:07 +08001075 WMA_LOGD("%d antennas for peer %d",
1076 wmi_peer_signal->num_chains_valid,
1077 wmi_peer_signal->peer_id);
Zhang Qian73c348a2017-03-13 16:15:55 +08001078 if (dst_len <= result_size) {
Zhang Qian303ebe92017-05-18 13:59:07 +08001079 peer_signal->vdev_id = wmi_peer_signal->vdev_id;
1080 peer_signal->peer_id = wmi_peer_signal->peer_id;
1081 peer_signal->num_chain =
1082 wmi_peer_signal->num_chains_valid;
1083 qdf_mem_copy(peer_signal->per_ant_snr,
1084 wmi_peer_signal->per_chain_snr,
1085 sizeof(peer_signal->per_ant_snr));
1086 qdf_mem_copy(peer_signal->nf,
1087 wmi_peer_signal->per_chain_nf,
1088 sizeof(peer_signal->nf));
1089 qdf_mem_copy(peer_signal->per_ant_rx_mpdus,
1090 wmi_peer_signal->per_antenna_rx_mpdus,
1091 sizeof(peer_signal->per_ant_rx_mpdus));
1092 qdf_mem_copy(peer_signal->per_ant_tx_mpdus,
1093 wmi_peer_signal->per_antenna_tx_mpdus,
1094 sizeof(peer_signal->per_ant_tx_mpdus));
Zhang Qian73c348a2017-03-13 16:15:55 +08001095 result_size -= dst_len;
1096 } else {
1097 WMA_LOGE(FL("Invalid length of PEER signal."));
1098 }
1099 wmi_peer_signal++;
1100 }
1101
1102 result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
1103 cca_stats = (struct sir_wifi_chan_cca_stats *)result;
1104 ll_stats->cca = cca_stats;
1105 dst_len = sizeof(struct sir_wifi_chan_cca_stats);
1106 for (i = 0; i < ll_stats->channel_num; i++) {
1107 if (dst_len <= result_size) {
1108 qdf_mem_copy(&cca_stats[i], &wmi_cca_stats->vdev_id,
1109 dst_len);
1110 result_size -= dst_len;
1111 } else {
1112 WMA_LOGE(FL("Invalid length of CCA."));
1113 }
1114 }
1115
1116 result += i * sizeof(struct sir_wifi_chan_cca_stats);
1117 wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
1118 &result, &result_size);
1119 wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
1120 &result, &result_size);
1121 sme_msg.type = eWMI_SME_LL_STATS_IND;
1122 sme_msg.bodyptr = (void *)link_stats_results;
1123 sme_msg.bodyval = 0;
1124 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1125 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1126 WMA_LOGP(FL("Failed to post peer stat change msg!"));
1127 qdf_mem_free(link_stats_results);
1128 return -EINVAL;
1129 }
1130
1131 return 0;
1132}
1133
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134/**
1135 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
1136 * @handle: wma handle
1137 * @cmd_param_info: data received with event from fw
1138 * @len: length of data
1139 *
1140 * Return: 0 for success or error code
1141 */
1142static int wma_unified_link_peer_stats_event_handler(void *handle,
1143 uint8_t *cmd_param_info,
1144 uint32_t len)
1145{
1146 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1147 wmi_peer_stats_event_fixed_param *fixed_param;
1148 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
1149 wmi_rate_stats *rate_stats;
1150 tSirLLStatsResults *link_stats_results;
1151 uint8_t *results, *t_peer_stats, *t_rate_stats;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301152 uint32_t count, num_rates = 0, rate_cnt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
1154 size_t peer_info_size, peer_stats_size, rate_stats_size;
1155 size_t link_stats_results_size;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001156 bool excess_data = false;
1157 uint32_t buf_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158
Anurag Chouhan6d760662016-02-20 16:05:43 +05301159 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160
1161 if (!pMac) {
1162 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1163 return -EINVAL;
1164 }
1165
1166 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1167 WMA_LOGD("%s: HDD callback is null", __func__);
1168 return -EINVAL;
1169 }
1170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1172 if (!param_tlvs) {
1173 WMA_LOGA("%s: Invalid stats event", __func__);
1174 return -EINVAL;
1175 }
1176 /*
1177 * cmd_param_info contains
1178 * wmi_peer_stats_event_fixed_param fixed_param;
1179 * num_peers * size of(struct wmi_peer_link_stats)
1180 * num_rates * size of(struct wmi_rate_stats)
1181 * num_rates is the sum of the rates of all the peers.
1182 */
1183 fixed_param = param_tlvs->fixed_param;
1184 peer_stats = param_tlvs->peer_stats;
1185 rate_stats = param_tlvs->peer_rate_stats;
1186
1187 if (!fixed_param || !peer_stats ||
1188 (peer_stats->num_rates && !rate_stats)) {
1189 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
1190 return -EINVAL;
1191 }
1192
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001193 do {
1194 if (peer_stats->num_rates >
1195 WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_rate_stats)) {
1196 excess_data = true;
1197 break;
1198 } else {
1199 buf_len =
1200 peer_stats->num_rates * sizeof(wmi_rate_stats);
1201 }
1202 if (fixed_param->num_peers >
1203 WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats)) {
1204 excess_data = true;
1205 break;
1206 } else {
1207 buf_len += fixed_param->num_peers *
1208 sizeof(wmi_peer_link_stats);
1209 }
1210 } while (0);
1211
1212 if (excess_data ||
1213 (sizeof(*fixed_param) > WMI_SVC_MSG_MAX_SIZE - buf_len)) {
1214 WMA_LOGE("excess wmi buffer: rates:%d, peers:%d",
1215 peer_stats->num_rates, fixed_param->num_peers);
1216 QDF_ASSERT(0);
1217 return -EINVAL;
1218 }
1219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001220 /*
1221 * num_rates - sum of the rates of all the peers
1222 */
1223 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
1224 for (count = 0; count < fixed_param->num_peers; count++) {
1225 num_rates += temp_peer_stats->num_rates;
1226 temp_peer_stats++;
1227 }
1228
1229 peer_stats_size = sizeof(tSirWifiPeerStat);
1230 peer_info_size = sizeof(tSirWifiPeerInfo);
1231 rate_stats_size = sizeof(tSirWifiRateStat);
1232 link_stats_results_size =
1233 sizeof(*link_stats_results) + peer_stats_size +
1234 (fixed_param->num_peers * peer_info_size) +
1235 (num_rates * rate_stats_size);
1236
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301237 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 if (NULL == link_stats_results) {
1239 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1240 __func__, link_stats_results_size);
1241 return -ENOMEM;
1242 }
1243
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245
1246 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
1247 link_stats_results->rspId = fixed_param->request_id;
1248 link_stats_results->ifaceId = 0;
1249 link_stats_results->num_peers = fixed_param->num_peers;
1250 link_stats_results->peer_event_number = fixed_param->peer_event_number;
1251 link_stats_results->moreResultToFollow = fixed_param->more_data;
1252
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301253 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 &fixed_param->num_peers, peer_stats_size);
1255
1256 results = (uint8_t *) link_stats_results->results;
1257 t_peer_stats = (uint8_t *) peer_stats;
1258 t_rate_stats = (uint8_t *) rate_stats;
1259 next_res_offset = peer_stats_size;
1260 next_peer_offset = WMI_TLV_HDR_SIZE;
1261 next_rate_offset = WMI_TLV_HDR_SIZE;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301262 for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301263 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 t_peer_stats + next_peer_offset, peer_info_size);
1265 next_res_offset += peer_info_size;
1266
1267 /* Copy rate stats associated with this peer */
1268 for (count = 0; count < peer_stats->num_rates; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269 rate_stats++;
1270
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301271 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272 t_rate_stats + next_rate_offset,
1273 rate_stats_size);
1274 next_res_offset += rate_stats_size;
1275 next_rate_offset += sizeof(*rate_stats);
1276 }
1277 next_peer_offset += sizeof(*peer_stats);
1278 peer_stats++;
1279 }
1280
1281 /* call hdd callback with Link Layer Statistics
1282 * vdev_id/ifacId in link_stats_results will be
1283 * used to retrieve the correct HDD context
1284 */
1285 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1286 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1287 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301288 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289
1290 return 0;
1291}
1292
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001293/**
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001294 * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
1295 * @handle: WMI handle
1296 *
1297 * Return: 0 on success, error number otherwise.
1298 */
yeshwanth sriram guntuka584c2332017-07-29 12:50:25 +05301299int wma_unified_radio_tx_mem_free(void *handle)
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001300{
1301 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1302 tSirWifiRadioStat *rs_results;
1303 uint32_t i = 0;
1304
1305 if (!wma_handle->link_stats_results)
1306 return 0;
1307
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001308 rs_results = (tSirWifiRadioStat *)
1309 &wma_handle->link_stats_results->results[0];
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001310 for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
1311 rs_results += i;
1312 if (rs_results->tx_time_per_power_level) {
1313 qdf_mem_free(rs_results->tx_time_per_power_level);
1314 rs_results->tx_time_per_power_level = NULL;
1315 }
1316
1317 if (rs_results->channels) {
1318 qdf_mem_free(rs_results->channels);
1319 rs_results->channels = NULL;
1320 }
1321 }
1322
1323 qdf_mem_free(wma_handle->link_stats_results);
1324 wma_handle->link_stats_results = NULL;
1325
1326 return 0;
1327}
1328
1329/**
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001330 * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
1331 * @handle: WMI handle
1332 * @cmd_param_info: command param info
1333 * @len: Length of @cmd_param_info
1334 *
1335 * This is the WMI event handler function to receive radio stats tx
1336 * power level stats.
1337 *
1338 * Return: 0 on success, error number otherwise.
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001339 */
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001340static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
1341 u_int8_t *cmd_param_info, u_int32_t len)
1342{
1343 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1344 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
1345 wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
1346 uint8_t *tx_power_level_values;
1347 tSirLLStatsResults *link_stats_results;
1348 tSirWifiRadioStat *rs_results;
1349
1350 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1351
1352 if (!mac) {
1353 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1354 return -EINVAL;
1355 }
1356
1357 if (!mac->sme.pLinkLayerStatsIndCallback) {
1358 WMA_LOGD("%s: HDD callback is null", __func__);
1359 return -EINVAL;
1360 }
1361
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001362 param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)
1363 cmd_param_info;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001364 if (!param_tlvs) {
1365 WMA_LOGA("%s: Invalid tx power level stats event", __func__);
1366 return -EINVAL;
1367 }
1368
1369 fixed_param = param_tlvs->fixed_param;
1370 if (!fixed_param) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001371 WMA_LOGA("%s:Invalid param_tlvs for Radio tx_power level Stats",
1372 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001373 return -EINVAL;
1374 }
1375
1376 link_stats_results = wma_handle->link_stats_results;
Srinivas Girigowda52cbce42016-10-25 14:11:58 -07001377 if (!link_stats_results) {
1378 WMA_LOGA("%s: link_stats_results is NULL", __func__);
1379 return -EINVAL;
1380 }
1381
Wu Gao478282a2017-09-19 15:45:29 +08001382 if (fixed_param->radio_id >= link_stats_results->num_radio) {
1383 WMA_LOGE("%s, invalid radio id:%d, num radio:%d",
1384 __func__, fixed_param->radio_id,
1385 link_stats_results->num_radio);
1386 return -EINVAL;
1387 }
1388
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001389 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 -07001390 __func__, fixed_param->total_num_tx_power_levels,
1391 fixed_param->num_tx_power_levels,
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001392 fixed_param->power_level_offset,
1393 fixed_param->radio_id);
1394
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001395 if (fixed_param->num_tx_power_levels > ((WMI_SVC_MSG_MAX_SIZE -
1396 sizeof(*fixed_param)) / sizeof(uint32_t))) {
1397 WMA_LOGE("%s: excess tx_power buffers:%d", __func__,
1398 fixed_param->num_tx_power_levels);
1399 QDF_ASSERT(0);
1400 return -EINVAL;
1401 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001402 rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] +
1403 fixed_param->radio_id;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001404 tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001405
1406 rs_results->total_num_tx_power_levels =
1407 fixed_param->total_num_tx_power_levels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001408 if (!rs_results->total_num_tx_power_levels) {
1409 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001410 goto post_stats;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001411 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001412
1413 if (!rs_results->tx_time_per_power_level) {
1414 rs_results->tx_time_per_power_level = qdf_mem_malloc(
1415 sizeof(uint32_t) *
1416 rs_results->total_num_tx_power_levels);
1417 if (!rs_results->tx_time_per_power_level) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001418 WMA_LOGA("%s: Mem alloc fail for tx power level stats",
1419 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001420 /* In error case, atleast send the radio stats without
1421 * tx_power_level stats */
1422 rs_results->total_num_tx_power_levels = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001423 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001424 goto post_stats;
1425 }
1426 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001427 qdf_mem_copy(&rs_results->tx_time_per_power_level[
1428 fixed_param->power_level_offset],
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001429 tx_power_level_values,
1430 sizeof(uint32_t) * fixed_param->num_tx_power_levels);
1431 if (rs_results->total_num_tx_power_levels ==
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001432 (fixed_param->num_tx_power_levels +
1433 fixed_param->power_level_offset)) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001434 link_stats_results->moreResultToFollow = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001435 link_stats_results->nr_received++;
1436 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001437
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001438 WMA_LOGD("%s: moreResultToFollow: %u nr: %u nr_received: %u",
1439 __func__, link_stats_results->moreResultToFollow,
1440 link_stats_results->num_radio,
1441 link_stats_results->nr_received);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001442
1443 /* If still data to receive, return from here */
1444 if (link_stats_results->moreResultToFollow)
1445 return 0;
1446
1447post_stats:
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001448 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1449 /* Not received all radio stats yet, don't post yet */
1450 return 0;
1451 }
1452
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001453 /* call hdd callback with Link Layer Statistics
1454 * vdev_id/ifacId in link_stats_results will be
1455 * used to retrieve the correct HDD context
1456 */
1457 mac->sme.pLinkLayerStatsIndCallback(mac->hHdd,
1458 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1459 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001460 wma_unified_radio_tx_mem_free(handle);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001461
1462 return 0;
1463}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001464
1465/**
1466 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
1467 * @handle: wma handle
1468 * @cmd_param_info: data received with event from fw
1469 * @len: length of data
1470 *
1471 * Return: 0 for success or error code
1472 */
1473static int wma_unified_link_radio_stats_event_handler(void *handle,
1474 uint8_t *cmd_param_info,
1475 uint32_t len)
1476{
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001477 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1479 wmi_radio_link_stats_event_fixed_param *fixed_param;
1480 wmi_radio_link_stats *radio_stats;
1481 wmi_channel_stats *channel_stats;
1482 tSirLLStatsResults *link_stats_results;
1483 uint8_t *results, *t_radio_stats, *t_channel_stats;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001484 uint32_t next_chan_offset, count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001485 size_t radio_stats_size, chan_stats_size;
1486 size_t link_stats_results_size;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001487 tSirWifiRadioStat *rs_results;
1488 tSirWifiChannelStats *chn_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489
Anurag Chouhan6d760662016-02-20 16:05:43 +05301490 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491
1492 if (!pMac) {
1493 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1494 return -EINVAL;
1495 }
1496
1497 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1498 WMA_LOGD("%s: HDD callback is null", __func__);
1499 return -EINVAL;
1500 }
1501
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1503 if (!param_tlvs) {
1504 WMA_LOGA("%s: Invalid stats event", __func__);
1505 return -EINVAL;
1506 }
1507
1508 /*
1509 * cmd_param_info contains
1510 * wmi_radio_link_stats_event_fixed_param fixed_param;
1511 * size of(struct wmi_radio_link_stats);
1512 * num_channels * size of(struct wmi_channel_stats)
1513 */
1514 fixed_param = param_tlvs->fixed_param;
1515 radio_stats = param_tlvs->radio_stats;
1516 channel_stats = param_tlvs->channel_stats;
1517
1518 if (!fixed_param || !radio_stats ||
1519 (radio_stats->num_channels && !channel_stats)) {
1520 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
1521 return -EINVAL;
1522 }
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001523 if (radio_stats->num_channels >
1524 (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS)) {
1525 WMA_LOGE("%s: Too many channels %d",
1526 __func__, radio_stats->num_channels);
1527 return -EINVAL;
1528 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529
1530 radio_stats_size = sizeof(tSirWifiRadioStat);
1531 chan_stats_size = sizeof(tSirWifiChannelStats);
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001532 if (fixed_param->num_radio >
1533 (UINT_MAX - sizeof(*link_stats_results))/radio_stats_size) {
1534 WMA_LOGE("excess num_radio %d is leading to int overflow",
1535 fixed_param->num_radio);
1536 return -EINVAL;
1537 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 link_stats_results_size = sizeof(*link_stats_results) +
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001539 fixed_param->num_radio * radio_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001541 if (!wma_handle->link_stats_results) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001542 wma_handle->link_stats_results = qdf_mem_malloc(
1543 link_stats_results_size);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001544 if (NULL == wma_handle->link_stats_results) {
1545 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1546 __func__, link_stats_results_size);
1547 return -ENOMEM;
1548 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549 }
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001550 link_stats_results = wma_handle->link_stats_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001552 WMA_LOGD("Radio stats Fixed Param:");
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001553 WMA_LOGD("req_id: %u num_radio: %u more_radio_events: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554 fixed_param->request_id, fixed_param->num_radio,
1555 fixed_param->more_radio_events);
1556
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001557 WMA_LOGD("Radio Info: radio_id: %u on_time: %u tx_time: %u rx_time: %u on_time_scan: %u",
1558 radio_stats->radio_id, radio_stats->on_time,
1559 radio_stats->tx_time, radio_stats->rx_time,
1560 radio_stats->on_time_scan);
1561 WMA_LOGD("on_time_nbd: %u on_time_gscan: %u on_time_roam_scan: %u",
1562 radio_stats->on_time_nbd,
1563 radio_stats->on_time_gscan, radio_stats->on_time_roam_scan);
1564 WMA_LOGD("on_time_pno_scan: %u on_time_hs20: %u num_channels: %u",
1565 radio_stats->on_time_pno_scan, radio_stats->on_time_hs20,
1566 radio_stats->num_channels);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001567 WMA_LOGD("on_time_host_scan: %u, on_time_lpi_scan: %u",
1568 radio_stats->on_time_host_scan, radio_stats->on_time_lpi_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001570 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
1571 link_stats_results->rspId = fixed_param->request_id;
1572 link_stats_results->ifaceId = 0;
1573 link_stats_results->num_radio = fixed_param->num_radio;
1574 link_stats_results->peer_event_number = 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001575
1576 /*
1577 * Backward compatibility:
1578 * There are firmware(s) which will send Radio stats only with
1579 * more_radio_events set to 0 and firmware which sends Radio stats
1580 * followed by tx_power level stats with more_radio_events set to 1.
1581 * if more_radio_events is set to 1, buffer the radio stats and
1582 * wait for tx_power_level stats.
1583 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
1585
1586 results = (uint8_t *) link_stats_results->results;
1587 t_radio_stats = (uint8_t *) radio_stats;
1588 t_channel_stats = (uint8_t *) channel_stats;
1589
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001590 rs_results = (tSirWifiRadioStat *) &results[0] + radio_stats->radio_id;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001591 rs_results->radio = radio_stats->radio_id;
1592 rs_results->onTime = radio_stats->on_time;
1593 rs_results->txTime = radio_stats->tx_time;
1594 rs_results->rxTime = radio_stats->rx_time;
1595 rs_results->onTimeScan = radio_stats->on_time_scan;
1596 rs_results->onTimeNbd = radio_stats->on_time_nbd;
1597 rs_results->onTimeGscan = radio_stats->on_time_gscan;
1598 rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
1599 rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
1600 rs_results->onTimeHs20 = radio_stats->on_time_hs20;
1601 rs_results->total_num_tx_power_levels = 0;
1602 rs_results->tx_time_per_power_level = NULL;
1603 rs_results->numChannels = radio_stats->num_channels;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001604 rs_results->on_time_host_scan = radio_stats->on_time_host_scan;
1605 rs_results->on_time_lpi_scan = radio_stats->on_time_lpi_scan;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001606 rs_results->channels = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001608 if (rs_results->numChannels) {
1609 rs_results->channels = (tSirWifiChannelStats *) qdf_mem_malloc(
1610 radio_stats->num_channels *
1611 chan_stats_size);
1612 if (rs_results->channels == NULL) {
1613 WMA_LOGD("%s: could not allocate mem for channel stats (size=%zu)",
1614 __func__, radio_stats->num_channels * chan_stats_size);
1615 wma_unified_radio_tx_mem_free(handle);
1616 return -ENOMEM;
1617 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001618
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001619 chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
1620 next_chan_offset = WMI_TLV_HDR_SIZE;
1621 WMA_LOGD("Channel Stats Info");
1622 for (count = 0; count < radio_stats->num_channels; count++) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001623 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001624 channel_stats->channel_width,
1625 channel_stats->center_freq,
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001626 channel_stats->center_freq0);
1627 WMA_LOGD("center_freq1 %u radio_awake_time %u cca_busy_time %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001628 channel_stats->center_freq1,
1629 channel_stats->radio_awake_time,
1630 channel_stats->cca_busy_time);
1631 channel_stats++;
1632
1633 qdf_mem_copy(chn_results,
1634 t_channel_stats + next_chan_offset,
1635 chan_stats_size);
1636 chn_results++;
1637 next_chan_offset += sizeof(*channel_stats);
1638 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639 }
1640
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001641 if (link_stats_results->moreResultToFollow) {
1642 /* More results coming, don't post yet */
1643 return 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001644 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001645 link_stats_results->nr_received++;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001646
1647 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1648 /* Not received all radio stats yet, don't post yet */
1649 return 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001650 }
1651
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001652 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1653 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1654 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001655 wma_unified_radio_tx_mem_free(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656
1657 return 0;
1658}
1659
Zhang Qiana6e9c102016-12-22 16:47:24 +08001660#ifdef WLAN_PEER_PS_NOTIFICATION
1661/**
1662 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1663 * @handle: wma handle
1664 * @event: FW event
1665 * @len: length of FW event
1666 *
1667 * Once peer STA power state changes, an event will be indicated by
1668 * FW. This function send a link layer state change msg to HDD. HDD
1669 * link layer callback will converts the event to NL msg.
1670 *
1671 * Return: 0 Success. Others fail.
1672 */
1673static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1674 u_int32_t len)
1675{
1676 WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *param_buf;
1677 wmi_peer_sta_ps_statechange_event_fixed_param *fixed_param;
1678 tSirWifiPeerStat *peer_stat;
1679 tSirWifiPeerInfo *peer_info;
1680 tSirLLStatsResults *link_stats_results;
1681 tSirMacAddr mac_address;
1682 uint32_t result_len;
1683 cds_msg_t sme_msg = { 0 };
1684 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1685
1686 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1687
1688 if (!mac) {
1689 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1690 return -EINVAL;
1691 }
1692
1693 if (!mac->sme.link_layer_stats_ext_cb) {
1694 WMA_LOGD("%s: HDD callback is null", __func__);
1695 return -EINVAL;
1696 }
1697
1698 WMA_LOGD("%s: Posting Peer Stats PS event to HDD", __func__);
1699
1700 param_buf = (WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *)event;
1701 fixed_param = param_buf->fixed_param;
1702
1703 result_len = sizeof(tSirLLStatsResults) +
1704 sizeof(tSirWifiPeerStat) +
1705 sizeof(tSirWifiPeerInfo);
1706 link_stats_results = qdf_mem_malloc(result_len);
1707 if (link_stats_results == NULL) {
1708 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1709 return -EINVAL;
1710 }
1711
1712 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->peer_macaddr, &mac_address[0]);
1713 WMA_LOGD("Peer power state change event from FW");
1714 WMA_LOGD("Fixed Param:");
1715 WMA_LOGD("MAC address: %2x:%2x:%2x:%2x:%2x:%2x, Power state: %d",
1716 mac_address[0], mac_address[1], mac_address[2],
1717 mac_address[3], mac_address[4], mac_address[5],
1718 fixed_param->peer_ps_state);
1719
1720 link_stats_results->paramId = WMI_LL_STATS_EXT_PS_CHG;
1721 link_stats_results->num_peers = 1;
1722 link_stats_results->peer_event_number = 1;
1723 link_stats_results->moreResultToFollow = 0;
1724
1725 peer_stat = (tSirWifiPeerStat *)link_stats_results->results;
1726 peer_stat->numPeers = 1;
1727 peer_info = (tSirWifiPeerInfo *)peer_stat->peerInfo;
1728 qdf_mem_copy(&peer_info->peerMacAddress,
1729 &mac_address,
1730 sizeof(tSirMacAddr));
1731 peer_info->power_saving = fixed_param->peer_ps_state;
1732
1733 sme_msg.type = eWMI_SME_LL_STATS_IND;
1734 sme_msg.bodyptr = link_stats_results;
1735 sme_msg.bodyval = 0;
1736
Zhang Qian73c348a2017-03-13 16:15:55 +08001737 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001738 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1739 WMA_LOGE("%s: Fail to post ps change ind msg", __func__);
1740 qdf_mem_free(link_stats_results);
1741 }
1742
1743 return 0;
1744}
1745#else
1746/**
1747 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1748 * @handle: wma handle
1749 * @event: FW event
1750 * @len: length of FW event
1751 *
1752 * Once peer STA power state changes, an event will be indicated by
1753 * FW. This function send a link layer state change msg to HDD. HDD
1754 * link layer callback will converts the event to NL msg.
1755 *
1756 * Return: 0 Success. Others fail.
1757 */
1758static inline int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1759 u_int32_t len)
1760{
1761 return 0;
1762}
1763#endif
1764
1765/**
1766 * wma_tx_failure_cb() - TX failure callback
1767 * @ctx: txrx context
1768 * @num_msdu: number of msdu with the same status
1769 * @tid: TID number
1770 * @status: failure status
1771 */
1772void wma_tx_failure_cb(void *ctx, uint32_t num_msdu,
1773 uint8_t tid, enum htt_tx_status status)
1774{
1775 tSirLLStatsResults *results;
1776 struct sir_wifi_iface_tx_fail *tx_fail;
1777 struct scheduler_msg sme_msg = { 0 };
1778 QDF_STATUS qdf_status;
1779 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1780
1781 if (!mac) {
1782 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1783 return;
1784 }
1785
1786 if (!mac->sme.link_layer_stats_ext_cb) {
1787 WMA_LOGD("%s: HDD callback is null", __func__);
1788 return;
1789 }
1790
1791 results = qdf_mem_malloc(sizeof(tSirLLStatsResults) +
1792 sizeof(struct sir_wifi_iface_tx_fail));
1793 if (results == NULL) {
1794 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1795 return;
1796 }
1797
1798 results->paramId = WMI_LL_STATS_EXT_TX_FAIL;
1799 results->num_peers = 1;
1800 results->peer_event_number = 1;
1801 results->moreResultToFollow = 0;
1802
1803 tx_fail = (struct sir_wifi_iface_tx_fail *)results->results;
1804 tx_fail->tid = tid;
1805 tx_fail->msdu_num = num_msdu;
1806 tx_fail->status = status;
1807
1808 sme_msg.type = eWMI_SME_LL_STATS_IND;
1809 sme_msg.bodyptr = results;
1810 sme_msg.bodyval = 0;
1811
1812 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1813 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1814 WMA_LOGE("%s: Fail to post TX failure ind msg", __func__);
1815 qdf_mem_free(results);
1816 }
1817}
1818
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819/**
1820 * wma_register_ll_stats_event_handler() - register link layer stats related
1821 * event handler
1822 * @wma_handle: wma handle
1823 *
1824 * Return: none
1825 */
1826void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
1827{
1828 if (NULL == wma_handle) {
1829 WMA_LOGE("%s: wma_handle is NULL", __func__);
1830 return;
1831 }
1832
1833 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301834 WMI_IFACE_LINK_STATS_EVENTID,
1835 wma_unified_link_iface_stats_event_handler,
1836 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001837 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301838 WMI_PEER_LINK_STATS_EVENTID,
1839 wma_unified_link_peer_stats_event_handler,
1840 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001841 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301842 WMI_RADIO_LINK_STATS_EVENTID,
1843 wma_unified_link_radio_stats_event_handler,
1844 WMA_RX_SERIALIZER_CTX);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001845 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1846 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID,
1847 wma_unified_radio_tx_power_level_stats_event_handler,
1848 WMA_RX_SERIALIZER_CTX);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001849 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1850 WMI_PEER_STA_PS_STATECHG_EVENTID,
1851 wma_peer_ps_evt_handler,
1852 WMA_RX_SERIALIZER_CTX);
Zhang Qian73c348a2017-03-13 16:15:55 +08001853 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1854 WMI_REPORT_STATS_EVENTID,
1855 wma_ll_stats_evt_handler,
1856 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858}
1859
1860
1861/**
1862 * wma_process_ll_stats_clear_req() - clear link layer stats
1863 * @wma: wma handle
1864 * @clearReq: ll stats clear request command params
1865 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301866 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001868QDF_STATUS wma_process_ll_stats_clear_req(tp_wma_handle wma,
1869 const tpSirLLStatsClearReq clearReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870{
Govind Singh4863da42016-03-08 11:45:00 +05301871 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001872 int ret;
1873
1874 if (!clearReq || !wma) {
1875 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301876 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877 }
1878
Deepak Dhamdhere6adc08e2017-07-27 09:33:22 -07001879 if (!wma->interfaces[clearReq->staId].handle) {
1880 WMA_LOGE("%s: vdev_id %d handle is NULL",
1881 __func__, clearReq->staId);
1882 return QDF_STATUS_E_FAILURE;
1883 }
1884
Govind Singh4863da42016-03-08 11:45:00 +05301885 cmd.stop_req = clearReq->stopReq;
1886 cmd.sta_id = clearReq->staId;
1887 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888
Govind Singh4863da42016-03-08 11:45:00 +05301889 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
1890 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 if (ret) {
1892 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301893 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 }
1895
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301896 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897}
1898
1899/**
1900 * wma_process_ll_stats_set_req() - link layer stats set request
1901 * @wma: wma handle
1902 * @setReq: ll stats set request command params
1903 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301904 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001906QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma,
1907 const tpSirLLStatsSetReq setReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908{
Govind Singh4863da42016-03-08 11:45:00 +05301909 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910 int ret;
1911
1912 if (!setReq || !wma) {
1913 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301914 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001915 }
1916
Govind Singh4863da42016-03-08 11:45:00 +05301917 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
1918 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 setReq->aggressiveStatisticsGathering;
1920
Govind Singh4863da42016-03-08 11:45:00 +05301921 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
1922 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 if (ret) {
1924 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301925 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926 }
1927
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301928 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929}
1930
1931/**
1932 * wma_process_ll_stats_get_req() - link layer stats get request
1933 * @wma:wma handle
1934 * @getReq:ll stats get request command params
1935 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301936 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001938QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
1939 const tpSirLLStatsGetReq getReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940{
Govind Singh4863da42016-03-08 11:45:00 +05301941 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 int ret;
1943
1944 if (!getReq || !wma) {
1945 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301946 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 }
1948
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +05301949 if (!wma->interfaces[getReq->staId].vdev_active) {
1950 WMA_LOGE("%s: vdev not created yet", __func__);
1951 return QDF_STATUS_E_FAILURE;
1952 }
1953
Govind Singh4863da42016-03-08 11:45:00 +05301954 cmd.req_id = getReq->reqId;
1955 cmd.param_id_mask = getReq->paramIdMask;
1956 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957
Govind Singh4863da42016-03-08 11:45:00 +05301958 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
1959 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 if (ret) {
1961 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301962 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 }
1964
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301965 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966}
1967
1968/**
1969 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
1970 * @wma:wma handle
1971 * @cmd_param_info: data from event
1972 * @len: length
1973 *
1974 * Return: 0 for success or error code
1975 */
1976int wma_unified_link_iface_stats_event_handler(void *handle,
1977 uint8_t *cmd_param_info,
1978 uint32_t len)
1979{
1980 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1981 wmi_iface_link_stats_event_fixed_param *fixed_param;
1982 wmi_iface_link_stats *link_stats;
1983 wmi_wmm_ac_stats *ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001984 wmi_iface_offload_stats *offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 tSirLLStatsResults *link_stats_results;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001986 uint8_t *results, *t_link_stats, *t_ac_stats, *t_offload_stats;
1987 uint32_t next_res_offset, next_ac_offset, next_offload_offset, count;
1988 uint32_t roaming_offset, size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 size_t link_stats_size, ac_stats_size, iface_info_size;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001990 size_t link_stats_results_size, offload_stats_size;
1991 size_t total_ac_size, total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992
Anurag Chouhan6d760662016-02-20 16:05:43 +05301993 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994
1995 if (!pMac) {
1996 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1997 return -EINVAL;
1998 }
1999
2000 if (!pMac->sme.pLinkLayerStatsIndCallback) {
2001 WMA_LOGD("%s: HDD callback is null", __func__);
2002 return -EINVAL;
2003 }
2004
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
2006 if (!param_tlvs) {
2007 WMA_LOGA("%s: Invalid stats event", __func__);
2008 return -EINVAL;
2009 }
2010
2011 /*
2012 * cmd_param_info contains
2013 * wmi_iface_link_stats_event_fixed_param fixed_param;
2014 * wmi_iface_link_stats iface_link_stats;
2015 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002016 * fixed_param->num_offload_stats * size of(wmi_iface_offload_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 */
2018 fixed_param = param_tlvs->fixed_param;
2019 link_stats = param_tlvs->iface_link_stats;
2020 ac_stats = param_tlvs->ac;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002021 offload_stats = param_tlvs->iface_offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002023 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats) ||
2024 (fixed_param->num_offload_stats && !offload_stats)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
2026 return -EINVAL;
2027 }
2028
2029 link_stats_size = sizeof(tSirWifiIfaceStat);
2030 iface_info_size = sizeof(tSirWifiInterfaceInfo);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 ac_stats_size = sizeof(tSirWifiWmmAcStat);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002033 offload_stats_size = sizeof(struct wifi_iface_offload_stat);
2034
2035 total_ac_size = ac_stats_size * WIFI_AC_MAX;
2036 total_offload_size = offload_stats_size * WMI_OFFLOAD_STATS_TYPE_MAX +
2037 member_size(tSirWifiIfaceStat, num_offload_stats);
2038
2039 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302041 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 if (!link_stats_results) {
2043 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
2044 __func__, link_stats_results_size);
2045 return -ENOMEM;
2046 }
2047
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302048 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049
2050 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
2051 link_stats_results->rspId = fixed_param->request_id;
2052 link_stats_results->ifaceId = fixed_param->vdev_id;
2053 link_stats_results->num_peers = link_stats->num_peers;
2054 link_stats_results->peer_event_number = 0;
2055 link_stats_results->moreResultToFollow = 0;
2056
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002057 /* results is copied to tSirWifiIfaceStat in upper layer
2058 * tSirWifiIfaceStat
2059 * - tSirWifiInterfaceInfo (all fields except roaming is
2060 * filled by host in the upper layer)
2061 * - various members of tSirWifiIfaceStat (from wmi_iface_link_stats)
2062 * - ACs information (from wmi_wmm_ac_stats)
2063 * - num_offload_stats (from fixed param)
2064 * - offload stats (from wmi_iface_offload_stats)
2065 */
2066
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002067 results = (uint8_t *) link_stats_results->results;
2068 t_link_stats = (uint8_t *) link_stats;
2069 t_ac_stats = (uint8_t *) ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002070 t_offload_stats = (uint8_t *) offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071
2072 /* Copy roaming state */
2073 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002074 size = member_size(tSirWifiInterfaceInfo, roaming);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002076 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state, size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002078 next_res_offset = iface_info_size;
2079 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002080 t_link_stats + WMI_TLV_HDR_SIZE,
2081 link_stats_size - iface_info_size -
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002082 total_ac_size - total_offload_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002084 next_res_offset = link_stats_size - total_ac_size - total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 next_ac_offset = WMI_TLV_HDR_SIZE;
2086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 for (count = 0; count < link_stats->num_ac; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002088 ac_stats++;
2089
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302090 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002091 t_ac_stats + next_ac_offset, ac_stats_size);
2092 next_res_offset += ac_stats_size;
2093 next_ac_offset += sizeof(*ac_stats);
2094 }
2095
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002096 next_res_offset = link_stats_size - total_offload_size;
2097 /* copy num_offload_stats into result */
2098 size = member_size(tSirWifiIfaceStat, num_offload_stats);
2099 qdf_mem_copy(results + next_res_offset, &fixed_param->num_offload_stats,
2100 size);
2101
2102 next_res_offset += size;
2103 next_offload_offset = WMI_TLV_HDR_SIZE;
2104
2105 for (count = 0; count < fixed_param->num_offload_stats; count++) {
2106 qdf_mem_copy(results + next_res_offset,
2107 t_offload_stats + next_offload_offset,
2108 offload_stats_size);
2109 next_res_offset += offload_stats_size;
2110 next_offload_offset += sizeof(*offload_stats);
2111 }
2112
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002113 /* call hdd callback with Link Layer Statistics
2114 * vdev_id/ifacId in link_stats_results will be
2115 * used to retrieve the correct HDD context
2116 */
2117 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
2118 WMA_LINK_LAYER_STATS_RESULTS_RSP,
2119 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302120 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002121
2122 return 0;
2123}
2124
Zhang Qian73c348a2017-03-13 16:15:55 +08002125/**
2126 * wma_config_stats_ext_threshold - set threthold for MAC counters
2127 * @wma: wma handler
2128 * @threshold: threhold for MAC counters
2129 *
2130 * For each MAC layer counter, FW holds two copies. One is the current value.
2131 * The other is the last report. Once a current counter's increment is larger
2132 * than the threshold, FW will indicate that counter to host even if the
2133 * monitoring timer does not expire.
2134 *
2135 * Return: None
2136 */
2137void wma_config_stats_ext_threshold(tp_wma_handle wma,
2138 struct sir_ll_ext_stats_threshold *thresh)
2139{
2140 uint32_t len, tag, hdr_len;
2141 uint8_t *buf_ptr;
2142 wmi_buf_t buf;
2143 wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
2144 wmi_chan_cca_stats_thresh *cca;
2145 wmi_peer_signal_stats_thresh *signal;
2146 wmi_tx_stats_thresh *tx;
2147 wmi_rx_stats_thresh *rx;
2148
2149 if (!thresh) {
2150 WMA_LOGE(FL("Invalid threshold input."));
2151 return;
2152 }
2153
2154 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
2155 sizeof(wmi_chan_cca_stats_thresh) +
2156 sizeof(wmi_peer_signal_stats_thresh) +
2157 sizeof(wmi_tx_stats_thresh) +
2158 sizeof(wmi_rx_stats_thresh) +
2159 5 * WMI_TLV_HDR_SIZE;
2160 buf = wmi_buf_alloc(wma->wmi_handle, len);
2161 if (!buf) {
2162 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
2163 return;
2164 }
2165
2166 buf_ptr = (u_int8_t *)wmi_buf_data(buf);
2167 tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
2168 hdr_len = WMITLV_GET_STRUCT_TLVLEN(
2169 wmi_pdev_set_stats_threshold_cmd_fixed_param);
2170 WMA_LOGD(FL("Setting fixed parameters. tag=%d, len=%d"), tag, hdr_len);
2171 cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
2172 WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
2173 cmd->enable_thresh = thresh->enable;
2174 cmd->use_thresh_bitmap = thresh->enable_bitmap;
2175 cmd->gbl_thresh = thresh->global_threshold;
2176 cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
2177 cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
2178 cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
2179 cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
2180 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
2181
2182 tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
2183 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
2184 cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
2185 WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
2186 WMA_LOGD(FL("Setting cca parameters. tag=%d, len=%d"), tag, hdr_len);
2187 cca->idle_time = thresh->cca.idle_time;
2188 cca->tx_time = thresh->cca.tx_time;
2189 cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
2190 cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
2191 cca->rx_busy_time = thresh->cca.rx_busy_time;
2192 cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
2193 cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
2194 cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
2195 WMA_LOGD(FL("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d"),
2196 cca->idle_time, cca->tx_time,
2197 cca->rx_in_bss_time, cca->rx_out_bss_time);
2198 WMA_LOGD(FL("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d"),
2199 cca->rx_busy_time, cca->rx_in_bad_cond_time,
2200 cca->tx_in_bad_cond_time, cca->wlan_not_avail_time);
2201 len += sizeof(wmi_chan_cca_stats_thresh);
2202
2203 signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
2204 tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
2205 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
2206 WMA_LOGD(FL("Setting signal parameters. tag=%d, len=%d"), tag, hdr_len);
2207 WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
2208 signal->per_chain_snr = thresh->signal.snr;
2209 signal->per_chain_nf = thresh->signal.nf;
2210 WMA_LOGD(FL("snr=%d, nf=%d"), signal->per_chain_snr,
2211 signal->per_chain_nf);
2212 len += sizeof(wmi_peer_signal_stats_thresh);
2213
2214 tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
2215 tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
2216 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
2217 WMA_LOGD(FL("Setting TX parameters. tag=%d, len=%d"), tag, len);
2218 WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
2219 tx->tx_msdu_cnt = thresh->tx.msdu;
2220 tx->tx_mpdu_cnt = thresh->tx.mpdu;
2221 tx->tx_ppdu_cnt = thresh->tx.ppdu;
2222 tx->tx_bytes = thresh->tx.bytes;
2223 tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
2224 tx->tx_drop_bytes = thresh->tx.byte_drop;
2225 tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
2226 tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
2227 tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
2228 tx->tx_mpdu_aggr = thresh->tx.aggregation;
2229 tx->tx_succ_mcs = thresh->tx.succ_mcs;
2230 tx->tx_fail_mcs = thresh->tx.fail_mcs;
2231 tx->tx_ppdu_delay = thresh->tx.delay;
2232 WMA_LOGD(FL("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d"),
2233 tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
2234 tx->tx_bytes, tx->tx_msdu_drop_cnt);
2235 WMA_LOGD(FL("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d"),
2236 tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
2237 tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
2238 WMA_LOGD(FL("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d"),
2239 tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
2240 tx->tx_ppdu_delay);
2241 len += sizeof(wmi_tx_stats_thresh);
2242
2243 rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
2244 tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
2245 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
2246 WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
2247 WMA_LOGD(FL("Setting RX parameters. tag=%d, len=%d"), tag, hdr_len);
2248 rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
2249 rx->mac_rx_bytes = thresh->rx.bytes;
2250 rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
2251 rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
2252 rx->rx_disorder_cnt = thresh->rx.disorder;
2253 rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
2254 rx->rx_mpdu_dup_cnt = thresh->rx.mpdu_dup;
2255 rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
2256 rx->rx_mpdu_aggr = thresh->rx.aggregation;
2257 rx->rx_mcs = thresh->rx.mcs;
2258 rx->sta_ps_inds = thresh->rx.ps_inds;
2259 rx->sta_ps_durs = thresh->rx.ps_durs;
2260 rx->rx_probe_reqs = thresh->rx.probe_reqs;
2261 rx->rx_oth_mgmts = thresh->rx.other_mgmt;
2262 WMA_LOGD(FL("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d"),
2263 rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
2264 rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
2265 WMA_LOGD(FL("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d"),
2266 rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
2267 rx->rx_mpdu_aggr, rx->rx_mcs);
2268 WMA_LOGD(FL("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d"),
2269 rx->sta_ps_inds, rx->sta_ps_durs,
2270 rx->rx_probe_reqs, rx->rx_oth_mgmts);
2271 len += sizeof(wmi_rx_stats_thresh);
2272
2273 WMA_LOGA("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
2274 WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
2275 if (EOK != wmi_unified_cmd_send(wma->wmi_handle,
2276 buf, len,
2277 WMI_PDEV_SET_STATS_THRESHOLD_CMDID)) {
2278 WMA_LOGE("Failed to send WMI_PDEV_SET_STATS_THRESHOLD_CMDID");
2279 wmi_buf_free(buf);
2280 }
2281}
2282
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002283#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2284
2285/**
2286 * wma_update_pdev_stats() - update pdev stats
2287 * @wma: wma handle
2288 * @pdev_stats: pdev stats
2289 *
2290 * Return: none
2291 */
2292static void wma_update_pdev_stats(tp_wma_handle wma,
2293 wmi_pdev_stats *pdev_stats)
2294{
2295 tAniGetPEStatsRsp *stats_rsp_params;
2296 uint32_t temp_mask;
2297 uint8_t *stats_buf;
2298 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2299 struct wma_txrx_node *node;
2300 uint8_t i;
2301
2302 for (i = 0; i < wma->max_bssid; i++) {
2303 node = &wma->interfaces[i];
2304 stats_rsp_params = node->stats_rsp;
2305 if (stats_rsp_params) {
2306 node->fw_stats_set |= FW_PDEV_STATS_SET;
2307 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
2308 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2309 temp_mask = stats_rsp_params->statsMask;
2310 if (temp_mask & (1 << eCsrSummaryStats))
2311 stats_buf += sizeof(tCsrSummaryStatsInfo);
2312
2313 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2314 classa_stats =
2315 (tCsrGlobalClassAStatsInfo *) stats_buf;
2316 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
2317 }
2318 }
2319 }
2320}
2321
2322/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302323 * wma_vdev_stats_lost_link_helper() - helper function to extract
2324 * lost link information from vdev statistics event while deleting BSS.
2325 * @wma: WMA handle
2326 * @vdev_stats: statistics information from firmware
2327 *
2328 * This is for informing HDD to collect lost link information while
2329 * disconnection. Following conditions to check
2330 * 1. vdev is up
2331 * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to
2332 * zero, hence add the check here to indicate the event comes during deleting
2333 * BSS
2334 * 3. DELETE_BSS is the request message queued. Put this condition check on the
2335 * last one as it consumes more resource searching entries in the list
2336 *
2337 * Return: none
2338 */
2339static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma,
2340 wmi_vdev_stats *vdev_stats)
2341{
2342 struct wma_txrx_node *node;
2343 int32_t rssi;
2344 struct wma_target_req *req_msg;
2345 static const uint8_t zero_mac[QDF_MAC_ADDR_SIZE] = {0};
Naveen Rawatf440a132017-05-05 12:27:39 -07002346 int32_t bcn_snr, dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302347
2348 node = &wma->interfaces[vdev_stats->vdev_id];
Mukul Sharmaf9047232017-03-02 16:58:56 +05302349 if (wma_is_vdev_up(vdev_stats->vdev_id) &&
Hanumanth Reddy Pothulaaef3c7f2017-05-18 12:19:23 +05302350 !qdf_mem_cmp(node->bssid, zero_mac, QDF_MAC_ADDR_SIZE)) {
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302351 req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id,
2352 WMA_TARGET_REQ_TYPE_VDEV_STOP);
2353 if ((NULL == req_msg) ||
2354 (WMA_DELETE_BSS_REQ != req_msg->msg_type)) {
2355 WMA_LOGD(FL("cannot find DELETE_BSS request message"));
2356 return;
2357 }
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002358 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2359 dat_snr = vdev_stats->vdev_snr.dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302360 WMA_LOGD(FL("get vdev id %d, beancon snr %d, data snr %d"),
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002361 vdev_stats->vdev_id, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302362
2363 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002364 rssi = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302365 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002366 rssi = dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302367 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302368 rssi = WMA_TGT_INVALID_SNR;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302369
2370 /* Get the absolute rssi value from the current rssi value */
2371 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2372 wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi);
2373 }
2374}
2375
2376/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 * wma_update_vdev_stats() - update vdev stats
2378 * @wma: wma handle
2379 * @vdev_stats: vdev stats
2380 *
2381 * Return: none
2382 */
2383static void wma_update_vdev_stats(tp_wma_handle wma,
2384 wmi_vdev_stats *vdev_stats)
2385{
2386 tAniGetPEStatsRsp *stats_rsp_params;
2387 tCsrSummaryStatsInfo *summary_stats = NULL;
2388 uint8_t *stats_buf;
2389 struct wma_txrx_node *node;
2390 uint8_t i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002391 int32_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302392 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002394 struct scheduler_msg sme_msg = { 0 };
Naveen Rawatf440a132017-05-05 12:27:39 -07002395 int32_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002397 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2398 dat_snr = vdev_stats->vdev_snr.dat_snr;
2399 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
2400 vdev_stats->vdev_id, bcn_snr, dat_snr);
2401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002402 node = &wma->interfaces[vdev_stats->vdev_id];
2403 stats_rsp_params = node->stats_rsp;
2404 if (stats_rsp_params) {
2405 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2406 node->fw_stats_set |= FW_VDEV_STATS_SET;
2407 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
2408 vdev_stats->vdev_id);
2409 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
2410 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
2411 for (i = 0; i < 4; i++) {
2412 summary_stats->tx_frm_cnt[i] =
2413 vdev_stats->tx_frm_cnt[i];
2414 summary_stats->fail_cnt[i] =
2415 vdev_stats->fail_cnt[i];
2416 summary_stats->multiple_retry_cnt[i] =
2417 vdev_stats->multiple_retry_cnt[i];
2418 }
2419
2420 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
2421 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
2422 summary_stats->rx_discard_cnt =
2423 vdev_stats->rx_discard_cnt;
2424 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
2425 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
2426 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002427 /* Update SNR and RSSI in SummaryStats */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302428 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002429 summary_stats->snr = bcn_snr;
2430 summary_stats->rssi =
2431 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302432 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002433 summary_stats->snr = dat_snr;
2434 summary_stats->rssi =
Naveen Rawatf440a132017-05-05 12:27:39 -07002435 dat_snr + WMA_TGT_NOISE_FLOOR_DBM;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002436 } else {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302437 summary_stats->snr = WMA_TGT_INVALID_SNR;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002438 summary_stats->rssi = 0;
2439 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 }
2441 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442
2443 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302444 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
2445 rssi = bcn_snr;
2446 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2447 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
2448 rssi = dat_snr;
2449 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2450 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 /*
2452 * Firmware sends invalid snr till it sees
2453 * Beacon/Data after connection since after
2454 * vdev up fw resets the snr to invalid.
2455 * In this duartion Host will return the last know
2456 * rssi during connection.
2457 */
2458 WMA_LOGE("Invalid SNR from firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 }
2460
2461 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
2462 pGetRssiReq->sessionId);
2463
2464 /* update the average rssi value to UMAC layer */
2465 if (NULL != pGetRssiReq->rssiCallback) {
2466 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
2467 pGetRssiReq->staId,
2468 pGetRssiReq->pDevContext);
2469 }
2470
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302471 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 wma->pGetRssiReq = NULL;
2473 }
2474
2475 if (node->psnr_req) {
2476 tAniGetSnrReq *p_snr_req = node->psnr_req;
2477
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302478 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07002479 p_snr_req->snr = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302480 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002481 p_snr_req->snr = dat_snr;
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002482 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302483 p_snr_req->snr = WMA_TGT_INVALID_SNR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484
2485 sme_msg.type = eWNI_SME_SNR_IND;
2486 sme_msg.bodyptr = p_snr_req;
2487 sme_msg.bodyval = 0;
2488
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002489 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302490 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302492 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 }
2494
2495 node->psnr_req = NULL;
2496 }
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302497 wma_vdev_stats_lost_link_helper(wma, vdev_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498}
2499
2500/**
2501 * wma_post_stats() - update stats to PE
2502 * @wma: wma handle
2503 * @node: txrx node
2504 *
2505 * Return: none
2506 */
2507static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
2508{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 /* send response to UMAC */
Naveen Rawat3c49d192017-03-02 18:43:16 -08002510 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, node->stats_rsp, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511 node->stats_rsp = NULL;
2512 node->fw_stats_set = 0;
2513}
2514
2515/**
2516 * wma_update_peer_stats() - update peer stats
2517 * @wma: wma handle
2518 * @peer_stats: peer stats
2519 *
2520 * Return: none
2521 */
2522static void wma_update_peer_stats(tp_wma_handle wma,
2523 wmi_peer_stats *peer_stats)
2524{
2525 tAniGetPEStatsRsp *stats_rsp_params;
2526 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2527 struct wma_txrx_node *node;
2528 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
2529 uint32_t temp_mask;
2530
2531 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
2532 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
2533 return;
2534
2535 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002536 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2537 if (stats_rsp_params) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 node->fw_stats_set |= FW_PEER_STATS_SET;
2539 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2541 temp_mask = stats_rsp_params->statsMask;
2542 if (temp_mask & (1 << eCsrSummaryStats))
2543 stats_buf += sizeof(tCsrSummaryStatsInfo);
2544
2545 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2546 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
2547 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002548 /* The linkspeed returned by fw is in kbps so convert
2549 * it in to units of 500kbps which is expected by UMAC
2550 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 if (peer_stats->peer_tx_rate) {
2552 classa_stats->tx_rate =
2553 peer_stats->peer_tx_rate / 500;
2554 }
2555
2556 classa_stats->tx_rate_flags = node->rate_flags;
2557 if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) {
2558 classa_stats->mcs_index =
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002559 wma_get_mcs_idx(
2560 (peer_stats->peer_tx_rate /
2561 100), node->rate_flags,
2562 node->nss, &mcsRateFlags);
Jeff Johnsonad0b2c62017-03-16 14:37:38 -07002563 classa_stats->nss = node->nss;
2564 classa_stats->mcs_rate_flags = mcsRateFlags;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565 }
2566 /* FW returns tx power in intervals of 0.5 dBm
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002567 * Convert it back to intervals of 1 dBm
2568 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 classa_stats->max_pwr =
2570 roundup(classa_stats->max_pwr, 2) >> 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572 }
2573}
2574
2575/**
2576 * wma_post_link_status() - post link status to SME
2577 * @pGetLinkStatus: SME Link status
2578 * @link_status: Link status
2579 *
2580 * Return: none
2581 */
2582void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
2583 uint8_t link_status)
2584{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302585 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002586 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587
2588 pGetLinkStatus->linkStatus = link_status;
2589 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
2590 sme_msg.bodyptr = pGetLinkStatus;
2591 sme_msg.bodyval = 0;
2592
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002593 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302594 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302596 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597 }
2598}
2599
2600/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302601 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
2602 * @wma: wma handle
2603 * @rssi_stats: rssi stats
2604 * @rssi_per_chain_stats: buffer where rssi stats to be stored
2605 *
2606 * This function stores per chain rssi stats received from fw for all vdevs for
2607 * which the stats were requested into a csr stats structure.
2608 *
2609 * Return: void
2610 */
2611static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
2612 wmi_rssi_stats *rssi_stats,
2613 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
2614{
2615 int i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002616 int32_t bcn_snr, dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302617
2618 for (i = 0; i < NUM_CHAINS_MAX; i++) {
2619 bcn_snr = rssi_stats->rssi_avg_beacon[i];
2620 dat_snr = rssi_stats->rssi_avg_data[i];
2621 WMA_LOGD("chain %d beacon snr %d data snr %d",
2622 i, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302623 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302624 rssi_per_chain_stats->rssi[i] = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302625 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
2626 rssi_per_chain_stats->rssi[i] = dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302627 else
2628 /*
2629 * Firmware sends invalid snr till it sees
2630 * Beacon/Data after connection since after
2631 * vdev up fw resets the snr to invalid.
2632 * In this duartion Host will return an invalid rssi
2633 * value.
2634 */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302635 rssi_per_chain_stats->rssi[i] = WMA_TGT_INVALID_SNR;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302636
2637 /*
2638 * Get the absolute rssi value from the current rssi value the
2639 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
2640 */
2641 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
2642 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
2643 rssi_per_chain_stats->peer_mac_addr);
2644 }
2645}
2646
2647/**
2648 * wma_update_rssi_stats() - to update rssi stats for all vdevs
2649 * for which the stats were requested.
2650 * @wma: wma handle
2651 * @rssi_stats: rssi stats
2652 *
2653 * This function updates the rssi stats for all vdevs for which
2654 * the stats were requested.
2655 *
2656 * Return: void
2657 */
2658static void wma_update_rssi_stats(tp_wma_handle wma,
2659 wmi_rssi_stats *rssi_stats)
2660{
2661 tAniGetPEStatsRsp *stats_rsp_params;
2662 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
2663 struct wma_txrx_node *node;
2664 uint8_t *stats_buf;
2665 uint32_t temp_mask;
2666 uint8_t vdev_id;
2667
2668 vdev_id = rssi_stats->vdev_id;
2669 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002670 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2671 if (stats_rsp_params) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302672 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
2673 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
2674 vdev_id);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302675 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2676 temp_mask = stats_rsp_params->statsMask;
2677
2678 if (temp_mask & (1 << eCsrSummaryStats))
2679 stats_buf += sizeof(tCsrSummaryStatsInfo);
2680 if (temp_mask & (1 << eCsrGlobalClassAStats))
2681 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302682 if (temp_mask & (1 << eCsrGlobalClassDStats))
2683 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302684
2685 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
2686 rssi_per_chain_stats =
2687 (struct csr_per_chain_rssi_stats_info *)stats_buf;
2688 wma_update_per_chain_rssi_stats(wma, rssi_stats,
2689 rssi_per_chain_stats);
2690 }
2691 }
2692}
2693
2694
2695/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 * wma_link_status_event_handler() - link status event handler
2697 * @handle: wma handle
2698 * @cmd_param_info: data from event
2699 * @len: length
2700 *
2701 * Return: 0 for success or error code
2702 */
2703int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
2704 uint32_t len)
2705{
2706 tp_wma_handle wma = (tp_wma_handle) handle;
2707 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
2708 wmi_vdev_rate_stats_event_fixed_param *event;
2709 wmi_vdev_rate_ht_info *ht_info;
2710 struct wma_txrx_node *intr = wma->interfaces;
2711 uint8_t link_status = LINK_STATUS_LEGACY;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002712 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713
2714 param_buf =
2715 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2716 if (!param_buf) {
2717 WMA_LOGA("%s: Invalid stats event", __func__);
2718 return -EINVAL;
2719 }
2720
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002721 event = (wmi_vdev_rate_stats_event_fixed_param *)
2722 param_buf->fixed_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
2724
2725 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002726
2727 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
2728 sizeof(*event)) / sizeof(*ht_info))) {
2729 WMA_LOGE("%s: excess vdev_stats buffers:%d", __func__,
2730 event->num_vdev_stats);
2731 QDF_ASSERT(0);
2732 return -EINVAL;
2733 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002734 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
2735 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
2736 __func__, ht_info->vdevid, ht_info->tx_nss,
2737 ht_info->rx_nss, ht_info->tx_preamble,
2738 ht_info->rx_preamble);
2739 if (ht_info->vdevid < wma->max_bssid
2740 && intr[ht_info->vdevid].plink_status_req) {
2741 if (ht_info->tx_nss || ht_info->rx_nss)
2742 link_status = LINK_STATUS_MIMO;
2743
2744 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
2745 (ht_info->rx_preamble == LINK_RATE_VHT))
2746 link_status |= LINK_STATUS_VHT;
2747
2748 if (intr[ht_info->vdevid].nss == 2)
2749 link_status |= LINK_SUPPORT_MIMO;
2750
2751 if (intr[ht_info->vdevid].rate_flags &
2752 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
2753 eHAL_TX_RATE_VHT80))
2754 link_status |= LINK_SUPPORT_VHT;
2755
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002756 wma_post_link_status(
2757 intr[ht_info->vdevid].plink_status_req,
2758 link_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759 intr[ht_info->vdevid].plink_status_req = NULL;
2760 link_status = LINK_STATUS_LEGACY;
2761 }
2762
2763 ht_info++;
2764 }
2765
2766 return 0;
2767}
2768
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302769int wma_rso_cmd_status_event_handler(wmi_roam_event_fixed_param *wmi_event)
2770{
2771 struct rso_cmd_status *rso_status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -07002772 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302773 QDF_STATUS qdf_status;
2774
2775 rso_status = qdf_mem_malloc(sizeof(*rso_status));
2776 if (!rso_status) {
2777 WMA_LOGE("%s: malloc fails for rso cmd status", __func__);
2778 return -ENOMEM;
2779 }
2780
2781 rso_status->vdev_id = wmi_event->vdev_id;
2782 if (WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS == wmi_event->notif)
2783 rso_status->status = true;
2784 else if (WMI_ROAM_NOTIF_SCAN_MODE_FAIL == wmi_event->notif)
2785 rso_status->status = false;
2786 sme_msg.type = eWNI_SME_RSO_CMD_STATUS_IND;
2787 sme_msg.bodyptr = rso_status;
2788 sme_msg.bodyval = 0;
2789 WMA_LOGI("%s: Post RSO cmd status to SME", __func__);
2790
2791 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2792 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2793 WMA_LOGE("%s: fail to post RSO cmd status to SME", __func__);
2794 qdf_mem_free(rso_status);
2795 }
2796 return 0;
2797}
2798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002799/**
Will Huanga9814592017-05-24 15:47:58 +08002800 * wma_handle_sta_peer_info() - handle peer information in
2801 * peer stats
2802 * @num_peer_stats: peer number
2803 * @peer_stats: peer stats received from firmware
2804 * @peer_macaddr: the specified mac address
2805 * @sapaddr: sap mac address
2806 *
2807 * This function will send eWNI_SME_GET_PEER_INFO_IND
2808 * to sme with stations' information
2809 *
2810 */
2811static void wma_handle_sta_peer_info(uint32_t num_peer_stats,
2812 wmi_peer_stats *peer_stats,
2813 struct qdf_mac_addr peer_macaddr,
2814 uint8_t *sapaddr)
2815{
2816 QDF_STATUS qdf_status;
2817 wmi_mac_addr temp_addr;
2818 struct sir_peer_info_resp *peer_info;
2819 struct scheduler_msg sme_msg = {0};
2820 uint32_t i;
2821 uint32_t j = 0;
2822
2823 if (!qdf_is_macaddr_broadcast(&peer_macaddr)) {
2824 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_macaddr.bytes, &temp_addr);
2825 for (i = 0; i < num_peer_stats; i++) {
2826 if ((((temp_addr.mac_addr47to32) & 0x0000ffff) ==
2827 ((peer_stats->peer_macaddr.mac_addr47to32) &
2828 0x0000ffff))
2829 && (temp_addr.mac_addr31to0 ==
2830 peer_stats->peer_macaddr.mac_addr31to0)) {
2831
2832 break;
2833 }
2834 peer_stats = peer_stats + 1;
2835 }
2836 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2837 sizeof(peer_info->info[0]));
2838 if (NULL == peer_info) {
2839 WMA_LOGE("%s: Memory allocation failed.", __func__);
2840 return;
2841 }
2842 if (i < num_peer_stats) {
2843 peer_info->count = 1;
2844 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2845 peer_info->info[0].peer_macaddr.bytes);
2846 peer_info->info[0].rssi = peer_stats->peer_rssi;
2847 peer_info->info[0].tx_rate = peer_stats->peer_tx_rate;
2848 peer_info->info[0].rx_rate = peer_stats->peer_rx_rate;
2849 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2850 __func__,
2851 peer_info->info[0].peer_macaddr.bytes,
2852 peer_stats->peer_rssi,
2853 peer_stats->peer_tx_rate,
2854 peer_stats->peer_rx_rate);
2855 } else {
2856 WMA_LOGE("%s: no match mac address", __func__);
2857 peer_info->count = 0;
2858 }
2859 } else {
2860 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2861 num_peer_stats * sizeof(peer_info->info[0]));
2862 if (NULL == peer_info) {
2863 WMA_LOGE("%s: Memory allocation failed.", __func__);
2864 return;
2865 }
2866 peer_info->count = num_peer_stats;
2867
2868 for (i = 0; i < num_peer_stats; i++) {
2869 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2870 peer_info->info[j].peer_macaddr.bytes);
2871 peer_info->info[j].rssi = peer_stats->peer_rssi;
2872 peer_info->info[j].tx_rate = peer_stats->peer_tx_rate;
2873 peer_info->info[j].rx_rate = peer_stats->peer_rx_rate;
2874 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2875 __func__,
2876 peer_info->info[j].peer_macaddr.bytes,
2877 peer_stats->peer_rssi,
2878 peer_stats->peer_tx_rate,
2879 peer_stats->peer_rx_rate);
2880 if (!qdf_mem_cmp(peer_info->info[j].peer_macaddr.bytes,
2881 sapaddr, QDF_MAC_ADDR_SIZE)) {
2882 peer_info->count = peer_info->count - 1;
2883 } else {
2884 j++;
2885 }
2886 peer_stats = peer_stats + 1;
2887 }
2888 WMA_LOGD("WDA send peer num %d", peer_info->count);
2889 }
2890
2891 sme_msg.type = eWNI_SME_GET_PEER_INFO_IND;
2892 sme_msg.bodyptr = peer_info;
2893 sme_msg.bodyval = 0;
2894
2895 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2896 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2897 WMA_LOGE("%s: Fail to post get rssi msg", __func__);
2898 qdf_mem_free(peer_info);
2899 }
2900
2901 return;
2902}
2903
2904/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 * wma_stats_event_handler() - stats event handler
2906 * @handle: wma handle
2907 * @cmd_param_info: data from event
2908 * @len: length
2909 *
2910 * Return: 0 for success or error code
2911 */
2912int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
2913 uint32_t len)
2914{
2915 tp_wma_handle wma = (tp_wma_handle) handle;
2916 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
2917 wmi_stats_event_fixed_param *event;
2918 wmi_pdev_stats *pdev_stats;
2919 wmi_vdev_stats *vdev_stats;
2920 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302921 wmi_rssi_stats *rssi_stats;
2922 wmi_per_chain_rssi_stats *rssi_event;
2923 struct wma_txrx_node *node;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002924 uint8_t *temp;
2925 uint32_t i;
2926 uint32_t buf_len = 0;
2927 bool excess_data = false;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05302928 wmi_congestion_stats *congestion_stats;
2929 tpAniSirGlobal mac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2932 if (!param_buf) {
2933 WMA_LOGA("%s: Invalid stats event", __func__);
2934 return -EINVAL;
2935 }
2936 event = param_buf->fixed_param;
2937 temp = (uint8_t *) param_buf->data;
2938
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002939 do {
2940 if (event->num_pdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
2941 sizeof(*event)) / sizeof(*pdev_stats))) {
2942 excess_data = true;
2943 break;
2944 } else {
2945 buf_len += event->num_pdev_stats * sizeof(*pdev_stats);
2946 }
2947
2948 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
2949 sizeof(*event)) / sizeof(*vdev_stats))) {
2950 excess_data = true;
2951 break;
2952 } else {
2953 buf_len += event->num_vdev_stats * sizeof(*vdev_stats);
2954 }
2955
2956 if (event->num_peer_stats > ((WMI_SVC_MSG_MAX_SIZE -
2957 sizeof(*event)) / sizeof(*peer_stats))) {
2958 excess_data = true;
2959 break;
2960 } else {
2961 buf_len += event->num_peer_stats * sizeof(*peer_stats);
2962 }
2963
2964 rssi_event =
2965 (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
bingsf9047652017-08-31 08:05:54 +08002966 if (rssi_event) {
2967 if (rssi_event->num_per_chain_rssi_stats >
2968 ((WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) /
2969 sizeof(*rssi_event))) {
2970 excess_data = true;
2971 break;
2972 } else {
2973 buf_len += sizeof(*rssi_event) *
2974 rssi_event->num_per_chain_rssi_stats;
2975 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002976 }
2977 } while (0);
2978
2979 if (excess_data ||
2980 (sizeof(*event) > WMI_SVC_MSG_MAX_SIZE - buf_len)) {
2981 WMA_LOGE("excess wmi buffer: stats pdev %d vdev %d peer %d",
2982 event->num_pdev_stats, event->num_vdev_stats,
2983 event->num_peer_stats);
2984 QDF_ASSERT(0);
2985 return -EINVAL;
2986 }
2987
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002988 if (event->num_pdev_stats > 0) {
2989 for (i = 0; i < event->num_pdev_stats; i++) {
2990 pdev_stats = (wmi_pdev_stats *) temp;
2991 wma_update_pdev_stats(wma, pdev_stats);
2992 temp += sizeof(wmi_pdev_stats);
2993 }
2994 }
2995
2996 if (event->num_vdev_stats > 0) {
2997 for (i = 0; i < event->num_vdev_stats; i++) {
2998 vdev_stats = (wmi_vdev_stats *) temp;
2999 wma_update_vdev_stats(wma, vdev_stats);
3000 temp += sizeof(wmi_vdev_stats);
3001 }
3002 }
3003
3004 if (event->num_peer_stats > 0) {
Will Huanga9814592017-05-24 15:47:58 +08003005 if (wma->get_sta_peer_info == true) {
3006 wma_handle_sta_peer_info(event->num_peer_stats,
3007 (wmi_peer_stats *)temp,
3008 wma->peer_macaddr,
3009 wma->myaddr);
3010 } else {
3011 for (i = 0; i < event->num_peer_stats; i++) {
3012 peer_stats = (wmi_peer_stats *) temp;
3013 wma_update_peer_stats(wma, peer_stats);
3014 temp += sizeof(wmi_peer_stats);
3015 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 }
3017 }
3018
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303019 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
3020 if (rssi_event) {
Himanshu Agarwalcd8a84a2016-07-21 14:59:50 +05303021 if (((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
3022 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) &&
3023 ((rssi_event->tlv_header & 0x0000FFFF) ==
3024 WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats))) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303025 if (rssi_event->num_per_chain_rssi_stats > 0) {
3026 temp = (uint8_t *) rssi_event;
3027 temp += sizeof(*rssi_event);
Dustin Brownc4a5ba22016-11-10 17:21:18 -08003028
3029 /* skip past struct array tlv header */
3030 temp += WMI_TLV_HDR_SIZE;
3031
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303032 for (i = 0;
3033 i < rssi_event->num_per_chain_rssi_stats;
3034 i++) {
3035 rssi_stats = (wmi_rssi_stats *)temp;
3036 wma_update_rssi_stats(wma, rssi_stats);
3037 temp += sizeof(wmi_rssi_stats);
3038 }
3039 }
3040 }
3041 }
3042
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303043 congestion_stats = (wmi_congestion_stats *) param_buf->congestion_stats;
3044 if (congestion_stats) {
3045 if (((congestion_stats->tlv_header & 0xFFFF0000) >> 16 ==
3046 WMITLV_TAG_STRUC_wmi_congestion_stats) &&
3047 ((congestion_stats->tlv_header & 0x0000FFFF) ==
3048 WMITLV_GET_STRUCT_TLVLEN(wmi_congestion_stats))) {
3049 mac = cds_get_context(QDF_MODULE_ID_PE);
3050 if (!mac) {
3051 WMA_LOGE("%s: Invalid mac", __func__);
3052 return -EINVAL;
3053 }
3054 if (!mac->sme.congestion_cb) {
3055 WMA_LOGE("%s: Callback not registered",
3056 __func__);
3057 return -EINVAL;
3058 }
3059 WMA_LOGI("%s: congestion %d", __func__,
3060 congestion_stats->congestion);
3061 mac->sme.congestion_cb(mac->hHdd,
3062 congestion_stats->congestion,
3063 congestion_stats->vdev_id);
3064 }
3065 }
3066
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303067 for (i = 0; i < wma->max_bssid; i++) {
3068 node = &wma->interfaces[i];
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003069 if (node->fw_stats_set & FW_PEER_STATS_SET)
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303070 wma_post_stats(wma, node);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303071 }
3072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003073 return 0;
3074}
3075
3076/**
Will Huanga9814592017-05-24 15:47:58 +08003077 * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct
3078 * @wma: wma interface
3079 * @stats_info: WMI peer info pointer
3080 * @peer_info: SIR peer info pointer
3081 *
3082 * This function will fill SIR peer info from WMI peer info struct
3083 *
3084 * Return: None
3085 */
3086static void wma_fill_peer_info(tp_wma_handle wma,
3087 wmi_peer_stats_info *stats_info,
3088 struct sir_peer_info_ext *peer_info)
3089{
3090 peer_info->tx_packets = stats_info->tx_packets.low_32;
3091 peer_info->tx_bytes = stats_info->tx_bytes.high_32;
3092 peer_info->tx_bytes <<= 32;
3093 peer_info->tx_bytes += stats_info->tx_bytes.low_32;
3094 peer_info->rx_packets = stats_info->rx_packets.low_32;
3095 peer_info->rx_bytes = stats_info->rx_bytes.high_32;
3096 peer_info->rx_bytes <<= 32;
3097 peer_info->rx_bytes += stats_info->rx_bytes.low_32;
3098 peer_info->tx_retries = stats_info->tx_retries;
3099 peer_info->tx_failed = stats_info->tx_failed;
3100 peer_info->rssi = stats_info->peer_rssi;
3101 peer_info->tx_rate = stats_info->last_tx_bitrate_kbps;
3102 peer_info->tx_rate_code = stats_info->last_tx_rate_code;
3103 peer_info->rx_rate = stats_info->last_rx_bitrate_kbps;
3104 peer_info->rx_rate_code = stats_info->last_rx_rate_code;
3105}
3106
3107/**
3108 * wma_peer_info_ext_rsp() - process peer ext info ext
3109 * @handle: wma interface
3110 * @buf: wmi event buf pointer
3111 *
3112 * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME
3113 *
3114 * Return: 0 on success, error code otherwise
3115 */
3116static QDF_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf)
3117{
3118 wmi_peer_stats_info_event_fixed_param *event;
3119 wmi_peer_stats_info *stats_info;
3120 struct sir_peer_info_ext_resp *resp;
3121 struct sir_peer_info_ext *peer_info;
3122 struct scheduler_msg sme_msg = {0};
3123 int i, j = 0;
3124 QDF_STATUS qdf_status;
3125
3126 event = (wmi_peer_stats_info_event_fixed_param *)buf;
3127 stats_info = (wmi_peer_stats_info *)(buf +
3128 sizeof(wmi_peer_stats_info_event_fixed_param));
3129
3130 if (wma->get_one_peer_info) {
3131 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3132 sizeof(resp->info[0]));
3133 if (!resp) {
3134 WMA_LOGE(FL("resp allocation failed."));
3135 return QDF_STATUS_E_NOMEM;
3136 }
3137 resp->count = 0;
3138 peer_info = &resp->info[0];
3139 for (i = 0; i < event->num_peers; i++) {
3140 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3141 peer_info->peer_macaddr.bytes);
3142
3143 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3144 wma->peer_macaddr.bytes,
3145 QDF_MAC_ADDR_SIZE)) {
3146 wma_fill_peer_info(wma, stats_info, peer_info);
3147 resp->count++;
3148 break;
3149 }
3150
3151 stats_info = stats_info + 1;
3152 }
3153 } else {
3154 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3155 event->num_peers * sizeof(resp->info[0]));
3156 if (!resp) {
3157 WMA_LOGE(FL("resp allocation failed."));
3158 return QDF_STATUS_E_NOMEM;
3159 }
3160 resp->count = event->num_peers;
3161 for (i = 0; i < event->num_peers; i++) {
3162 peer_info = &resp->info[j];
3163 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3164 peer_info->peer_macaddr.bytes);
3165
3166 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3167 wma->myaddr, QDF_MAC_ADDR_SIZE)) {
3168 resp->count = resp->count - 1;
3169 } else {
3170 wma_fill_peer_info(wma, stats_info, peer_info);
3171 j++;
3172 }
3173 stats_info = stats_info + 1;
3174 }
3175 }
3176
3177 sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND;
3178 sme_msg.bodyptr = resp;
3179 sme_msg.bodyval = 0;
3180
3181 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3182 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3183 WMA_LOGE("%s: Fail to post get peer info msg", __func__);
3184 qdf_mem_free(resp);
3185 }
3186
3187 return qdf_status;
3188}
3189
3190/**
3191 * dump_peer_stats_info() - dump wmi peer info struct
3192 * @event: wmi peer info fixed param pointer
3193 * @peer_stats: wmi peer stats info pointer
3194 *
3195 * This function will dump wmi peer info struct
3196 *
3197 * Return: None
3198 */
3199static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event,
3200 wmi_peer_stats_info *peer_stats)
3201{
3202 int i;
3203 wmi_peer_stats_info *stats = peer_stats;
3204 u_int8_t mac[6];
3205
3206 WMA_LOGI("%s vdev_id %d, num_peers %d more_data %d",
3207 __func__, event->vdev_id,
3208 event->num_peers, event->more_data);
3209
3210 for (i = 0; i < event->num_peers; i++) {
3211 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
3212 WMA_LOGI("%s mac %pM", __func__, mac);
3213 WMA_LOGI("%s tx_bytes %d %d tx_packets %d %d",
3214 __func__,
3215 stats->tx_bytes.low_32,
3216 stats->tx_bytes.high_32,
3217 stats->tx_packets.low_32,
3218 stats->tx_packets.high_32);
3219 WMA_LOGI("%s rx_bytes %d %d rx_packets %d %d",
3220 __func__,
3221 stats->rx_bytes.low_32,
3222 stats->rx_bytes.high_32,
3223 stats->rx_packets.low_32,
3224 stats->rx_packets.high_32);
3225 WMA_LOGI("%s tx_retries %d tx_failed %d",
3226 __func__, stats->tx_retries, stats->tx_failed);
3227 WMA_LOGI("%s tx_rate_code %x rx_rate_code %x",
3228 __func__,
3229 stats->last_tx_rate_code,
3230 stats->last_rx_rate_code);
3231 WMA_LOGI("%s tx_rate %x rx_rate %x",
3232 __func__,
3233 stats->last_tx_bitrate_kbps,
3234 stats->last_rx_bitrate_kbps);
3235 WMA_LOGI("%s peer_rssi %d", __func__, stats->peer_rssi);
3236 stats++;
3237 }
3238}
3239
3240int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
3241 u_int32_t len)
3242{
3243 tp_wma_handle wma = (tp_wma_handle) handle;
3244 WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
3245 wmi_peer_stats_info_event_fixed_param *event;
3246 u_int32_t buf_size;
3247 u_int8_t *buf;
3248
3249 param_buf =
3250 (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info;
3251 if (!param_buf) {
3252 WMA_LOGA("%s: Invalid stats event", __func__);
3253 return -EINVAL;
3254 }
3255
3256 WMA_LOGI("%s Recv WMI_PEER_STATS_INFO_EVENTID", __func__);
3257 event = param_buf->fixed_param;
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003258 if (event->num_peers >
3259 ((WMI_SVC_MSG_MAX_SIZE -
3260 sizeof(wmi_peer_stats_info_event_fixed_param))/
3261 sizeof(wmi_peer_stats_info))) {
3262 WMA_LOGE("Excess num of peers from fw %d", event->num_peers);
3263 return -EINVAL;
3264 }
Will Huanga9814592017-05-24 15:47:58 +08003265 buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) +
3266 sizeof(wmi_peer_stats_info) * event->num_peers;
3267 buf = qdf_mem_malloc(buf_size);
3268 if (!buf) {
3269 WMA_LOGE("%s: Failed alloc memory for buf", __func__);
3270 return -ENOMEM;
3271 }
3272
3273 qdf_mem_copy(buf, param_buf->fixed_param,
3274 sizeof(wmi_peer_stats_info_event_fixed_param));
3275 qdf_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)),
3276 param_buf->peer_stats_info,
3277 sizeof(wmi_peer_stats_info) * event->num_peers);
3278 WMA_LOGI("%s dump peer stats info", __func__);
3279 dump_peer_stats_info(event, param_buf->peer_stats_info);
3280
3281 wma_peer_info_ext_rsp(wma, buf);
3282 qdf_mem_free(buf);
3283
3284 return 0;
3285}
3286
3287/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288 * wma_send_link_speed() - send link speed to SME
3289 * @link_speed: link speed
3290 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303291 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303293QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303295 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303296 tpAniSirGlobal mac_ctx;
3297 tSirLinkSpeedInfo *ls_ind;
3298
3299 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
3300 if (!mac_ctx) {
3301 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
3302 return QDF_STATUS_E_INVAL;
3303 }
3304
3305 ls_ind = (tSirLinkSpeedInfo *)qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 if (!ls_ind) {
3307 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303308 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309 } else {
3310 ls_ind->estLinkSpeed = link_speed;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303311 if (mac_ctx->sme.pLinkSpeedIndCb)
3312 mac_ctx->sme.pLinkSpeedIndCb(ls_ind,
3313 mac_ctx->sme.pLinkSpeedCbContext);
3314 else
3315 WMA_LOGD("%s: pLinkSpeedIndCb is null", __func__);
3316 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003318 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303319 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003320}
3321
3322/**
3323 * wma_link_speed_event_handler() - link speed event handler
3324 * @handle: wma handle
3325 * @cmd_param_info: event data
3326 * @len: length
3327 *
3328 * Return: 0 for success or error code
3329 */
3330int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
3331 uint32_t len)
3332{
3333 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
3334 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303335 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003337 param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)
3338 cmd_param_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339 if (!param_buf) {
3340 WMA_LOGE("%s: Invalid linkspeed event", __func__);
3341 return -EINVAL;
3342 }
3343 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303344 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003345 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 return 0;
3348}
3349
3350/**
3351 * wma_wni_cfg_dnld() - cfg download request
3352 * @handle: wma handle
3353 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303354 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303356QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303358 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303359 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360
3361 WMA_LOGD("%s: Enter", __func__);
3362
3363 if (NULL == mac) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003364 WMA_LOGE("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303365 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303366 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367 }
3368
3369 process_cfg_download_req(mac);
3370
3371 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303372 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373}
3374
3375/**
3376 * wma_unified_debug_print_event_handler() - debug print event handler
3377 * @handle: wma handle
3378 * @datap: data pointer
3379 * @len: length
3380 *
3381 * Return: 0 for success or error code
3382 */
3383int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
3384 uint32_t len)
3385{
3386 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
3387 uint8_t *data;
3388 uint32_t datalen;
3389
3390 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
3391 if (!param_buf) {
3392 WMA_LOGE("Get NULL point message from FW");
3393 return -ENOMEM;
3394 }
3395 data = param_buf->data;
3396 datalen = param_buf->num_data;
3397
3398#ifdef BIG_ENDIAN_HOST
3399 {
3400 char dbgbuf[500] = { 0 };
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 memcpy(dbgbuf, data, datalen);
3403 SWAPME(dbgbuf, datalen);
3404 WMA_LOGD("FIRMWARE:%s", dbgbuf);
3405 return 0;
3406 }
3407#else
3408 WMA_LOGD("FIRMWARE:%s", data);
3409 return 0;
3410#endif /* BIG_ENDIAN_HOST */
3411}
3412
3413/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414 * wma_is_sap_active() - check sap is active or not
3415 * @handle: wma handle
3416 *
3417 * Return: true/false
3418 */
3419bool wma_is_sap_active(tp_wma_handle wma_handle)
3420{
3421 int i;
3422
3423 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303424 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 continue;
3426 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3427 wma_handle->interfaces[i].sub_type == 0)
3428 return true;
3429 }
3430 return false;
3431}
3432
3433/**
3434 * wma_is_p2p_go_active() - check p2p go is active or not
3435 * @handle: wma handle
3436 *
3437 * Return: true/false
3438 */
3439bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
3440{
3441 int i;
3442
3443 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303444 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003445 continue;
3446 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3447 wma_handle->interfaces[i].sub_type ==
3448 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
3449 return true;
3450 }
3451 return false;
3452}
3453
3454/**
3455 * wma_is_p2p_cli_active() - check p2p cli is active or not
3456 * @handle: wma handle
3457 *
3458 * Return: true/false
3459 */
3460bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
3461{
3462 int i;
3463
3464 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303465 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003466 continue;
3467 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3468 wma_handle->interfaces[i].sub_type ==
3469 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
3470 return true;
3471 }
3472 return false;
3473}
3474
3475/**
3476 * wma_is_sta_active() - check sta is active or not
3477 * @handle: wma handle
3478 *
3479 * Return: true/false
3480 */
3481bool wma_is_sta_active(tp_wma_handle wma_handle)
3482{
3483 int i;
3484
3485 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303486 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003487 continue;
3488 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3489 wma_handle->interfaces[i].sub_type == 0)
3490 return true;
3491 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
3492 return true;
3493 }
3494 return false;
3495}
3496
3497/**
3498 * wma_peer_phymode() - get phymode
3499 * @nw_type: nw type
3500 * @sta_type: sta type
3501 * @is_ht: is ht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003502 * @ch_width: supported channel width
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503 * @is_vht: is vht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003504 * @is_he: is HE supported
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 *
3506 * Return: WLAN_PHY_MODE
3507 */
3508WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
3509 uint8_t is_ht, uint8_t ch_width,
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003510 uint8_t is_vht, bool is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511{
3512 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
3513
3514 switch (nw_type) {
3515 case eSIR_11B_NW_TYPE:
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003516#ifdef FEATURE_WLAN_TDLS
3517 if (STA_ENTRY_TDLS_PEER == sta_type) {
3518 if (is_vht) {
3519 if (CH_WIDTH_80MHZ == ch_width)
3520 phymode = MODE_11AC_VHT80;
3521 else
3522 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3523 MODE_11AC_VHT40 :
3524 MODE_11AC_VHT20;
3525 } else if (is_ht) {
3526 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3527 MODE_11NG_HT40 : MODE_11NG_HT20;
3528 } else
3529 phymode = MODE_11B;
3530 } else
3531#endif /* FEATURE_WLAN_TDLS */
3532 {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533 phymode = MODE_11B;
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003534 if (is_ht || is_vht || is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003535 WMA_LOGE("HT/VHT is enabled with 11B NW type");
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003536 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 break;
3538 case eSIR_11G_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_11G;
3541 break;
3542 }
3543 if (CH_WIDTH_40MHZ < ch_width)
3544 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
3545 if (ch_width)
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003546 phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ?
3547 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548 else
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003549 phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ?
3550 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 break;
3552 case eSIR_11A_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003553 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554 phymode = MODE_11A;
3555 break;
3556 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003557 if (is_he) {
3558 if (ch_width == CH_WIDTH_160MHZ)
3559 phymode = MODE_11AX_HE160;
3560 else if (ch_width == CH_WIDTH_80P80MHZ)
3561 phymode = MODE_11AX_HE80_80;
3562 else if (ch_width == CH_WIDTH_80MHZ)
3563 phymode = MODE_11AX_HE80;
3564 else
3565 phymode = (ch_width) ?
3566 MODE_11AX_HE40 : MODE_11AX_HE20;
3567 } else if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003568 if (ch_width == CH_WIDTH_160MHZ)
3569 phymode = MODE_11AC_VHT160;
3570 else if (ch_width == CH_WIDTH_80P80MHZ)
3571 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07003572 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573 phymode = MODE_11AC_VHT80;
3574 else
3575 phymode = (ch_width) ?
3576 MODE_11AC_VHT40 : MODE_11AC_VHT20;
3577 } else
3578 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
3579 break;
3580 default:
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003581 WMA_LOGE("%s: Invalid nw type %d", __func__, nw_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003582 break;
3583 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003584 WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"),
3585 nw_type, is_ht, ch_width, is_vht, is_he, phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586
3587 return phymode;
3588}
3589
3590/**
3591 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
3592 * @wma_handle: wma handle
3593 * @vdev_id: vdev id
3594 * @value: value
3595 *
3596 * Return: 0 for success or return error
3597 */
3598int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
3599 uint8_t vdev_id, uint32_t value)
3600{
3601 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003602 struct cdp_vdev *vdev;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303603 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3604
3605 if (!soc) {
3606 WMA_LOGE("%s:SOC context is NULL", __func__);
3607 return -EINVAL;
3608 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609
3610 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3611 if (!vdev) {
3612 WMA_LOGE("%s:Invalid vdev handle", __func__);
3613 return -EINVAL;
3614 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303615 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 req.stats_type_reset_mask = value;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003617 cdp_fw_stats_get(soc, vdev, &req, false, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618
3619 return 0;
3620}
3621
3622#ifdef HELIUMPLUS
Jeff Johnson560dc562017-03-17 15:19:31 -07003623#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003624 ((_mask) = 1 << (_rate_info ## _V2))
3625#else /* !HELIUMPLUS */
Jeff Johnson560dc562017-03-17 15:19:31 -07003626#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 ((_mask) = 1 << (_rate_info))
3628#endif
3629
Nirav Shah93e789e2016-04-14 19:47:43 +05303630#ifdef HELIUMPLUS
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003631static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303632{
3633 if (value > (HTT_DBG_NUM_STATS + 1) ||
3634 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
3635 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
3636 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3637 WMA_LOGE("%s: Not supported", __func__);
3638 return false;
3639 }
3640 return true;
3641}
3642#else
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003643static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303644{
3645 if (value > (HTT_DBG_NUM_STATS + 1) ||
3646 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
3647 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
3648 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3649 WMA_LOGE("%s: Not supported", __func__);
3650 return false;
3651 }
3652 return true;
3653}
3654#endif
3655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656/**
3657 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
3658 * @wma_handle: wma handle
3659 * @vdev_id: vdev id
3660 * @value: value
3661 *
3662 * Return: 0 for success or return error
3663 */
3664int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
3665 uint8_t vdev_id, uint32_t value)
3666{
3667 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003668 struct cdp_vdev *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669 uint32_t l_up_mask;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303670 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3671
3672 if (!soc) {
3673 WMA_LOGE("%s:SOC context is NULL", __func__);
3674 return -EINVAL;
3675 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003676
3677 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3678 if (!vdev) {
3679 WMA_LOGE("%s:Invalid vdev handle", __func__);
3680 return -EINVAL;
3681 }
Nirav Shah93e789e2016-04-14 19:47:43 +05303682
3683 if (wma_is_valid_fw_stats_cmd(value) == false)
3684 return -EINVAL;
3685
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303686 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687 req.print.verbose = 1;
3688
Nirav Shah93e789e2016-04-14 19:47:43 +05303689 /* TODO: Need to check how to avoid mem leak*/
3690 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003691 req.stats_type_upload_mask = l_up_mask;
3692
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003693 cdp_fw_stats_get(soc, vdev, &req, false, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694
3695 return 0;
3696}
3697
3698/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003699 * wma_get_stats_rsp_buf() - fill get stats response buffer
3700 * @get_stats_param: get stats parameters
3701 *
3702 * Return: stats response buffer
3703 */
3704static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
3705 (tAniGetPEStatsReq *get_stats_param)
3706{
3707 tAniGetPEStatsRsp *stats_rsp_params;
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003708 uint32_t len, temp_mask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709
3710 len = sizeof(tAniGetPEStatsRsp);
3711 temp_mask = get_stats_param->statsMask;
3712
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003713 if (temp_mask & (1 << eCsrSummaryStats))
3714 len += sizeof(tCsrSummaryStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003716 if (temp_mask & (1 << eCsrGlobalClassAStats))
3717 len += sizeof(tCsrGlobalClassAStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003718
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003719 if (temp_mask & (1 << eCsrGlobalClassDStats))
3720 len += sizeof(tCsrGlobalClassDStatsInfo);
3721
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003722 if (temp_mask & (1 << csr_per_chain_rssi_stats))
3723 len += sizeof(struct csr_per_chain_rssi_stats_info);
3724
3725 stats_rsp_params = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 if (!stats_rsp_params) {
3727 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303728 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 return NULL;
3730 }
3731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 stats_rsp_params->staId = get_stats_param->staId;
3733 stats_rsp_params->statsMask = get_stats_param->statsMask;
3734 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
3735 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303736 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 return stats_rsp_params;
3738}
3739
3740/**
3741 * wma_get_stats_req() - get stats request
3742 * @handle: wma handle
3743 * @get_stats_param: stats params
3744 *
3745 * Return: none
3746 */
3747void wma_get_stats_req(WMA_HANDLE handle,
3748 tAniGetPEStatsReq *get_stats_param)
3749{
3750 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3751 struct wma_txrx_node *node;
Govind Singh4863da42016-03-08 11:45:00 +05303752 struct pe_stats_req cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003753 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05303754
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003755
3756 WMA_LOGD("%s: Enter", __func__);
3757 node = &wma_handle->interfaces[get_stats_param->sessionId];
3758 if (node->stats_rsp) {
3759 pGetPEStatsRspParams = node->stats_rsp;
3760 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
3761 pGetPEStatsRspParams->statsMask ==
3762 get_stats_param->statsMask) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003763 WMA_LOGD("Stats for staId %d with stats mask %d is pending.. ignore new request",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003764 get_stats_param->staId,
3765 get_stats_param->statsMask);
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303766 pGetPEStatsRspParams =
3767 wma_get_stats_rsp_buf(get_stats_param);
3768 if (!pGetPEStatsRspParams) {
3769 WMA_LOGE("failed to allocate memory for stats response");
3770 goto end;
3771 }
3772 goto req_pending;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003773 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303774 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 node->stats_rsp = NULL;
3776 node->fw_stats_set = 0;
3777 }
3778 }
3779
3780 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
3781 if (!pGetPEStatsRspParams)
3782 goto end;
3783
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003784 node->fw_stats_set = 0;
Naveen Rawat3c49d192017-03-02 18:43:16 -08003785 if (node->stats_rsp) {
Jeff Johnsonadba3962017-09-18 08:12:35 -07003786 WMA_LOGD(FL("stats_rsp is not null, prev_value: %pK"),
Naveen Rawat3c49d192017-03-02 18:43:16 -08003787 node->stats_rsp);
3788 qdf_mem_free(node->stats_rsp);
3789 node->stats_rsp = NULL;
3790 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003791 node->stats_rsp = pGetPEStatsRspParams;
Will Huanga9814592017-05-24 15:47:58 +08003792 wma_handle->get_sta_peer_info = false;
Jeff Johnsonadba3962017-09-18 08:12:35 -07003793 WMA_LOGD("stats_rsp allocated: %pK, sta_id: %d, mask: %d, vdev_id: %d",
Naveen Rawat3c49d192017-03-02 18:43:16 -08003794 node->stats_rsp, node->stats_rsp->staId,
3795 node->stats_rsp->statsMask, get_stats_param->sessionId);
Govind Singh4863da42016-03-08 11:45:00 +05303796
3797 cmd.session_id = get_stats_param->sessionId;
Dustin Brown12a96022017-07-12 10:34:50 -07003798 cmd.stats_mask = get_stats_param->statsMask;
Govind Singh4863da42016-03-08 11:45:00 +05303799 if (wmi_unified_get_stats_cmd(wma_handle->wmi_handle, &cmd,
3800 node->bssid)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801
3802 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
3803 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804 goto failed;
3805 }
3806
3807 goto end;
3808failed:
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303809 node->stats_rsp = NULL;
3810req_pending:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303811 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812 /* send response to UMAC */
3813 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
3814 0);
3815end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303816 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 WMA_LOGD("%s: Exit", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818}
3819
3820/**
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303821 * wma_get_cca_stats() - send request to fw to get CCA
3822 * @wma_handle: wma handle
3823 * @vdev_id: vdev id
3824 *
3825 * Return: QDF status
3826 */
3827QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
3828 uint8_t vdev_id)
3829{
3830 if (wmi_unified_congestion_request_cmd(wma_handle->wmi_handle,
3831 vdev_id)) {
3832 WMA_LOGE("Failed to congestion request to fw");
3833 return QDF_STATUS_E_FAILURE;
3834 }
3835 return QDF_STATUS_SUCCESS;
3836}
3837
3838/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
3840 * @vdev_id: vdev id
3841 * @buffer_size: size of buffer
3842 *
3843 * Return: none
3844 */
3845void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
3846{
3847 tp_wma_handle wma;
3848 struct beacon_info *beacon;
3849 uint8_t *buf;
3850 uint32_t buf_size;
3851
Anurag Chouhan6d760662016-02-20 16:05:43 +05303852 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853 if (!wma) {
3854 WMA_LOGE("%s: Invalid WMA handle", __func__);
3855 return NULL;
3856 }
3857
3858 if (vdev_id >= wma->max_bssid) {
3859 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3860 return NULL;
3861 }
3862
3863 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
3864 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
3865 return NULL;
3866 }
3867
3868 beacon = wma->interfaces[vdev_id].beacon;
3869
3870 if (!beacon) {
3871 WMA_LOGE("%s: beacon invalid", __func__);
3872 return NULL;
3873 }
3874
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303875 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003876
Nirav Shahcbc6d722016-03-01 16:24:53 +05303877 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303878 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879
3880 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303881 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
3883 return NULL;
3884 }
3885
Nirav Shahcbc6d722016-03-01 16:24:53 +05303886 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003887
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303888 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889
3890 if (buffer_size)
3891 *buffer_size = buf_size;
3892
3893 return buf;
3894}
3895
3896/**
3897 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
3898 * @vdev_id: vdev id
3899 *
3900 * Return: mac address
3901 */
3902uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
3903{
3904 tp_wma_handle wma;
3905
Anurag Chouhan6d760662016-02-20 16:05:43 +05303906 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 if (!wma) {
3908 WMA_LOGE("%s: Invalid WMA handle", __func__);
3909 return NULL;
3910 }
3911
3912 if (vdev_id >= wma->max_bssid) {
3913 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3914 return NULL;
3915 }
3916
3917 return wma->interfaces[vdev_id].addr;
3918}
3919
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003920QDF_STATUS wma_get_connection_info(uint8_t vdev_id,
3921 struct policy_mgr_vdev_entry_info *conn_table_entry)
3922{
3923 struct wma_txrx_node *wma_conn_table_entry;
3924
3925 wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id);
3926 if (NULL == wma_conn_table_entry) {
3927 WMA_LOGE("%s: can't find vdev_id %d in WMA table", __func__, vdev_id);
3928 return QDF_STATUS_E_FAILURE;
3929 }
3930 conn_table_entry->chan_width = wma_conn_table_entry->chan_width;
3931 conn_table_entry->mac_id = wma_conn_table_entry->mac_id;
3932 conn_table_entry->mhz = wma_conn_table_entry->mhz;
3933 conn_table_entry->sub_type = wma_conn_table_entry->sub_type;
3934 conn_table_entry->type = wma_conn_table_entry->type;
3935
3936 return QDF_STATUS_SUCCESS;
3937}
3938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003939/**
3940 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
3941 * @vdev_id: vdev id
3942 *
3943 * Return: entry from vdev table
3944 */
3945struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
3946{
3947 tp_wma_handle wma;
3948
Anurag Chouhan6d760662016-02-20 16:05:43 +05303949 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950 if (!wma) {
3951 WMA_LOGE("%s: Invalid WMA handle", __func__);
3952 return NULL;
3953 }
3954
3955 if (vdev_id >= wma->max_bssid) {
3956 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3957 return NULL;
3958 }
3959
3960 return &wma->interfaces[vdev_id];
3961}
3962
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963#if defined(QCA_WIFI_FTM)
3964/**
3965 * wma_utf_rsp() - utf response
3966 * @wma_handle: wma handle
3967 * @payload: payload
3968 * @len: length of payload
3969 *
3970 * Return: 0 for success or error code
3971 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003972static int wma_utf_rsp(tp_wma_handle wma_handle, uint8_t **payload,
3973 uint32_t *len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003974{
3975 int ret = -1;
3976 uint32_t payload_len;
3977
3978 payload_len = wma_handle->utf_event_info.length;
3979 if (payload_len) {
3980 ret = 0;
3981
3982 /*
3983 * The first 4 bytes holds the payload size
3984 * and the actual payload sits next to it
3985 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303986 *payload = (uint8_t *) qdf_mem_malloc((uint32_t) payload_len
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003987 + sizeof(A_UINT32));
3988 *(A_UINT32 *) &(*payload[0]) =
3989 wma_handle->utf_event_info.length;
3990 memcpy(*payload + sizeof(A_UINT32),
3991 wma_handle->utf_event_info.data, payload_len);
3992 wma_handle->utf_event_info.length = 0;
3993 *len = payload_len;
3994 }
3995
3996 return ret;
3997}
3998
3999/**
4000 * wma_post_ftm_response() - post ftm response to upper layer
4001 * @wma_handle: wma handle
4002 *
4003 * Return: none
4004 */
4005static void wma_post_ftm_response(tp_wma_handle wma_handle)
4006{
4007 int ret;
4008 uint8_t *payload;
4009 uint32_t data_len;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08004010 struct scheduler_msg msg = { 0 };
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304011 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004012
4013 ret = wma_utf_rsp(wma_handle, &payload, &data_len);
4014
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004015 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004016 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017
4018 sys_build_message_header(SYS_MSG_ID_FTM_RSP, &msg);
4019 msg.bodyptr = payload;
4020 msg.bodyval = 0;
4021
Rajeev Kumarb60abe42017-01-21 15:39:31 -08004022 status = scheduler_post_msg(QDF_MODULE_ID_SYS, &msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304024 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025 WMA_LOGE("failed to post ftm response to SYS");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304026 qdf_mem_free(payload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 }
4028}
4029
4030/**
4031 * wma_process_utf_event() - process utf event
4032 * @handle: wma handle
4033 * @datap: data buffer
4034 * @dataplen: data length
4035 *
4036 * Return: 0 for success or error code
4037 */
4038static int
4039wma_process_utf_event(WMA_HANDLE handle, uint8_t *datap, uint32_t dataplen)
4040{
4041 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05304042 struct seg_hdr_info segHdrInfo;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 uint8_t totalNumOfSegments, currentSeq;
4044 WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf;
4045 uint8_t *data;
4046 uint32_t datalen;
4047
4048 param_buf = (WMI_PDEV_UTF_EVENTID_param_tlvs *) datap;
4049 if (!param_buf) {
4050 WMA_LOGE("Get NULL point message from FW");
4051 return -EINVAL;
4052 }
4053 data = param_buf->data;
4054 datalen = param_buf->num_data;
4055
Govind Singhd76a5b02016-03-08 15:12:14 +05304056 segHdrInfo = *(struct seg_hdr_info *) &(data[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057
4058 wma_handle->utf_event_info.currentSeq = (segHdrInfo.segmentInfo & 0xF);
4059
4060 currentSeq = (segHdrInfo.segmentInfo & 0xF);
4061 totalNumOfSegments = (segHdrInfo.segmentInfo >> 4) & 0xF;
4062
4063 datalen = datalen - sizeof(segHdrInfo);
4064
4065 if (currentSeq == 0) {
4066 wma_handle->utf_event_info.expectedSeq = 0;
4067 wma_handle->utf_event_info.offset = 0;
4068 } else {
4069 if (wma_handle->utf_event_info.expectedSeq != currentSeq)
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004070 WMA_LOGE("Mismatch in expecting seq expected Seq %d got seq %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071 wma_handle->utf_event_info.expectedSeq,
4072 currentSeq);
4073 }
4074
Varun Reddy Yeturud4c523d2017-09-26 15:28:42 -07004075 if ((datalen > MAX_UTF_EVENT_LENGTH) ||
4076 (wma_handle->utf_event_info.offset >
4077 (MAX_UTF_EVENT_LENGTH - datalen))) {
4078 WMA_LOGE("Excess data from firmware, offset:%zu, len:%d",
4079 wma_handle->utf_event_info.offset, datalen);
4080 return -EINVAL;
4081 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 memcpy(&wma_handle->utf_event_info.
4083 data[wma_handle->utf_event_info.offset],
4084 &data[sizeof(segHdrInfo)], datalen);
4085 wma_handle->utf_event_info.offset =
4086 wma_handle->utf_event_info.offset + datalen;
4087 wma_handle->utf_event_info.expectedSeq++;
4088
4089 if (wma_handle->utf_event_info.expectedSeq == totalNumOfSegments) {
4090 if (wma_handle->utf_event_info.offset != segHdrInfo.len)
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004091 WMA_LOGE("All segs received total len mismatch.. len %zu total len %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 wma_handle->utf_event_info.offset,
4093 segHdrInfo.len);
4094
4095 wma_handle->utf_event_info.length =
4096 wma_handle->utf_event_info.offset;
4097 }
4098
4099 wma_post_ftm_response(wma_handle);
4100
4101 return 0;
4102}
4103
4104/**
4105 * wma_utf_detach() - utf detach
4106 * @wma_handle: wma handle
4107 *
4108 * Return: none
4109 */
4110void wma_utf_detach(tp_wma_handle wma_handle)
4111{
4112 if (wma_handle->utf_event_info.data) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304113 qdf_mem_free(wma_handle->utf_event_info.data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 wma_handle->utf_event_info.data = NULL;
4115 wma_handle->utf_event_info.length = 0;
4116 wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
4117 WMI_PDEV_UTF_EVENTID);
4118 }
4119}
4120
4121/**
4122 * wma_utf_attach() - utf attach
4123 * @wma_handle: wma handle
4124 *
4125 * Return: none
4126 */
4127void wma_utf_attach(tp_wma_handle wma_handle)
4128{
4129 int ret;
4130
4131 wma_handle->utf_event_info.data = (unsigned char *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304132 qdf_mem_malloc(MAX_UTF_EVENT_LENGTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004133 wma_handle->utf_event_info.length = 0;
4134
4135 ret = wmi_unified_register_event_handler(wma_handle->wmi_handle,
4136 WMI_PDEV_UTF_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05304137 wma_process_utf_event,
4138 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139
4140 if (ret)
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08004141 WMA_LOGE("%s: Failed to register UTF event callback", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142}
4143
4144/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004145 * wma_utf_cmd() - utf command
4146 * @wma_handle: wma handle
4147 * @data: data
4148 * @len: length
4149 *
Govind Singhd76a5b02016-03-08 15:12:14 +05304150 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07004152static QDF_STATUS wma_utf_cmd(tp_wma_handle wma_handle, uint8_t *data,
4153 uint16_t len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004154{
Govind Singhd76a5b02016-03-08 15:12:14 +05304155 struct pdev_utf_params param = {0};
4156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 wma_handle->utf_event_info.length = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05304158 param.utf_payload = data;
4159 param.len = len;
4160
4161 return wmi_unified_pdev_utf_cmd_send(wma_handle->wmi_handle, &param,
4162 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163}
4164
4165/**
4166 * wma_process_ftm_command() - process ftm command
4167 * @wma_handle: wma handle
4168 * @msg_buffer: message buffer
4169 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304170 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004171 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304172QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004173wma_process_ftm_command(tp_wma_handle wma_handle,
4174 struct ar6k_testmode_cmd_data *msg_buffer)
4175{
4176 uint8_t *data = NULL;
4177 uint16_t len = 0;
4178 int ret;
4179
4180 if (!msg_buffer)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304181 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004182
Anurag Chouhan6d760662016-02-20 16:05:43 +05304183 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184 WMA_LOGE("FTM command issued in non-FTM mode");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304185 qdf_mem_free(msg_buffer->data);
4186 qdf_mem_free(msg_buffer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304187 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188 }
4189
4190 data = msg_buffer->data;
4191 len = msg_buffer->len;
4192
4193 ret = wma_utf_cmd(wma_handle, data, len);
4194
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304195 qdf_mem_free(msg_buffer->data);
4196 qdf_mem_free(msg_buffer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197
4198 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304199 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004200
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304201 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202}
4203#endif /* QCA_WIFI_FTM */
4204
Jeff Johnsonabb74042017-08-31 11:44:55 -07004205QDF_STATUS wma_get_wcnss_software_version(uint8_t *version,
4206 uint32_t version_buffer_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004208 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209
4210 if (NULL == wma_handle) {
4211 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304212 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004213 }
4214
Jeff Johnsonabb74042017-08-31 11:44:55 -07004215 snprintf(version, version_buffer_size, "%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216 (unsigned int)wma_handle->target_fw_version);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304217 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218}
4219
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004220/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
4222 * @vdev_id: VDEV whose MAC ID is required
4223 *
4224 * Get MAC id corresponding to a vdev id from the WMA structure
4225 *
4226 * Return: Negative value on failure and MAC id on success
4227 */
4228int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
4229{
4230 tp_wma_handle wma;
4231
Anurag Chouhan6d760662016-02-20 16:05:43 +05304232 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 if (!wma) {
4234 WMA_LOGE("%s: Invalid WMA handle", __func__);
4235 return -EINVAL;
4236 }
4237
4238 if (wma->interfaces)
4239 return wma->interfaces[vdev_id].mac_id;
4240
4241 return -EINVAL;
4242}
4243
4244/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 * wma_update_intf_hw_mode_params() - Update WMA params
4246 * @vdev_id: VDEV id whose params needs to be updated
4247 * @mac_id: MAC id to be updated
4248 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
4249 *
4250 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
4251 *
4252 * Return: None
4253 */
4254void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
4255 uint32_t cfgd_hw_mode_index)
4256{
4257 tp_wma_handle wma;
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004258 uint32_t param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259
Anurag Chouhan6d760662016-02-20 16:05:43 +05304260 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 if (!wma) {
4262 WMA_LOGE("%s: Invalid WMA handle", __func__);
4263 return;
4264 }
4265
4266 if (!wma->interfaces) {
4267 WMA_LOGE("%s: Interface is NULL", __func__);
4268 return;
4269 }
4270
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004271 if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) {
4272 WMA_LOGE("%s: Invalid index", __func__);
4273 return;
4274 }
4275
4276 param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004277 wma->interfaces[vdev_id].mac_id = mac_id;
4278 if (mac_id == 0) {
4279 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304280 WMA_HW_MODE_MAC0_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004281 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304282 WMA_HW_MODE_MAC0_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283 } else {
4284 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304285 WMA_HW_MODE_MAC1_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304287 WMA_HW_MODE_MAC1_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288 }
4289}
4290
4291/**
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004292 * wma_get_vht_ch_width - return vht channel width
4293 *
4294 * Return: return vht channel width
4295 */
4296uint32_t wma_get_vht_ch_width(void)
4297{
4298 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304299 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004300
4301 if (NULL == wm_hdl)
4302 return fw_ch_wd;
4303
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004304 if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004305 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004306 else if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
4307 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004308
4309 return fw_ch_wd;
4310}
Govind Singhd76a5b02016-03-08 15:12:14 +05304311
4312/**
Krunal Soniaa664da2016-06-15 23:46:40 -07004313 * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
4314 * @mask: given bitmask
4315 *
4316 * This helper function should return number of setbits from bitmask
4317 *
4318 * Return: number of setbits from bitmask
4319 */
4320uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
4321{
4322 uint32_t num_of_setbits = 0;
4323
4324 while (mask) {
4325 mask &= (mask - 1);
4326 num_of_setbits++;
4327 }
4328 return num_of_setbits;
4329}
4330
4331/**
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004332 * wma_is_csa_offload_enabled - checks fw CSA offload capability
4333 *
4334 * Return: true or false
4335 */
4336
4337bool wma_is_csa_offload_enabled(void)
4338{
4339 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4340
4341 if (!wma)
4342 return false;
4343
4344 return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4345 WMI_SERVICE_CSA_OFFLOAD);
4346}
4347/**
Govind Singhd76a5b02016-03-08 15:12:14 +05304348 * wma_config_debug_module_cmd - set debug log config
4349 * @wmi_handle: wmi layer handle
4350 * @param: debug log parameter
4351 * @val: debug log value
4352 * @module_id_bitmap: debug module id bitmap
4353 * @bitmap_len: debug module bitmap length
4354 *
4355 * Return: QDF_STATUS_SUCCESS for success or error code
4356 */
4357QDF_STATUS
4358wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
4359 A_UINT32 val, A_UINT32 *module_id_bitmap,
4360 A_UINT32 bitmap_len)
4361{
4362 struct dbglog_params dbg_param;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004363
Govind Singhd76a5b02016-03-08 15:12:14 +05304364 dbg_param.param = param;
4365 dbg_param.val = val;
4366 dbg_param.module_id_bitmap = module_id_bitmap;
4367 dbg_param.bitmap_len = bitmap_len;
4368
4369 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
4370}
Peng Xu8fdaa492016-06-22 10:20:47 -07004371
4372/**
4373 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
4374 *
4375 * This function checks if driver is capable of p2p listen offload
4376 * true: capable of p2p offload
4377 * false: not capable
4378 *
4379 * Return: true - capable, false - not capable
4380 */
4381bool wma_is_p2p_lo_capable(void)
4382{
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004383 return wma_is_service_enabled(WMI_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT);
Peng Xu8fdaa492016-06-22 10:20:47 -07004384}
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004385
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004386bool wma_capability_enhanced_mcast_filter(void)
4387{
4388 return wma_is_service_enabled(WMI_SERVICE_ENHANCED_MCAST_FILTER);
4389}
4390
4391
Mukul Sharmaf9047232017-03-02 16:58:56 +05304392bool wma_is_vdev_up(uint8_t vdev_id)
4393{
4394 struct wlan_objmgr_vdev *vdev;
4395 tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
4396 enum wlan_vdev_state state = WLAN_VDEV_S_INIT;
4397
4398 if (!wma) {
4399 WMA_LOGE("%s: WMA context is invald!", __func__);
4400 return false;
4401 }
4402
4403 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
4404 WLAN_LEGACY_WMA_ID);
4405 if (vdev) {
4406 wlan_vdev_obj_lock(vdev);
4407 state = wlan_vdev_mlme_get_state(vdev);
4408 wlan_vdev_obj_unlock(vdev);
4409 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4410 }
Mukul Sharmaf9047232017-03-02 16:58:56 +05304411 return (state == WLAN_VDEV_S_RUN) ? true : false;
4412}
4413
Dustin Brownec2c92e2017-07-26 11:13:49 -07004414void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004415{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004416 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4417
4418 cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4419 qdf_wake_lock_timeout_acquire(wl, msec);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004420 qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004421}
4422
Dustin Brownec2c92e2017-07-26 11:13:49 -07004423void wma_release_wakelock(qdf_wake_lock_t *wl)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004424{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004425 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4426
4427 qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004428 qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004429}
4430
Dustin Brownd5f12942017-03-10 11:06:25 -08004431QDF_STATUS
4432wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
4433{
4434 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004435 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
Dustin Brownd5f12942017-03-10 11:06:25 -08004436
Dustin Brownec2c92e2017-07-26 11:13:49 -07004437 wma_acquire_wakelock(&vdev->vdev_start_wakelock,
4438 WMA_VDEV_START_REQUEST_TIMEOUT);
Dustin Brownd5f12942017-03-10 11:06:25 -08004439 status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
4440 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004441 wma_release_wakelock(&vdev->vdev_start_wakelock);
Dustin Brownd5f12942017-03-10 11:06:25 -08004442
4443 return status;
4444}
4445
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004446QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4447{
4448 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004449 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004450
Dustin Brownec2c92e2017-07-26 11:13:49 -07004451 wma_acquire_wakelock(&vdev->vdev_stop_wakelock,
4452 WMA_VDEV_STOP_REQUEST_TIMEOUT);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004453 status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id);
4454 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004455 wma_release_wakelock(&vdev->vdev_stop_wakelock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004456
4457 return status;
4458}
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004459
4460bool wma_is_service_enabled(WMI_SERVICE service_type)
4461{
4462 tp_wma_handle wma;
4463 wma = cds_get_context(QDF_MODULE_ID_WMA);
4464 if (!wma) {
4465 WMA_LOGE("%s: Invalid WMA handle", __func__);
4466 return false;
4467 }
4468
4469 return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, service_type);
4470}
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004471
Dustin Brownec2c92e2017-07-26 11:13:49 -07004472QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
4473 struct vdev_up_params *params,
4474 uint8_t bssid[IEEE80211_ADDR_LEN])
4475{
4476 QDF_STATUS status;
4477 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
4478
4479 status = wmi_unified_vdev_up_send(wma->wmi_handle, bssid, params);
4480 wma_release_wakelock(&vdev->vdev_start_wakelock);
4481
4482 return status;
4483}
4484
4485QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4486{
4487 QDF_STATUS status;
4488 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
4489
4490 status = wmi_unified_vdev_down_send(wma->wmi_handle, vdev_id);
4491 wma_release_wakelock(&vdev->vdev_start_wakelock);
4492
4493 return status;
4494}
4495
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004496tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
4497{
4498 switch (type) {
4499 case WMI_PEER_TYPE_DEFAULT:
4500 return WIFI_PEER_STA;
4501 case WMI_PEER_TYPE_BSS:
4502 return WIFI_PEER_AP;
4503 case WMI_PEER_TYPE_TDLS:
4504 return WIFI_PEER_TDLS;
4505 case WMI_PEER_TYPE_NAN_DATA:
4506 return WIFI_PEER_NAN;
4507 default:
4508 WMA_LOGE("Cannot map wmi_peer_type %d to HAL peer type", type);
4509 return WIFI_PEER_INVALID;
4510 }
4511}
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304512
4513int wma_chip_power_save_failure_detected_handler(void *handle,
4514 uint8_t *cmd_param_info,
4515 uint32_t len)
4516{
4517 tp_wma_handle wma = (tp_wma_handle)handle;
4518 WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
4519 wmi_chip_power_save_failure_detected_fixed_param *event;
4520 struct chip_pwr_save_fail_detected_params pwr_save_fail_params;
4521 tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(
4522 QDF_MODULE_ID_PE);
4523 if (wma == NULL) {
4524 WMA_LOGE("%s: wma_handle is NULL", __func__);
4525 return -EINVAL;
4526 }
4527 if (!mac) {
4528 WMA_LOGE("%s: Invalid mac context", __func__);
4529 return -EINVAL;
4530 }
4531 if (!mac->sme.chip_power_save_fail_cb) {
4532 WMA_LOGE("%s: Callback not registered", __func__);
4533 return -EINVAL;
4534 }
4535
4536 param_buf =
4537 (WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
4538 cmd_param_info;
4539 if (!param_buf) {
4540 WMA_LOGE("%s: Invalid pwr_save_fail_params breached event",
4541 __func__);
4542 return -EINVAL;
4543 }
4544 event = param_buf->fixed_param;
4545 pwr_save_fail_params.failure_reason_code =
4546 event->power_save_failure_reason_code;
4547 pwr_save_fail_params.wake_lock_bitmap[0] =
4548 event->protocol_wake_lock_bitmap[0];
4549 pwr_save_fail_params.wake_lock_bitmap[1] =
4550 event->protocol_wake_lock_bitmap[1];
4551 pwr_save_fail_params.wake_lock_bitmap[2] =
4552 event->protocol_wake_lock_bitmap[2];
4553 pwr_save_fail_params.wake_lock_bitmap[3] =
4554 event->protocol_wake_lock_bitmap[3];
4555 mac->sme.chip_power_save_fail_cb(mac->hHdd,
4556 &pwr_save_fail_params);
4557
4558 WMA_LOGD("%s: Invoke HDD pwr_save_fail callback", __func__);
4559 return 0;
4560}