blob: a47582c14be6f945aae0da8027c645107536b58a [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Yun Park01a45f72018-01-04 15:30:59 -08002 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019/**
20 * DOC: wma_utis.c
21 * This file contains utilities and stats related functions.
22 */
23
24/* Header files */
25
26#include "wma.h"
27#include "wma_api.h"
28#include "cds_api.h"
29#include "wmi_unified_api.h"
30#include "wlan_qct_sys.h"
31#include "wni_api.h"
32#include "ani_global.h"
33#include "wmi_unified.h"
34#include "wni_cfg.h"
35#include "cfg_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036
Nirav Shahcbc6d722016-03-01 16:24:53 +053037#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053038#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053039#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040
41#include "wma_types.h"
42#include "lim_api.h"
43#include "lim_session_utils.h"
44
45#include "cds_utils.h"
46
47#if !defined(REMOVE_PKT_LOG)
48#include "pktlog_ac.h"
49#endif /* REMOVE_PKT_LOG */
50
51#include "dbglog_host.h"
52#include "csr_api.h"
53#include "ol_fw.h"
54
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080055#include "wma_internal.h"
Tushnim Bhattacharyya51258a72017-03-13 12:55:02 -070056#include "wlan_policy_mgr_api.h"
Govind Singhd76a5b02016-03-08 15:12:14 +053057#include "wmi_unified_param.h"
Naveen Rawatc0c91cd2015-11-05 14:27:37 -080058#include "linux/ieee80211.h"
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080059#include <cdp_txrx_handle.h>
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -070060#include "cds_reg_service.h"
Arunk Khandavalli2462f462018-01-25 14:41:02 +053061#include "target_if.h"
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -070062
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063/* MCS Based rate table */
64/* HT MCS parameters with Nss = 1 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080065static struct index_data_rate_type mcs_nss1[] = {
66 /* MCS L20 S20 L40 S40 */
67 {0, {65, 72}, {135, 150 } },
68 {1, {130, 144}, {270, 300 } },
69 {2, {195, 217}, {405, 450 } },
70 {3, {260, 289}, {540, 600 } },
71 {4, {390, 433}, {815, 900 } },
72 {5, {520, 578}, {1080, 1200} },
73 {6, {585, 650}, {1215, 1350} },
74 {7, {650, 722}, {1350, 1500} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075};
76
77/* HT MCS parameters with Nss = 2 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080078static struct index_data_rate_type mcs_nss2[] = {
79 /* MCS L20 S20 L40 S40 */
80 {0, {130, 144}, {270, 300 } },
81 {1, {260, 289}, {540, 600 } },
82 {2, {390, 433}, {810, 900 } },
83 {3, {520, 578}, {1080, 1200} },
84 {4, {780, 867}, {1620, 1800} },
85 {5, {1040, 1156}, {2160, 2400} },
86 {6, {1170, 1300}, {2430, 2700} },
87 {7, {1300, 1440}, {2700, 3000} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088};
89
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080090/* MCS Based VHT rate table */
91/* MCS parameters with Nss = 1*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -080092static struct index_vht_data_rate_type vht_mcs_nss1[] = {
93 /* MCS L20 S20 L40 S40 L80 S80 */
94 {0, {65, 72 }, {135, 150}, {293, 325} },
95 {1, {130, 144}, {270, 300}, {585, 650} },
96 {2, {195, 217}, {405, 450}, {878, 975} },
97 {3, {260, 289}, {540, 600}, {1170, 1300} },
98 {4, {390, 433}, {810, 900}, {1755, 1950} },
99 {5, {520, 578}, {1080, 1200}, {2340, 2600} },
100 {6, {585, 650}, {1215, 1350}, {2633, 2925} },
101 {7, {650, 722}, {1350, 1500}, {2925, 3250} },
102 {8, {780, 867}, {1620, 1800}, {3510, 3900} },
103 {9, {865, 960}, {1800, 2000}, {3900, 4333} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104};
105
106/*MCS parameters with Nss = 2*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800107static struct index_vht_data_rate_type vht_mcs_nss2[] = {
108 /* MCS L20 S20 L40 S40 L80 S80 */
109 {0, {130, 144}, {270, 300}, { 585, 650} },
110 {1, {260, 289}, {540, 600}, {1170, 1300} },
111 {2, {390, 433}, {810, 900}, {1755, 1950} },
112 {3, {520, 578}, {1080, 1200}, {2340, 2600} },
113 {4, {780, 867}, {1620, 1800}, {3510, 3900} },
114 {5, {1040, 1156}, {2160, 2400}, {4680, 5200} },
115 {6, {1170, 1300}, {2430, 2700}, {5265, 5850} },
116 {7, {1300, 1444}, {2700, 3000}, {5850, 6500} },
117 {8, {1560, 1733}, {3240, 3600}, {7020, 7800} },
118 {9, {1730, 1920}, {3600, 4000}, {7800, 8667} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800119};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120
121#ifdef BIG_ENDIAN_HOST
122
123/* ############# function definitions ############ */
124
125/**
126 * wma_swap_bytes() - swap bytes
127 * @pv: buffer
128 * @n: swap bytes
129 *
130 * Return: none
131 */
132void wma_swap_bytes(void *pv, uint32_t n)
133{
134 int32_t no_words;
135 int32_t i;
136 uint32_t *word_ptr;
137
138 no_words = n / sizeof(uint32_t);
139 word_ptr = (uint32_t *) pv;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700140 for (i = 0; i < no_words; i++)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141 *(word_ptr + i) = __cpu_to_le32(*(word_ptr + i));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142}
143
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700144#define SWAPME(x, len) wma_swap_bytes(&x, len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145#endif /* BIG_ENDIAN_HOST */
146
147/**
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800148 * wma_mcs_rate_match() - find the match mcs rate
149 * @match_rate: the rate to look up
150 * @is_sgi: return if the SGI rate is found
151 * @nss: the nss in use
152 * @nss1_rate: the nss1 rate
153 * @nss1_srate: the nss1 SGI rate
154 * @nss2_rate: the nss2 rate
155 * @nss2_srate: the nss2 SGI rate
156 *
157 * This is a helper function to find the match of the tx_rate
158 * in terms of the nss1/nss2 rate with non-SGI/SGI.
159 *
160 * Return: the found rate or 0 otherwise
161 */
162static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi,
163 uint8_t nss, uint16_t nss1_rate,
164 uint16_t nss1_srate,
165 uint16_t nss2_rate,
166 uint16_t nss2_srate)
167{
168 WMA_LOGD("%s match_rate: %d, %d %d %d %d",
169 __func__, match_rate, nss1_rate, nss1_srate, nss2_rate,
170 nss2_srate);
171
172 if (match_rate == nss1_rate) {
173 return nss1_rate;
174 } else if (match_rate == nss1_srate) {
175 *is_sgi = true;
176 return nss1_srate;
177 } else if (nss == 2 && match_rate == nss2_rate)
178 return nss2_rate;
179 else if (nss == 2 && match_rate == nss2_srate) {
180 *is_sgi = true;
181 return nss2_srate;
182 } else
183 return 0;
184}
185
186/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187 * wma_get_mcs_idx() - get mcs index
188 * @maxRate: max rate
189 * @rate_flags: rate flags
190 * @nss: number of nss
191 * @mcsRateFlag: mcs rate flag
192 *
193 * Return: return mcs index
194 */
195static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
196 uint8_t nss, uint8_t *mcsRateFlag)
197{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800198 uint8_t index = 0;
Arif Hussainb8fef842016-07-19 09:43:13 -0700199 uint16_t match_rate = 0;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800200 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800201
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800202 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
203 __func__, maxRate, rate_flags, nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204
205 *mcsRateFlag = rate_flags;
206 *mcsRateFlag &= ~eHAL_TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800207 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800208 if (rate_flags & eHAL_TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800209 /* check for vht80 nss1/2 rate set */
210 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
211 vht_mcs_nss1[index].ht80_rate[0],
212 vht_mcs_nss1[index].ht80_rate[1],
213 vht_mcs_nss2[index].ht80_rate[0],
214 vht_mcs_nss2[index].ht80_rate[1]);
215 if (match_rate)
216 goto rate_found;
217 }
218 if ((rate_flags & eHAL_TX_RATE_VHT40) |
219 (rate_flags & eHAL_TX_RATE_VHT80)) {
220 /* check for vht40 nss1/2 rate set */
221 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
222 vht_mcs_nss1[index].ht40_rate[0],
223 vht_mcs_nss1[index].ht40_rate[1],
224 vht_mcs_nss2[index].ht40_rate[0],
225 vht_mcs_nss2[index].ht40_rate[1]);
226 if (match_rate) {
227 *mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
228 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 }
230 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800231 if ((rate_flags & eHAL_TX_RATE_VHT20) |
232 (rate_flags & eHAL_TX_RATE_VHT40) |
233 (rate_flags & eHAL_TX_RATE_VHT80)) {
234 /* check for vht20 nss1/2 rate set */
235 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
236 vht_mcs_nss1[index].ht20_rate[0],
237 vht_mcs_nss1[index].ht20_rate[1],
238 vht_mcs_nss2[index].ht20_rate[0],
239 vht_mcs_nss2[index].ht20_rate[1]);
240 if (match_rate) {
241 *mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 |
242 eHAL_TX_RATE_VHT40);
243 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800244 }
245 }
246 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800247 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800248 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800249 /* check for ht40 nss1/2 rate set */
250 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
251 mcs_nss1[index].ht40_rate[0],
252 mcs_nss1[index].ht40_rate[1],
253 mcs_nss2[index].ht40_rate[0],
254 mcs_nss2[index].ht40_rate[1]);
255 if (match_rate) {
256 *mcsRateFlag = eHAL_TX_RATE_HT40;
Yeshwanth Sriram Guntukad18c7a22018-02-02 15:22:30 +0530257 if (nss == 2)
258 index += MAX_HT_MCS_IDX;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800259 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 }
261 }
wadesongbf665542017-02-28 14:30:51 +0800262 if ((rate_flags & eHAL_TX_RATE_HT20) ||
263 (rate_flags & eHAL_TX_RATE_HT40)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800264 /* check for ht20 nss1/2 rate set */
265 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
266 mcs_nss1[index].ht20_rate[0],
267 mcs_nss1[index].ht20_rate[1],
268 mcs_nss2[index].ht20_rate[0],
269 mcs_nss2[index].ht20_rate[1]);
270 if (match_rate) {
271 *mcsRateFlag = eHAL_TX_RATE_HT20;
Yeshwanth Sriram Guntukad18c7a22018-02-02 15:22:30 +0530272 if (nss == 2)
273 index += MAX_HT_MCS_IDX;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800274 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275 }
276 }
277 }
278
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800279rate_found:
280 /* set SGI flag only if this is SGI rate */
281 if (match_rate && is_sgi == true)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800282 *mcsRateFlag |= eHAL_TX_RATE_SGI;
283
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800284 WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
285 __func__, match_rate, index, *mcsRateFlag, is_sgi);
286
287 return match_rate ? index : INVALID_MCS_IDX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288}
289
290/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530291 * wma_peek_vdev_req() - peek what request message is queued for response.
292 * the function does not delete the node after found
293 * @wma: WMA handle
294 * @vdev_id: vdev ID
295 * @type: request message type
296 *
297 * Return: the request message found
298 */
299static struct wma_target_req *wma_peek_vdev_req(tp_wma_handle wma,
300 uint8_t vdev_id, uint8_t type)
301{
302 struct wma_target_req *req_msg = NULL;
303 bool found = false;
304 qdf_list_node_t *node1 = NULL, *node2 = NULL;
305
306 qdf_spin_lock_bh(&wma->vdev_respq_lock);
307 if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&wma->vdev_resp_queue,
308 &node2)) {
309 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530310 return NULL;
311 }
312
313 do {
314 node1 = node2;
315 req_msg = qdf_container_of(node1, struct wma_target_req, node);
316 if (req_msg->vdev_id != vdev_id)
317 continue;
318 if (req_msg->type != type)
319 continue;
320
321 found = true;
322 break;
323 } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&wma->vdev_resp_queue,
324 node1, &node2));
325 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
326 if (!found) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800327 WMA_LOGE(FL("target request not found for vdev_id %d type %d"),
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530328 vdev_id, type);
329 return NULL;
330 }
331 WMA_LOGD(FL("target request found for vdev id: %d type %d msg %d"),
332 vdev_id, type, req_msg->msg_type);
333 return req_msg;
334}
335
336void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id,
337 int32_t rssi)
338{
339 struct sir_lost_link_info *lost_link_info;
340 QDF_STATUS qdf_status;
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800341 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530342
343 /* report lost link information only for STA mode */
Mukul Sharmaf9047232017-03-02 16:58:56 +0530344 if (wma_is_vdev_up(vdev_id) &&
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530345 (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) &&
346 (0 == wma->interfaces[vdev_id].sub_type)) {
347 lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
348 if (NULL == lost_link_info) {
349 WMA_LOGE("%s: failed to allocate memory", __func__);
350 return;
351 }
352 lost_link_info->vdev_id = vdev_id;
353 lost_link_info->rssi = rssi;
354 sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
355 sme_msg.bodyptr = lost_link_info;
356 sme_msg.bodyval = 0;
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800357 WMA_LOGD("%s: post msg to SME, bss_idx %d, rssi %d", __func__,
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530358 lost_link_info->vdev_id, lost_link_info->rssi);
359
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800360 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530361 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
362 WMA_LOGE("%s: fail to post msg to SME", __func__);
363 qdf_mem_free(lost_link_info);
364 }
365 }
366}
367
368/**
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700369 * host_map_smps_mode() - map fw smps mode to enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370 * @fw_smps_mode: fw smps mode
371 *
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700372 * Return: return enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700374enum eSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700376 enum eSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
377
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 switch (fw_smps_mode) {
379 case WMI_SMPS_FORCED_MODE_STATIC:
380 smps_mode = STATIC_SMPS_MODE;
381 break;
382 case WMI_SMPS_FORCED_MODE_DYNAMIC:
383 smps_mode = DYNAMIC_SMPS_MODE;
384 break;
385 default:
386 smps_mode = SMPS_MODE_DISABLED;
387 }
388
389 return smps_mode;
390}
391
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800392/**
393 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
394 * mode commmand param
395 * @smps_mode: SMPS mode according to the protocol
396 *
397 * Return: int > 0 for success else failure
398 */
399int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
400{
401 int param = -EINVAL;
402
403 switch (smps_mode) {
404 case STATIC_SMPS_MODE:
405 param = WMI_SMPS_FORCED_MODE_STATIC;
406 break;
407 case DYNAMIC_SMPS_MODE:
408 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
409 break;
410 case SMPS_MODE_DISABLED:
411 param = WMI_SMPS_FORCED_MODE_DISABLED;
412 break;
413 default:
414 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
415 smps_mode);
416 }
417 return param;
418}
419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420#ifdef WLAN_FEATURE_STATS_EXT
421/**
422 * wma_stats_ext_event_handler() - extended stats event handler
423 * @handle: wma handle
424 * @event_buf: event buffer received from fw
425 * @len: length of data
426 *
427 * Return: 0 for success or error code
428 */
429int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
430 uint32_t len)
431{
432 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
433 tSirStatsExtEvent *stats_ext_event;
434 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530435 QDF_STATUS status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -0700436 struct scheduler_msg cds_msg = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800437 uint8_t *buf_ptr;
438 uint32_t alloc_len;
439
440 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
441
442 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
443 if (!param_buf) {
444 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
445 return -EINVAL;
446 }
447
448 stats_ext_info = param_buf->fixed_param;
449 buf_ptr = (uint8_t *) stats_ext_info;
450
451 alloc_len = sizeof(tSirStatsExtEvent);
452 alloc_len += stats_ext_info->data_len;
453
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700454 if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE -
Yeshwanth Sriram Guntukaf71b48e2018-04-20 15:18:08 +0530455 WMI_TLV_HDR_SIZE - sizeof(*stats_ext_info)) ||
456 stats_ext_info->data_len > param_buf->num_data) {
Abhinav Kumara03659c2017-12-28 15:18:07 +0530457 WMA_LOGE("Excess data_len:%d, num_data:%d",
458 stats_ext_info->data_len, param_buf->num_data);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700459 return -EINVAL;
460 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530461 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462 if (NULL == stats_ext_event) {
463 WMA_LOGE("%s: Memory allocation failure", __func__);
464 return -ENOMEM;
465 }
466
467 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
468
469 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
470 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530471 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472 buf_ptr, stats_ext_event->event_data_len);
473
474 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
475 cds_msg.bodyptr = (void *)stats_ext_event;
476 cds_msg.bodyval = 0;
477
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800478 status = scheduler_post_msg(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530479 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530481 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482 return -EFAULT;
483 }
484
485 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
486 return 0;
487}
488#endif /* WLAN_FEATURE_STATS_EXT */
489
Nirav Shah93e789e2016-04-14 19:47:43 +0530490
Govind Singha471e5e2015-10-12 17:11:14 +0530491/**
492 * wma_profile_data_report_event_handler() - fw profiling handler
493 * @handle: wma handle
494 * @event_buf: event buffer received from fw
495 * @len: length of data
496 *
497 * Return: 0 for success or error code
498 */
499int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
500 uint32_t len)
501{
502 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
503 wmi_wlan_profile_ctx_t *profile_ctx;
504 wmi_wlan_profile_t *profile_data;
505 uint32_t i = 0;
506 uint32_t entries;
507 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530508 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530509
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700510 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
Govind Singha471e5e2015-10-12 17:11:14 +0530511 if (!param_buf) {
512 WMA_LOGE("%s: Invalid profile data event buf", __func__);
513 return -EINVAL;
514 }
515 profile_ctx = param_buf->profile_ctx;
516 buf_ptr = (uint8_t *)profile_ctx;
517 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
518 profile_data = (wmi_wlan_profile_t *) buf_ptr;
519 entries = profile_ctx->bin_count;
Amar Singhal4bd22232017-10-04 13:24:00 -0700520
521 if (entries > param_buf->num_profile_data) {
522 WMA_LOGE("FW bin count %d more than data %d in TLV hdr",
523 entries,
524 param_buf->num_profile_data);
525 return -EINVAL;
526 }
527
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530528 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530529 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530530 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530531 "TOT: %d\n"
532 "tx_msdu_cnt: %d\n"
533 "tx_mpdu_cnt: %d\n"
534 "tx_ppdu_cnt: %d\n"
535 "rx_msdu_cnt: %d\n"
536 "rx_mpdu_cnt: %d\n"
537 "bin_count: %d\n",
538 profile_ctx->tot,
539 profile_ctx->tx_msdu_cnt,
540 profile_ctx->tx_mpdu_cnt,
541 profile_ctx->tx_ppdu_cnt,
542 profile_ctx->rx_msdu_cnt,
543 profile_ctx->rx_mpdu_cnt,
544 profile_ctx->bin_count);
545
Nirav Shah93e789e2016-04-14 19:47:43 +0530546 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
547 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
548
Govind Singha471e5e2015-10-12 17:11:14 +0530549 for (i = 0; i < entries; i++) {
550 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
551 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530552 snprintf(temp_str, sizeof(temp_str),
553 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530554 profile_data[i].id,
555 profile_data[i].cnt,
556 profile_data[i].tot,
557 profile_data[i].min,
558 profile_data[i].max,
559 profile_data[i].hist_intvl,
560 profile_data[i].hist[0],
561 profile_data[i].hist[1],
562 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530563 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
564 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530565 }
566
567 return 0;
568}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569
570#ifdef WLAN_FEATURE_LINK_LAYER_STATS
571
Zhang Qian73c348a2017-03-13 16:15:55 +0800572#define WMA_FILL_TX_STATS(eve, msg) do {\
573 (msg)->msdus = (eve)->tx_msdu_cnt;\
574 (msg)->mpdus = (eve)->tx_mpdu_cnt;\
575 (msg)->ppdus = (eve)->tx_ppdu_cnt;\
576 (msg)->bytes = (eve)->tx_bytes;\
577 (msg)->drops = (eve)->tx_msdu_drop_cnt;\
578 (msg)->drop_bytes = (eve)->tx_drop_bytes;\
579 (msg)->retries = (eve)->tx_mpdu_retry_cnt;\
580 (msg)->failed = (eve)->tx_mpdu_fail_cnt;\
581} while (0)
582
583#define WMA_FILL_RX_STATS(eve, msg) do {\
584 (msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
585 (msg)->bytes = (eve)->mac_rx_bytes;\
586 (msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
587 (msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
588 (msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
589 (msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
590 (msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
591} while (0)
592
593/**
594 * wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
595 * @len: buffer length output
596 * @peer_num: peer number
597 * @fixed_param: fixed parameters in WMI event
598 *
599 * Structure of the stats message
600 * LL_EXT_STATS
601 * |
602 * |--Channel stats[1~n]
603 * |--Peer[1~n]
604 * |
605 * +---Signal
606 * +---TX
607 * | +---BE
608 * | +---BK
609 * | +---VI
610 * | +---VO
611 * |
612 * +---RX
613 * +---BE
614 * +---BK
615 * +---VI
616 * +---VO
617 * For each Access Category, the arregation and mcs
618 * stats are as this:
619 * TX
620 * +-BE/BK/VI/VO
621 * +----tx_mpdu_aggr_array
622 * +----tx_succ_mcs_array
623 * +----tx_fail_mcs_array
624 * +----tx_delay_array
625 * RX
626 * +-BE/BK/VI/VO
627 * +----rx_mpdu_aggr_array
628 * +----rx_mcs_array
629 *
630 * return: Address for result buffer.
631 */
632static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
633 uint32_t peer_num,
634 wmi_report_stats_event_fixed_param *fixed_param)
635{
636 tSirLLStatsResults *buf;
637 uint32_t buf_len;
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530638 uint32_t total_array_len, total_peer_len;
639 bool excess_data = false;
Zhang Qian73c348a2017-03-13 16:15:55 +0800640
641 if (!len || !fixed_param) {
642 WMA_LOGE(FL("Invalid input parameters."));
643 return NULL;
644 }
645
646 /*
647 * Result buffer has a structure like this:
648 * ---------------------------------
649 * | trigger_cond_i |
650 * +-------------------------------+
651 * | cca_chgd_bitmap |
652 * +-------------------------------+
653 * | sig_chgd_bitmap |
654 * +-------------------------------+
655 * | tx_chgd_bitmap |
656 * +-------------------------------+
657 * | rx_chgd_bitmap |
658 * +-------------------------------+
659 * | peer_num |
660 * +-------------------------------+
661 * | channel_num |
662 * +-------------------------------+
663 * | tx_mpdu_aggr_array_len |
664 * +-------------------------------+
665 * | tx_succ_mcs_array_len |
666 * +-------------------------------+
667 * | tx_fail_mcs_array_len |
668 * +-------------------------------+
669 * | tx_delay_array_len |
670 * +-------------------------------+
671 * | rx_mpdu_aggr_array_len |
672 * +-------------------------------+
673 * | rx_mcs_array_len |
674 * +-------------------------------+
675 * | pointer to CCA stats |
676 * +-------------------------------+
677 * | CCA stats |
678 * +-------------------------------+
679 * | peer_stats |----+
680 * +-------------------------------+ |
681 * | TX aggr/mcs parameters array | |
682 * | Length of this buffer is | |
683 * | not fixed. |<-+ |
684 * +-------------------------------+ | |
685 * | per peer tx stats |--+ |
686 * | BE | <--+
687 * | BK | |
688 * | VI | |
689 * | VO | |
690 * +-------------------------------+ |
691 * | TX aggr/mcs parameters array | |
692 * | Length of this buffer is | |
693 * | not fixed. |<-+ |
694 * +-------------------------------+ | |
695 * | peer peer rx stats |--+ |
696 * | BE | <--+
697 * | BK |
698 * | VI |
699 * | VO |
700 * ---------------------------------
701 */
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530702
Zhang Qian73c348a2017-03-13 16:15:55 +0800703 buf_len = sizeof(tSirLLStatsResults) +
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530704 sizeof(struct sir_wifi_ll_ext_stats);
705 do {
706 if (fixed_param->num_chan_cca_stats > (WMI_SVC_MSG_MAX_SIZE /
707 sizeof(struct sir_wifi_chan_cca_stats))) {
708 excess_data = true;
709 break;
710 }
711 buf_len += (fixed_param->num_chan_cca_stats *
712 sizeof(struct sir_wifi_chan_cca_stats));
713 if (fixed_param->tx_mpdu_aggr_array_len >
714 WMI_SVC_MSG_MAX_SIZE) {
715 excess_data = true;
716 break;
717 } else {
718 total_array_len = fixed_param->tx_mpdu_aggr_array_len;
719 }
720 if (fixed_param->tx_succ_mcs_array_len >
721 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
722 excess_data = true;
723 break;
724 } else {
725 total_array_len += fixed_param->tx_succ_mcs_array_len;
726 }
727 if (fixed_param->tx_fail_mcs_array_len >
728 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
729 excess_data = true;
730 break;
731 } else {
732 total_array_len += fixed_param->tx_fail_mcs_array_len;
733 }
734 if (fixed_param->tx_ppdu_delay_array_len >
735 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
736 excess_data = true;
737 break;
738 } else {
739 total_array_len += fixed_param->tx_ppdu_delay_array_len;
740 }
741 if (fixed_param->rx_mpdu_aggr_array_len >
742 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
743 excess_data = true;
744 break;
745 } else {
746 total_array_len += fixed_param->rx_mpdu_aggr_array_len;
747 }
748 if (fixed_param->rx_mcs_array_len >
749 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
750 excess_data = true;
751 break;
752 } else {
753 total_array_len += fixed_param->rx_mcs_array_len;
754 }
755
756 if (total_array_len > (WMI_SVC_MSG_MAX_SIZE /
757 (sizeof(uint32_t) * WLAN_MAX_AC))) {
758 excess_data = true;
759 break;
760 } else {
761 total_peer_len = (sizeof(uint32_t) * WLAN_MAX_AC *
762 total_array_len) +
763 (WLAN_MAX_AC *
764 (sizeof(struct sir_wifi_tx) +
765 sizeof(struct sir_wifi_rx)));
766 }
Vignesh Viswanathanca67e362017-10-04 23:42:00 +0530767 if (total_peer_len > WMI_SVC_MSG_MAX_SIZE) {
768 excess_data = true;
769 break;
770 }
Vignesh Viswanathanbd1ad032017-11-15 15:13:56 +0530771 if (peer_num > WMI_SVC_MSG_MAX_SIZE / (total_peer_len +
772 sizeof(struct sir_wifi_ll_ext_peer_stats))) {
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530773 excess_data = true;
774 break;
775 } else {
776 buf_len += peer_num *
777 (sizeof(struct sir_wifi_ll_ext_peer_stats) +
778 total_peer_len);
779 }
780 } while (0);
781
782 if (excess_data || (buf_len > WMI_SVC_MSG_MAX_SIZE)) {
783 WMA_LOGE("%s: excess wmi buffer: peer %d cca %d tx_mpdu %d tx_succ%d tx_fail %d tx_ppdu %d rx_mpdu %d rx_mcs %d",
784 __func__, peer_num, fixed_param->num_chan_cca_stats,
785 fixed_param->tx_mpdu_aggr_array_len,
786 fixed_param->tx_succ_mcs_array_len,
787 fixed_param->tx_fail_mcs_array_len,
788 fixed_param->tx_ppdu_delay_array_len,
789 fixed_param->rx_mpdu_aggr_array_len,
790 fixed_param->rx_mcs_array_len);
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530791 return NULL;
792 }
Zhang Qian73c348a2017-03-13 16:15:55 +0800793
794 buf = (tSirLLStatsResults *)qdf_mem_malloc(buf_len);
795 if (buf == NULL) {
796 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
797 buf_len = 0;
798 return NULL;
799 }
800
801 *len = buf_len;
802 return buf;
803}
804
805/**
806 * wma_fill_tx_stats() - Fix TX stats into result buffer
807 * @ll_stats: LL stats buffer
808 * @fix_param: parameters with fixed length in WMI event
809 * @param_buf: parameters without fixed length in WMI event
810 * @buf: buffer for TLV parameters
811 *
812 * Return: None
813 */
814static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
815 wmi_report_stats_event_fixed_param *fix_param,
816 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
817 uint8_t **buf, uint32_t *buf_length)
818{
819 uint8_t *result;
820 uint32_t i, j, k;
821 wmi_peer_ac_tx_stats *wmi_peer_tx;
822 wmi_tx_stats *wmi_tx;
823 struct sir_wifi_tx *tx_stats;
824 struct sir_wifi_ll_ext_peer_stats *peer_stats;
825 uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
826 uint32_t len, dst_len, tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
827 tx_fail_mcs_array_len, tx_delay_array_len;
828
829 result = *buf;
830 dst_len = *buf_length;
831 tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
832 ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
833 tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
834 ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
835 tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
836 ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
837 tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
838 ll_stats->tx_delay_array_len = tx_delay_array_len;
839 wmi_peer_tx = param_buf->peer_ac_tx_stats;
840 wmi_tx = param_buf->tx_stats;
841
842 len = fix_param->num_peer_ac_tx_stats *
843 WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
844 if (len <= dst_len) {
845 tx_mpdu_aggr = (uint32_t *)result;
846 qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
847 result += len;
848 dst_len -= len;
849 } else {
850 WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong."));
851 tx_mpdu_aggr = NULL;
852 }
853
854 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
855 tx_succ_mcs_array_len * sizeof(uint32_t);
856 if (len <= dst_len) {
857 tx_succ_mcs = (uint32_t *)result;
858 qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
859 result += len;
860 dst_len -= len;
861 } else {
862 WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong."));
863 tx_succ_mcs = NULL;
864 }
865
866 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
867 tx_fail_mcs_array_len * sizeof(uint32_t);
868 if (len <= dst_len) {
869 tx_fail_mcs = (uint32_t *)result;
870 qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
871 result += len;
872 dst_len -= len;
873 } else {
874 WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong."));
875 tx_fail_mcs = NULL;
876 }
877
878 len = fix_param->num_peer_ac_tx_stats *
879 WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
880 if (len <= dst_len) {
881 tx_delay = (uint32_t *)result;
882 qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
883 result += len;
884 dst_len -= len;
885 } else {
886 WMA_LOGE(FL("TX_DELAY buffer length is wrong."));
887 tx_delay = NULL;
888 }
889
890 /* per peer tx stats */
891 peer_stats = ll_stats->peer_stats;
892
893 for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
894 uint32_t peer_id = wmi_peer_tx[i].peer_id;
895 struct sir_wifi_tx *ac;
896 wmi_tx_stats *wmi_tx_stats;
897
898 for (j = 0; j < ll_stats->peer_num; j++) {
899 peer_stats += j;
900 if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
901 peer_stats->peer_id == peer_id)
902 break;
903 }
904
905 if (j < ll_stats->peer_num) {
906 peer_stats->peer_id = wmi_peer_tx[i].peer_id;
907 peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
908 tx_stats = (struct sir_wifi_tx *)result;
909 for (k = 0; k < WLAN_MAX_AC; k++) {
910 wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
911 ac = &tx_stats[k];
912 WMA_FILL_TX_STATS(wmi_tx_stats, ac);
913 ac->mpdu_aggr_size = tx_mpdu_aggr;
914 ac->aggr_len = tx_mpdu_aggr_array_len *
915 sizeof(uint32_t);
916 ac->success_mcs_len = tx_succ_mcs_array_len *
917 sizeof(uint32_t);
918 ac->success_mcs = tx_succ_mcs;
919 ac->fail_mcs = tx_fail_mcs;
920 ac->fail_mcs_len = tx_fail_mcs_array_len *
921 sizeof(uint32_t);
922 ac->delay = tx_delay;
923 ac->delay_len = tx_delay_array_len *
924 sizeof(uint32_t);
925 peer_stats->ac_stats[k].tx_stats = ac;
926 peer_stats->ac_stats[k].type = k;
927 tx_mpdu_aggr += tx_mpdu_aggr_array_len;
928 tx_succ_mcs += tx_succ_mcs_array_len;
929 tx_fail_mcs += tx_fail_mcs_array_len;
930 tx_delay += tx_delay_array_len;
931 }
932 result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
933 } else {
934 /*
935 * Buffer for Peer TX counter overflow.
936 * There is peer ID mismatch between TX, RX,
937 * signal counters.
938 */
939 WMA_LOGE(FL("One peer TX info is dropped."));
940
941 tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
942 tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
943 tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
944 tx_delay += tx_delay_array_len * WLAN_MAX_AC;
945 }
946 }
947 *buf = result;
948 *buf_length = dst_len;
949}
950
951/**
952 * wma_fill_rx_stats() - Fix RX stats into result buffer
953 * @ll_stats: LL stats buffer
954 * @fix_param: parameters with fixed length in WMI event
955 * @param_buf: parameters without fixed length in WMI event
956 * @buf: buffer for TLV parameters
957 *
958 * Return: None
959 */
960static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
961 wmi_report_stats_event_fixed_param *fix_param,
962 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
963 uint8_t **buf, uint32_t *buf_length)
964{
965 uint8_t *result;
966 uint32_t i, j, k;
967 uint32_t *rx_mpdu_aggr, *rx_mcs;
968 wmi_rx_stats *wmi_rx;
969 wmi_peer_ac_rx_stats *wmi_peer_rx;
970 struct sir_wifi_rx *rx_stats;
971 struct sir_wifi_ll_ext_peer_stats *peer_stats;
972 uint32_t len, dst_len, rx_mpdu_aggr_array_len, rx_mcs_array_len;
973
974 rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
975 ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
976 rx_mcs_array_len = fix_param->rx_mcs_array_len;
977 ll_stats->rx_mcs_array_len = rx_mcs_array_len;
978 wmi_peer_rx = param_buf->peer_ac_rx_stats;
979 wmi_rx = param_buf->rx_stats;
980
981 result = *buf;
982 dst_len = *buf_length;
983 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
984 WLAN_MAX_AC * rx_mpdu_aggr_array_len);
985 if (len <= dst_len) {
986 rx_mpdu_aggr = (uint32_t *)result;
987 qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
988 result += len;
989 dst_len -= len;
990 } else {
991 WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong."));
992 rx_mpdu_aggr = NULL;
993 }
994
995 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
996 WLAN_MAX_AC * rx_mcs_array_len);
997 if (len <= dst_len) {
998 rx_mcs = (uint32_t *)result;
999 qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len);
1000 result += len;
1001 dst_len -= len;
1002 } else {
1003 WMA_LOGE(FL("RX_MCS array length is wrong."));
1004 rx_mcs = NULL;
1005 }
1006
1007 /* per peer rx stats */
1008 peer_stats = ll_stats->peer_stats;
1009 for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) {
1010 uint32_t peer_id = wmi_peer_rx[i].peer_id;
1011 struct sir_wifi_rx *ac;
1012 wmi_rx_stats *wmi_rx_stats;
1013
1014 for (j = 0; j < ll_stats->peer_num; j++) {
1015 peer_stats += j;
1016 if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
1017 (peer_stats->peer_id == peer_id))
1018 break;
1019 }
1020
1021 if (j < ll_stats->peer_num) {
1022 peer_stats->peer_id = wmi_peer_rx[i].peer_id;
1023 peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
1024 peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
1025 peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
1026 peer_stats->rx_probe_reqs =
1027 wmi_peer_rx[i].rx_probe_reqs;
1028 peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
1029 rx_stats = (struct sir_wifi_rx *)result;
1030
1031 for (k = 0; k < WLAN_MAX_AC; k++) {
1032 wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
1033 ac = &rx_stats[k];
1034 WMA_FILL_RX_STATS(wmi_rx_stats, ac);
1035 ac->mpdu_aggr = rx_mpdu_aggr;
1036 ac->aggr_len = rx_mpdu_aggr_array_len *
1037 sizeof(uint32_t);
1038 ac->mcs = rx_mcs;
1039 ac->mcs_len = rx_mcs_array_len *
1040 sizeof(uint32_t);
1041 peer_stats->ac_stats[k].rx_stats = ac;
1042 peer_stats->ac_stats[k].type = k;
1043 rx_mpdu_aggr += rx_mpdu_aggr_array_len;
1044 rx_mcs += rx_mcs_array_len;
1045 }
1046 result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
1047 } else {
1048 /*
1049 * Buffer for Peer RX counter overflow.
1050 * There is peer ID mismatch between TX, RX,
1051 * signal counters.
1052 */
1053 WMA_LOGE(FL("One peer RX info is dropped."));
1054 rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
1055 rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
1056 }
1057 }
1058 *buf = result;
1059 *buf_length = dst_len;
1060}
1061
1062/**
1063 * wma_ll_stats_evt_handler() - handler for MAC layer counters.
1064 * @handle - wma handle
1065 * @event - FW event
1066 * @len - length of FW event
1067 *
1068 * return: 0 success.
1069 */
1070static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
1071 u_int32_t len)
1072{
1073 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
1074 wmi_report_stats_event_fixed_param *fixed_param;
1075 tSirLLStatsResults *link_stats_results;
1076 wmi_chan_cca_stats *wmi_cca_stats;
1077 wmi_peer_signal_stats *wmi_peer_signal;
1078 wmi_peer_ac_rx_stats *wmi_peer_rx;
1079 struct sir_wifi_ll_ext_stats *ll_stats;
1080 struct sir_wifi_ll_ext_peer_stats *peer_stats;
1081 struct sir_wifi_chan_cca_stats *cca_stats;
1082 struct sir_wifi_peer_signal_stats *peer_signal;
1083 uint8_t *result;
1084 uint32_t i, peer_num, result_size, dst_len;
1085 tpAniSirGlobal mac;
1086 struct scheduler_msg sme_msg = { 0 };
1087 QDF_STATUS qdf_status;
1088
1089 mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
1090 if (!mac) {
1091 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1092 return -EINVAL;
1093 }
1094
1095 if (!mac->sme.link_layer_stats_ext_cb) {
1096 WMA_LOGD("%s: HDD callback is null", __func__);
1097 return -EINVAL;
1098 }
1099
1100 WMA_LOGD("%s: Posting MAC counters event to HDD", __func__);
1101
1102 param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
1103 fixed_param = param_buf->fixed_param;
1104 wmi_cca_stats = param_buf->chan_cca_stats;
1105 wmi_peer_signal = param_buf->peer_signal_stats;
1106 wmi_peer_rx = param_buf->peer_ac_rx_stats;
Abhinav Kumara03659c2017-12-28 15:18:07 +05301107 if (fixed_param->num_peer_signal_stats >
1108 param_buf->num_peer_signal_stats ||
1109 fixed_param->num_peer_ac_tx_stats >
1110 param_buf->num_peer_ac_tx_stats ||
1111 fixed_param->num_peer_ac_rx_stats >
1112 param_buf->num_peer_ac_rx_stats) {
1113 WMA_LOGE("%s: excess num_peer_signal_stats:%d, num_peer_ac_tx_stats:%d, num_peer_ac_rx_stats:%d",
1114 __func__, fixed_param->num_peer_signal_stats,
1115 fixed_param->num_peer_ac_tx_stats,
1116 fixed_param->num_peer_ac_rx_stats);
1117 return -EINVAL;
1118 }
Zhang Qian73c348a2017-03-13 16:15:55 +08001119
1120 /* Get the MAX of three peer numbers */
1121 peer_num = fixed_param->num_peer_signal_stats >
1122 fixed_param->num_peer_ac_tx_stats ?
1123 fixed_param->num_peer_signal_stats :
1124 fixed_param->num_peer_ac_tx_stats;
1125 peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
1126 peer_num : fixed_param->num_peer_ac_rx_stats;
1127
1128 if (peer_num == 0)
1129 return -EINVAL;
1130
1131 link_stats_results = wma_get_ll_stats_ext_buf(&result_size,
1132 peer_num,
1133 fixed_param);
1134 if (!link_stats_results) {
1135 WMA_LOGE("%s: Fail to allocate stats buffer", __func__);
1136 return -EINVAL;
1137 }
1138 link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
1139 link_stats_results->num_peers = peer_num;
1140 link_stats_results->peer_event_number = 1;
1141 link_stats_results->moreResultToFollow = 0;
1142
1143 ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
1144 ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
1145 ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
1146 ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
1147 ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
1148 ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
1149 ll_stats->channel_num = fixed_param->num_chan_cca_stats;
1150 ll_stats->peer_num = peer_num;
1151
1152 result = (uint8_t *)ll_stats->stats;
1153 peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
1154 ll_stats->peer_stats = peer_stats;
1155
1156 for (i = 0; i < peer_num; i++) {
1157 peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
1158 peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
1159 }
1160
1161 /* Per peer signal */
1162 result_size -= sizeof(struct sir_wifi_ll_ext_stats);
1163 dst_len = sizeof(struct sir_wifi_peer_signal_stats);
1164 for (i = 0; i < fixed_param->num_peer_signal_stats; i++) {
1165 peer_stats[i].peer_id = wmi_peer_signal->peer_id;
1166 peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
1167 peer_signal = &peer_stats[i].peer_signal_stats;
1168
Zhang Qian303ebe92017-05-18 13:59:07 +08001169 WMA_LOGD("%d antennas for peer %d",
1170 wmi_peer_signal->num_chains_valid,
1171 wmi_peer_signal->peer_id);
Zhang Qian73c348a2017-03-13 16:15:55 +08001172 if (dst_len <= result_size) {
Zhang Qian303ebe92017-05-18 13:59:07 +08001173 peer_signal->vdev_id = wmi_peer_signal->vdev_id;
1174 peer_signal->peer_id = wmi_peer_signal->peer_id;
1175 peer_signal->num_chain =
1176 wmi_peer_signal->num_chains_valid;
1177 qdf_mem_copy(peer_signal->per_ant_snr,
1178 wmi_peer_signal->per_chain_snr,
1179 sizeof(peer_signal->per_ant_snr));
1180 qdf_mem_copy(peer_signal->nf,
1181 wmi_peer_signal->per_chain_nf,
1182 sizeof(peer_signal->nf));
1183 qdf_mem_copy(peer_signal->per_ant_rx_mpdus,
1184 wmi_peer_signal->per_antenna_rx_mpdus,
1185 sizeof(peer_signal->per_ant_rx_mpdus));
1186 qdf_mem_copy(peer_signal->per_ant_tx_mpdus,
1187 wmi_peer_signal->per_antenna_tx_mpdus,
1188 sizeof(peer_signal->per_ant_tx_mpdus));
Zhang Qian73c348a2017-03-13 16:15:55 +08001189 result_size -= dst_len;
1190 } else {
1191 WMA_LOGE(FL("Invalid length of PEER signal."));
1192 }
1193 wmi_peer_signal++;
1194 }
1195
1196 result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
1197 cca_stats = (struct sir_wifi_chan_cca_stats *)result;
1198 ll_stats->cca = cca_stats;
1199 dst_len = sizeof(struct sir_wifi_chan_cca_stats);
1200 for (i = 0; i < ll_stats->channel_num; i++) {
1201 if (dst_len <= result_size) {
1202 qdf_mem_copy(&cca_stats[i], &wmi_cca_stats->vdev_id,
1203 dst_len);
1204 result_size -= dst_len;
1205 } else {
1206 WMA_LOGE(FL("Invalid length of CCA."));
1207 }
1208 }
1209
1210 result += i * sizeof(struct sir_wifi_chan_cca_stats);
1211 wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
1212 &result, &result_size);
1213 wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
1214 &result, &result_size);
1215 sme_msg.type = eWMI_SME_LL_STATS_IND;
1216 sme_msg.bodyptr = (void *)link_stats_results;
1217 sme_msg.bodyval = 0;
1218 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1219 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1220 WMA_LOGP(FL("Failed to post peer stat change msg!"));
1221 qdf_mem_free(link_stats_results);
1222 return -EINVAL;
1223 }
1224
1225 return 0;
1226}
1227
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001228/**
1229 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
1230 * @handle: wma handle
1231 * @cmd_param_info: data received with event from fw
1232 * @len: length of data
1233 *
1234 * Return: 0 for success or error code
1235 */
1236static int wma_unified_link_peer_stats_event_handler(void *handle,
1237 uint8_t *cmd_param_info,
1238 uint32_t len)
1239{
1240 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1241 wmi_peer_stats_event_fixed_param *fixed_param;
1242 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
1243 wmi_rate_stats *rate_stats;
1244 tSirLLStatsResults *link_stats_results;
1245 uint8_t *results, *t_peer_stats, *t_rate_stats;
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301246 uint32_t count, rate_cnt;
1247 uint32_t total_num_rates = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
1249 size_t peer_info_size, peer_stats_size, rate_stats_size;
1250 size_t link_stats_results_size;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001251 bool excess_data = false;
1252 uint32_t buf_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253
Anurag Chouhan6d760662016-02-20 16:05:43 +05301254 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255
1256 if (!pMac) {
1257 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1258 return -EINVAL;
1259 }
1260
1261 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1262 WMA_LOGD("%s: HDD callback is null", __func__);
1263 return -EINVAL;
1264 }
1265
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1267 if (!param_tlvs) {
1268 WMA_LOGA("%s: Invalid stats event", __func__);
1269 return -EINVAL;
1270 }
1271 /*
1272 * cmd_param_info contains
1273 * wmi_peer_stats_event_fixed_param fixed_param;
1274 * num_peers * size of(struct wmi_peer_link_stats)
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301275 * total_num_rates * size of(struct wmi_rate_stats)
1276 * total_num_rates is the sum of the rates of all the peers.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001277 */
1278 fixed_param = param_tlvs->fixed_param;
1279 peer_stats = param_tlvs->peer_stats;
1280 rate_stats = param_tlvs->peer_rate_stats;
1281
1282 if (!fixed_param || !peer_stats ||
1283 (peer_stats->num_rates && !rate_stats)) {
1284 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
1285 return -EINVAL;
1286 }
1287
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001288 do {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001289 if (fixed_param->num_peers >
Abhinav Kumara03659c2017-12-28 15:18:07 +05301290 WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats) ||
1291 fixed_param->num_peers > param_tlvs->num_peer_stats) {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001292 excess_data = true;
1293 break;
1294 } else {
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301295 buf_len = fixed_param->num_peers *
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001296 sizeof(wmi_peer_link_stats);
1297 }
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301298 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
1299 for (count = 0; count < fixed_param->num_peers; count++) {
1300 if (temp_peer_stats->num_rates >
1301 WMI_SVC_MSG_MAX_SIZE / sizeof(wmi_rate_stats)) {
1302 excess_data = true;
1303 break;
1304 } else {
1305 total_num_rates += temp_peer_stats->num_rates;
1306 if (total_num_rates >
1307 WMI_SVC_MSG_MAX_SIZE /
Abhinav Kumara03659c2017-12-28 15:18:07 +05301308 sizeof(wmi_rate_stats) || total_num_rates >
1309 param_tlvs->num_peer_rate_stats) {
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301310 excess_data = true;
1311 break;
1312 }
1313 buf_len += temp_peer_stats->num_rates *
1314 sizeof(wmi_rate_stats);
1315 }
1316 temp_peer_stats++;
1317 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001318 } while (0);
1319
1320 if (excess_data ||
1321 (sizeof(*fixed_param) > WMI_SVC_MSG_MAX_SIZE - buf_len)) {
1322 WMA_LOGE("excess wmi buffer: rates:%d, peers:%d",
1323 peer_stats->num_rates, fixed_param->num_peers);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001324 return -EINVAL;
1325 }
1326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 peer_stats_size = sizeof(tSirWifiPeerStat);
1328 peer_info_size = sizeof(tSirWifiPeerInfo);
1329 rate_stats_size = sizeof(tSirWifiRateStat);
1330 link_stats_results_size =
1331 sizeof(*link_stats_results) + peer_stats_size +
1332 (fixed_param->num_peers * peer_info_size) +
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301333 (total_num_rates * rate_stats_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001334
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301335 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336 if (NULL == link_stats_results) {
1337 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1338 __func__, link_stats_results_size);
1339 return -ENOMEM;
1340 }
1341
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301342 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001343
1344 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
1345 link_stats_results->rspId = fixed_param->request_id;
1346 link_stats_results->ifaceId = 0;
1347 link_stats_results->num_peers = fixed_param->num_peers;
1348 link_stats_results->peer_event_number = fixed_param->peer_event_number;
1349 link_stats_results->moreResultToFollow = fixed_param->more_data;
1350
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301351 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352 &fixed_param->num_peers, peer_stats_size);
1353
1354 results = (uint8_t *) link_stats_results->results;
1355 t_peer_stats = (uint8_t *) peer_stats;
1356 t_rate_stats = (uint8_t *) rate_stats;
1357 next_res_offset = peer_stats_size;
1358 next_peer_offset = WMI_TLV_HDR_SIZE;
1359 next_rate_offset = WMI_TLV_HDR_SIZE;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301360 for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301361 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 t_peer_stats + next_peer_offset, peer_info_size);
1363 next_res_offset += peer_info_size;
1364
1365 /* Copy rate stats associated with this peer */
1366 for (count = 0; count < peer_stats->num_rates; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367 rate_stats++;
1368
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301369 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 t_rate_stats + next_rate_offset,
1371 rate_stats_size);
1372 next_res_offset += rate_stats_size;
1373 next_rate_offset += sizeof(*rate_stats);
1374 }
1375 next_peer_offset += sizeof(*peer_stats);
1376 peer_stats++;
1377 }
1378
1379 /* call hdd callback with Link Layer Statistics
1380 * vdev_id/ifacId in link_stats_results will be
1381 * used to retrieve the correct HDD context
1382 */
1383 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1384 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1385 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301386 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387
1388 return 0;
1389}
1390
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001391/**
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001392 * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
1393 * @handle: WMI handle
1394 *
1395 * Return: 0 on success, error number otherwise.
1396 */
yeshwanth sriram guntuka584c2332017-07-29 12:50:25 +05301397int wma_unified_radio_tx_mem_free(void *handle)
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001398{
1399 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1400 tSirWifiRadioStat *rs_results;
1401 uint32_t i = 0;
1402
1403 if (!wma_handle->link_stats_results)
1404 return 0;
1405
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001406 rs_results = (tSirWifiRadioStat *)
1407 &wma_handle->link_stats_results->results[0];
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001408 for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
1409 rs_results += i;
1410 if (rs_results->tx_time_per_power_level) {
1411 qdf_mem_free(rs_results->tx_time_per_power_level);
1412 rs_results->tx_time_per_power_level = NULL;
1413 }
1414
1415 if (rs_results->channels) {
1416 qdf_mem_free(rs_results->channels);
1417 rs_results->channels = NULL;
1418 }
1419 }
1420
1421 qdf_mem_free(wma_handle->link_stats_results);
1422 wma_handle->link_stats_results = NULL;
1423
1424 return 0;
1425}
1426
1427/**
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001428 * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
1429 * @handle: WMI handle
1430 * @cmd_param_info: command param info
1431 * @len: Length of @cmd_param_info
1432 *
1433 * This is the WMI event handler function to receive radio stats tx
1434 * power level stats.
1435 *
1436 * Return: 0 on success, error number otherwise.
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001437 */
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001438static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
1439 u_int8_t *cmd_param_info, u_int32_t len)
1440{
1441 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1442 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
1443 wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
1444 uint8_t *tx_power_level_values;
1445 tSirLLStatsResults *link_stats_results;
1446 tSirWifiRadioStat *rs_results;
Vignesh Viswanathan59f0fad2018-01-25 17:04:46 +05301447 uint32_t max_total_num_tx_power_levels = MAX_TPC_LEVELS * NUM_OF_BANDS *
1448 MAX_SPATIAL_STREAM_ANY_V3;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001449
1450 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1451
1452 if (!mac) {
1453 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1454 return -EINVAL;
1455 }
1456
1457 if (!mac->sme.pLinkLayerStatsIndCallback) {
1458 WMA_LOGD("%s: HDD callback is null", __func__);
1459 return -EINVAL;
1460 }
1461
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001462 param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)
1463 cmd_param_info;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001464 if (!param_tlvs) {
1465 WMA_LOGA("%s: Invalid tx power level stats event", __func__);
1466 return -EINVAL;
1467 }
1468
1469 fixed_param = param_tlvs->fixed_param;
1470 if (!fixed_param) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001471 WMA_LOGA("%s:Invalid param_tlvs for Radio tx_power level Stats",
1472 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001473 return -EINVAL;
1474 }
1475
1476 link_stats_results = wma_handle->link_stats_results;
Srinivas Girigowda52cbce42016-10-25 14:11:58 -07001477 if (!link_stats_results) {
1478 WMA_LOGA("%s: link_stats_results is NULL", __func__);
1479 return -EINVAL;
1480 }
1481
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001482 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 -07001483 __func__, fixed_param->total_num_tx_power_levels,
1484 fixed_param->num_tx_power_levels,
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001485 fixed_param->power_level_offset,
1486 fixed_param->radio_id);
1487
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001488 if (fixed_param->num_tx_power_levels > ((WMI_SVC_MSG_MAX_SIZE -
Abhinav Kumara03659c2017-12-28 15:18:07 +05301489 sizeof(*fixed_param)) / sizeof(uint32_t)) ||
1490 fixed_param->num_tx_power_levels >
1491 param_tlvs->num_tx_time_per_power_level) {
1492 WMA_LOGE("%s: excess tx_power buffers:%d, num_tx_time_per_power_level:%d",
1493 __func__, fixed_param->num_tx_power_levels,
1494 param_tlvs->num_tx_time_per_power_level);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001495 return -EINVAL;
1496 }
Vignesh Viswanathanad7eded2017-11-28 16:58:24 +05301497
Vignesh Viswanathan01e1adb2018-03-23 20:22:38 +05301498 if (fixed_param->radio_id >= link_stats_results->num_radio) {
1499 WMA_LOGE("%s: Invalid radio_id %d num_radio %d",
Vignesh Viswanathan59f0fad2018-01-25 17:04:46 +05301500 __func__, fixed_param->radio_id,
1501 link_stats_results->num_radio);
1502 return -EINVAL;
1503 }
1504
1505 if (fixed_param->total_num_tx_power_levels >
1506 max_total_num_tx_power_levels) {
1507 WMA_LOGD("Invalid total_num_tx_power_levels %d",
1508 fixed_param->total_num_tx_power_levels);
1509 return -EINVAL;
1510 }
1511
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001512 rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] +
1513 fixed_param->radio_id;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001514 tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001515
1516 rs_results->total_num_tx_power_levels =
1517 fixed_param->total_num_tx_power_levels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001518 if (!rs_results->total_num_tx_power_levels) {
1519 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001520 goto post_stats;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001521 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001522
Vignesh Viswanathanad7eded2017-11-28 16:58:24 +05301523 if ((fixed_param->power_level_offset >
1524 rs_results->total_num_tx_power_levels) ||
1525 (fixed_param->num_tx_power_levels >
1526 rs_results->total_num_tx_power_levels -
1527 fixed_param->power_level_offset)) {
1528 WMA_LOGE("%s: Invalid offset %d total_num %d num %d",
1529 __func__, fixed_param->power_level_offset,
1530 rs_results->total_num_tx_power_levels,
1531 fixed_param->num_tx_power_levels);
1532 return -EINVAL;
1533 }
1534
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001535 if (!rs_results->tx_time_per_power_level) {
1536 rs_results->tx_time_per_power_level = qdf_mem_malloc(
1537 sizeof(uint32_t) *
1538 rs_results->total_num_tx_power_levels);
1539 if (!rs_results->tx_time_per_power_level) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001540 WMA_LOGA("%s: Mem alloc fail for tx power level stats",
1541 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001542 /* In error case, atleast send the radio stats without
1543 * tx_power_level stats */
1544 rs_results->total_num_tx_power_levels = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001545 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001546 goto post_stats;
1547 }
1548 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001549 qdf_mem_copy(&rs_results->tx_time_per_power_level[
1550 fixed_param->power_level_offset],
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001551 tx_power_level_values,
1552 sizeof(uint32_t) * fixed_param->num_tx_power_levels);
1553 if (rs_results->total_num_tx_power_levels ==
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001554 (fixed_param->num_tx_power_levels +
1555 fixed_param->power_level_offset)) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001556 link_stats_results->moreResultToFollow = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001557 link_stats_results->nr_received++;
1558 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001559
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001560 WMA_LOGD("%s: moreResultToFollow: %u nr: %u nr_received: %u",
1561 __func__, link_stats_results->moreResultToFollow,
1562 link_stats_results->num_radio,
1563 link_stats_results->nr_received);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001564
1565 /* If still data to receive, return from here */
1566 if (link_stats_results->moreResultToFollow)
1567 return 0;
1568
1569post_stats:
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001570 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1571 /* Not received all radio stats yet, don't post yet */
1572 return 0;
1573 }
1574
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001575 /* call hdd callback with Link Layer Statistics
1576 * vdev_id/ifacId in link_stats_results will be
1577 * used to retrieve the correct HDD context
1578 */
1579 mac->sme.pLinkLayerStatsIndCallback(mac->hHdd,
1580 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1581 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001582 wma_unified_radio_tx_mem_free(handle);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001583
1584 return 0;
1585}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586
1587/**
1588 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
1589 * @handle: wma handle
1590 * @cmd_param_info: data received with event from fw
1591 * @len: length of data
1592 *
1593 * Return: 0 for success or error code
1594 */
1595static int wma_unified_link_radio_stats_event_handler(void *handle,
1596 uint8_t *cmd_param_info,
1597 uint32_t len)
1598{
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001599 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001600 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1601 wmi_radio_link_stats_event_fixed_param *fixed_param;
1602 wmi_radio_link_stats *radio_stats;
1603 wmi_channel_stats *channel_stats;
1604 tSirLLStatsResults *link_stats_results;
1605 uint8_t *results, *t_radio_stats, *t_channel_stats;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001606 uint32_t next_chan_offset, count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 size_t radio_stats_size, chan_stats_size;
1608 size_t link_stats_results_size;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001609 tSirWifiRadioStat *rs_results;
1610 tSirWifiChannelStats *chn_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001611
Anurag Chouhan6d760662016-02-20 16:05:43 +05301612 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613
1614 if (!pMac) {
1615 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1616 return -EINVAL;
1617 }
1618
1619 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1620 WMA_LOGD("%s: HDD callback is null", __func__);
1621 return -EINVAL;
1622 }
1623
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001624 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1625 if (!param_tlvs) {
1626 WMA_LOGA("%s: Invalid stats event", __func__);
1627 return -EINVAL;
1628 }
1629
1630 /*
1631 * cmd_param_info contains
1632 * wmi_radio_link_stats_event_fixed_param fixed_param;
1633 * size of(struct wmi_radio_link_stats);
1634 * num_channels * size of(struct wmi_channel_stats)
1635 */
1636 fixed_param = param_tlvs->fixed_param;
1637 radio_stats = param_tlvs->radio_stats;
1638 channel_stats = param_tlvs->channel_stats;
1639
1640 if (!fixed_param || !radio_stats ||
1641 (radio_stats->num_channels && !channel_stats)) {
1642 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
1643 return -EINVAL;
1644 }
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001645 if (radio_stats->num_channels >
Abhinav Kumara03659c2017-12-28 15:18:07 +05301646 (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS) ||
1647 radio_stats->num_channels > param_tlvs->num_channel_stats) {
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001648 WMA_LOGE("%s: Too many channels %d",
1649 __func__, radio_stats->num_channels);
1650 return -EINVAL;
1651 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001652
1653 radio_stats_size = sizeof(tSirWifiRadioStat);
1654 chan_stats_size = sizeof(tSirWifiChannelStats);
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001655 if (fixed_param->num_radio >
1656 (UINT_MAX - sizeof(*link_stats_results))/radio_stats_size) {
1657 WMA_LOGE("excess num_radio %d is leading to int overflow",
1658 fixed_param->num_radio);
1659 return -EINVAL;
1660 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001661 link_stats_results_size = sizeof(*link_stats_results) +
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001662 fixed_param->num_radio * radio_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001663
Vignesh Viswanathan01e1adb2018-03-23 20:22:38 +05301664 if (radio_stats->radio_id >= fixed_param->num_radio) {
1665 WMA_LOGE("%s, invalid radio id:%d, num radio:%d",
1666 __func__, radio_stats->radio_id,
1667 fixed_param->num_radio);
1668 return -EINVAL;
1669 }
1670
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001671 if (!wma_handle->link_stats_results) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001672 wma_handle->link_stats_results = qdf_mem_malloc(
1673 link_stats_results_size);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001674 if (NULL == wma_handle->link_stats_results) {
1675 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1676 __func__, link_stats_results_size);
1677 return -ENOMEM;
1678 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001679 }
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001680 link_stats_results = wma_handle->link_stats_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001682 WMA_LOGD("Radio stats Fixed Param:");
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001683 WMA_LOGD("req_id: %u num_radio: %u more_radio_events: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684 fixed_param->request_id, fixed_param->num_radio,
1685 fixed_param->more_radio_events);
1686
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001687 WMA_LOGD("Radio Info: radio_id: %u on_time: %u tx_time: %u rx_time: %u on_time_scan: %u",
1688 radio_stats->radio_id, radio_stats->on_time,
1689 radio_stats->tx_time, radio_stats->rx_time,
1690 radio_stats->on_time_scan);
1691 WMA_LOGD("on_time_nbd: %u on_time_gscan: %u on_time_roam_scan: %u",
1692 radio_stats->on_time_nbd,
1693 radio_stats->on_time_gscan, radio_stats->on_time_roam_scan);
1694 WMA_LOGD("on_time_pno_scan: %u on_time_hs20: %u num_channels: %u",
1695 radio_stats->on_time_pno_scan, radio_stats->on_time_hs20,
1696 radio_stats->num_channels);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001697 WMA_LOGD("on_time_host_scan: %u, on_time_lpi_scan: %u",
1698 radio_stats->on_time_host_scan, radio_stats->on_time_lpi_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001699
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001700 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
1701 link_stats_results->rspId = fixed_param->request_id;
1702 link_stats_results->ifaceId = 0;
1703 link_stats_results->num_radio = fixed_param->num_radio;
1704 link_stats_results->peer_event_number = 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001705
1706 /*
1707 * Backward compatibility:
1708 * There are firmware(s) which will send Radio stats only with
1709 * more_radio_events set to 0 and firmware which sends Radio stats
1710 * followed by tx_power level stats with more_radio_events set to 1.
1711 * if more_radio_events is set to 1, buffer the radio stats and
1712 * wait for tx_power_level stats.
1713 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
1715
1716 results = (uint8_t *) link_stats_results->results;
1717 t_radio_stats = (uint8_t *) radio_stats;
1718 t_channel_stats = (uint8_t *) channel_stats;
1719
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001720 rs_results = (tSirWifiRadioStat *) &results[0] + radio_stats->radio_id;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001721 rs_results->radio = radio_stats->radio_id;
1722 rs_results->onTime = radio_stats->on_time;
1723 rs_results->txTime = radio_stats->tx_time;
1724 rs_results->rxTime = radio_stats->rx_time;
1725 rs_results->onTimeScan = radio_stats->on_time_scan;
1726 rs_results->onTimeNbd = radio_stats->on_time_nbd;
1727 rs_results->onTimeGscan = radio_stats->on_time_gscan;
1728 rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
1729 rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
1730 rs_results->onTimeHs20 = radio_stats->on_time_hs20;
1731 rs_results->total_num_tx_power_levels = 0;
gaurank kathpalia247554c2017-11-30 19:12:01 +05301732 if (rs_results->tx_time_per_power_level) {
1733 qdf_mem_free(rs_results->tx_time_per_power_level);
1734 rs_results->tx_time_per_power_level = NULL;
1735 }
1736 if (rs_results->channels) {
1737 qdf_mem_free(rs_results->channels);
1738 rs_results->channels = NULL;
1739 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001740 rs_results->numChannels = radio_stats->num_channels;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001741 rs_results->on_time_host_scan = radio_stats->on_time_host_scan;
1742 rs_results->on_time_lpi_scan = radio_stats->on_time_lpi_scan;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001743 if (rs_results->numChannels) {
1744 rs_results->channels = (tSirWifiChannelStats *) qdf_mem_malloc(
1745 radio_stats->num_channels *
1746 chan_stats_size);
1747 if (rs_results->channels == NULL) {
1748 WMA_LOGD("%s: could not allocate mem for channel stats (size=%zu)",
1749 __func__, radio_stats->num_channels * chan_stats_size);
1750 wma_unified_radio_tx_mem_free(handle);
1751 return -ENOMEM;
1752 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001754 chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
1755 next_chan_offset = WMI_TLV_HDR_SIZE;
1756 WMA_LOGD("Channel Stats Info");
1757 for (count = 0; count < radio_stats->num_channels; count++) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001758 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001759 channel_stats->channel_width,
1760 channel_stats->center_freq,
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001761 channel_stats->center_freq0);
1762 WMA_LOGD("center_freq1 %u radio_awake_time %u cca_busy_time %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001763 channel_stats->center_freq1,
1764 channel_stats->radio_awake_time,
1765 channel_stats->cca_busy_time);
1766 channel_stats++;
1767
1768 qdf_mem_copy(chn_results,
1769 t_channel_stats + next_chan_offset,
1770 chan_stats_size);
1771 chn_results++;
1772 next_chan_offset += sizeof(*channel_stats);
1773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 }
1775
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001776 if (link_stats_results->moreResultToFollow) {
1777 /* More results coming, don't post yet */
1778 return 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001779 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001780 link_stats_results->nr_received++;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001781
1782 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1783 /* Not received all radio stats yet, don't post yet */
1784 return 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001785 }
1786
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001787 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1788 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1789 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001790 wma_unified_radio_tx_mem_free(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001791
1792 return 0;
1793}
1794
Zhang Qiana6e9c102016-12-22 16:47:24 +08001795#ifdef WLAN_PEER_PS_NOTIFICATION
1796/**
1797 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1798 * @handle: wma handle
1799 * @event: FW event
1800 * @len: length of FW event
1801 *
1802 * Once peer STA power state changes, an event will be indicated by
1803 * FW. This function send a link layer state change msg to HDD. HDD
1804 * link layer callback will converts the event to NL msg.
1805 *
1806 * Return: 0 Success. Others fail.
1807 */
1808static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1809 u_int32_t len)
1810{
1811 WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *param_buf;
1812 wmi_peer_sta_ps_statechange_event_fixed_param *fixed_param;
1813 tSirWifiPeerStat *peer_stat;
1814 tSirWifiPeerInfo *peer_info;
1815 tSirLLStatsResults *link_stats_results;
1816 tSirMacAddr mac_address;
1817 uint32_t result_len;
1818 cds_msg_t sme_msg = { 0 };
1819 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1820
1821 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1822
1823 if (!mac) {
1824 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1825 return -EINVAL;
1826 }
1827
1828 if (!mac->sme.link_layer_stats_ext_cb) {
1829 WMA_LOGD("%s: HDD callback is null", __func__);
1830 return -EINVAL;
1831 }
1832
1833 WMA_LOGD("%s: Posting Peer Stats PS event to HDD", __func__);
1834
1835 param_buf = (WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *)event;
1836 fixed_param = param_buf->fixed_param;
1837
1838 result_len = sizeof(tSirLLStatsResults) +
1839 sizeof(tSirWifiPeerStat) +
1840 sizeof(tSirWifiPeerInfo);
1841 link_stats_results = qdf_mem_malloc(result_len);
1842 if (link_stats_results == NULL) {
1843 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1844 return -EINVAL;
1845 }
1846
1847 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->peer_macaddr, &mac_address[0]);
1848 WMA_LOGD("Peer power state change event from FW");
1849 WMA_LOGD("Fixed Param:");
1850 WMA_LOGD("MAC address: %2x:%2x:%2x:%2x:%2x:%2x, Power state: %d",
1851 mac_address[0], mac_address[1], mac_address[2],
1852 mac_address[3], mac_address[4], mac_address[5],
1853 fixed_param->peer_ps_state);
1854
1855 link_stats_results->paramId = WMI_LL_STATS_EXT_PS_CHG;
1856 link_stats_results->num_peers = 1;
1857 link_stats_results->peer_event_number = 1;
1858 link_stats_results->moreResultToFollow = 0;
1859
1860 peer_stat = (tSirWifiPeerStat *)link_stats_results->results;
1861 peer_stat->numPeers = 1;
1862 peer_info = (tSirWifiPeerInfo *)peer_stat->peerInfo;
1863 qdf_mem_copy(&peer_info->peerMacAddress,
1864 &mac_address,
1865 sizeof(tSirMacAddr));
1866 peer_info->power_saving = fixed_param->peer_ps_state;
1867
1868 sme_msg.type = eWMI_SME_LL_STATS_IND;
1869 sme_msg.bodyptr = link_stats_results;
1870 sme_msg.bodyval = 0;
1871
Zhang Qian73c348a2017-03-13 16:15:55 +08001872 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001873 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1874 WMA_LOGE("%s: Fail to post ps change ind msg", __func__);
1875 qdf_mem_free(link_stats_results);
1876 }
1877
1878 return 0;
1879}
1880#else
1881/**
1882 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1883 * @handle: wma handle
1884 * @event: FW event
1885 * @len: length of FW event
1886 *
1887 * Once peer STA power state changes, an event will be indicated by
1888 * FW. This function send a link layer state change msg to HDD. HDD
1889 * link layer callback will converts the event to NL msg.
1890 *
1891 * Return: 0 Success. Others fail.
1892 */
1893static inline int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1894 u_int32_t len)
1895{
1896 return 0;
1897}
1898#endif
1899
1900/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 * wma_register_ll_stats_event_handler() - register link layer stats related
1902 * event handler
1903 * @wma_handle: wma handle
1904 *
1905 * Return: none
1906 */
1907void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
1908{
1909 if (NULL == wma_handle) {
1910 WMA_LOGE("%s: wma_handle is NULL", __func__);
1911 return;
1912 }
1913
1914 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301915 wmi_iface_link_stats_event_id,
Govind Singhd76a5b02016-03-08 15:12:14 +05301916 wma_unified_link_iface_stats_event_handler,
1917 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301919 wmi_peer_link_stats_event_id,
Govind Singhd76a5b02016-03-08 15:12:14 +05301920 wma_unified_link_peer_stats_event_handler,
1921 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301923 wmi_radio_link_stats_link,
Govind Singhd76a5b02016-03-08 15:12:14 +05301924 wma_unified_link_radio_stats_event_handler,
1925 WMA_RX_SERIALIZER_CTX);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001926 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301927 wmi_radio_tx_power_level_stats_event_id,
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001928 wma_unified_radio_tx_power_level_stats_event_handler,
1929 WMA_RX_SERIALIZER_CTX);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001930 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301931 wmi_peer_sta_ps_statechg_event_id,
Zhang Qiana6e9c102016-12-22 16:47:24 +08001932 wma_peer_ps_evt_handler,
1933 WMA_RX_SERIALIZER_CTX);
Zhang Qian73c348a2017-03-13 16:15:55 +08001934 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301935 wmi_report_stats_event_id,
Zhang Qian73c348a2017-03-13 16:15:55 +08001936 wma_ll_stats_evt_handler,
1937 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001939}
1940
1941
1942/**
1943 * wma_process_ll_stats_clear_req() - clear link layer stats
1944 * @wma: wma handle
1945 * @clearReq: ll stats clear request command params
1946 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301947 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001949QDF_STATUS wma_process_ll_stats_clear_req(tp_wma_handle wma,
1950 const tpSirLLStatsClearReq clearReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951{
Govind Singh4863da42016-03-08 11:45:00 +05301952 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 int ret;
1954
1955 if (!clearReq || !wma) {
1956 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301957 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958 }
1959
Deepak Dhamdhere6adc08e2017-07-27 09:33:22 -07001960 if (!wma->interfaces[clearReq->staId].handle) {
1961 WMA_LOGE("%s: vdev_id %d handle is NULL",
1962 __func__, clearReq->staId);
1963 return QDF_STATUS_E_FAILURE;
1964 }
1965
Govind Singh4863da42016-03-08 11:45:00 +05301966 cmd.stop_req = clearReq->stopReq;
1967 cmd.sta_id = clearReq->staId;
1968 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969
Govind Singh4863da42016-03-08 11:45:00 +05301970 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
1971 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 if (ret) {
1973 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301974 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975 }
1976
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301977 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978}
1979
1980/**
1981 * wma_process_ll_stats_set_req() - link layer stats set request
1982 * @wma: wma handle
1983 * @setReq: ll stats set request command params
1984 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301985 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001987QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma,
1988 const tpSirLLStatsSetReq setReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989{
Govind Singh4863da42016-03-08 11:45:00 +05301990 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 int ret;
1992
1993 if (!setReq || !wma) {
1994 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301995 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996 }
1997
Govind Singh4863da42016-03-08 11:45:00 +05301998 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
1999 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 setReq->aggressiveStatisticsGathering;
2001
Govind Singh4863da42016-03-08 11:45:00 +05302002 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
2003 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004 if (ret) {
2005 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302006 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 }
2008
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302009 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010}
2011
2012/**
2013 * wma_process_ll_stats_get_req() - link layer stats get request
2014 * @wma:wma handle
2015 * @getReq:ll stats get request command params
2016 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302017 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002019QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
2020 const tpSirLLStatsGetReq getReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021{
Govind Singh4863da42016-03-08 11:45:00 +05302022 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023 int ret;
2024
2025 if (!getReq || !wma) {
2026 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302027 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 }
2029
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +05302030 if (!wma->interfaces[getReq->staId].vdev_active) {
2031 WMA_LOGE("%s: vdev not created yet", __func__);
2032 return QDF_STATUS_E_FAILURE;
2033 }
2034
Govind Singh4863da42016-03-08 11:45:00 +05302035 cmd.req_id = getReq->reqId;
2036 cmd.param_id_mask = getReq->paramIdMask;
2037 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038
Govind Singh4863da42016-03-08 11:45:00 +05302039 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
2040 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 if (ret) {
2042 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302043 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044 }
2045
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302046 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002047}
2048
2049/**
2050 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
2051 * @wma:wma handle
2052 * @cmd_param_info: data from event
2053 * @len: length
2054 *
2055 * Return: 0 for success or error code
2056 */
2057int wma_unified_link_iface_stats_event_handler(void *handle,
2058 uint8_t *cmd_param_info,
2059 uint32_t len)
2060{
2061 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
2062 wmi_iface_link_stats_event_fixed_param *fixed_param;
2063 wmi_iface_link_stats *link_stats;
2064 wmi_wmm_ac_stats *ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002065 wmi_iface_offload_stats *offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 tSirLLStatsResults *link_stats_results;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002067 uint8_t *results, *t_link_stats, *t_ac_stats, *t_offload_stats;
2068 uint32_t next_res_offset, next_ac_offset, next_offload_offset, count;
2069 uint32_t roaming_offset, size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 size_t link_stats_size, ac_stats_size, iface_info_size;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002071 size_t link_stats_results_size, offload_stats_size;
2072 size_t total_ac_size, total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002073
Anurag Chouhan6d760662016-02-20 16:05:43 +05302074 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075
2076 if (!pMac) {
2077 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
2078 return -EINVAL;
2079 }
2080
2081 if (!pMac->sme.pLinkLayerStatsIndCallback) {
2082 WMA_LOGD("%s: HDD callback is null", __func__);
2083 return -EINVAL;
2084 }
2085
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
2087 if (!param_tlvs) {
2088 WMA_LOGA("%s: Invalid stats event", __func__);
2089 return -EINVAL;
2090 }
2091
2092 /*
2093 * cmd_param_info contains
2094 * wmi_iface_link_stats_event_fixed_param fixed_param;
2095 * wmi_iface_link_stats iface_link_stats;
2096 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002097 * fixed_param->num_offload_stats * size of(wmi_iface_offload_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002098 */
2099 fixed_param = param_tlvs->fixed_param;
2100 link_stats = param_tlvs->iface_link_stats;
2101 ac_stats = param_tlvs->ac;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002102 offload_stats = param_tlvs->iface_offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002104 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats) ||
2105 (fixed_param->num_offload_stats && !offload_stats)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
2107 return -EINVAL;
2108 }
Abhinav Kumara03659c2017-12-28 15:18:07 +05302109 if (link_stats->num_ac > WIFI_AC_MAX || link_stats->num_ac >
2110 param_tlvs->num_ac) {
2111 WMA_LOGE("%s: Excess data received from firmware num_ac %d, param_tlvs->num_ac %d",
2112 __func__, link_stats->num_ac, param_tlvs->num_ac);
Vignesh Viswanathan37794ae2017-09-28 15:26:56 +05302113 return -EINVAL;
2114 }
Abhinav Kumara03659c2017-12-28 15:18:07 +05302115 if (fixed_param->num_offload_stats > WMI_OFFLOAD_STATS_TYPE_MAX ||
2116 fixed_param->num_offload_stats >
2117 param_tlvs->num_iface_offload_stats) {
2118 WMA_LOGE("%s: Excess num offload stats recvd from fw: %d, um_iface_offload_stats: %d",
2119 __func__, fixed_param->num_offload_stats,
2120 param_tlvs->num_iface_offload_stats);
Vignesh Viswanathan37794ae2017-09-28 15:26:56 +05302121 return -EINVAL;
2122 }
2123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002124 link_stats_size = sizeof(tSirWifiIfaceStat);
2125 iface_info_size = sizeof(tSirWifiInterfaceInfo);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 ac_stats_size = sizeof(tSirWifiWmmAcStat);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002128 offload_stats_size = sizeof(struct wifi_iface_offload_stat);
2129
2130 total_ac_size = ac_stats_size * WIFI_AC_MAX;
2131 total_offload_size = offload_stats_size * WMI_OFFLOAD_STATS_TYPE_MAX +
2132 member_size(tSirWifiIfaceStat, num_offload_stats);
2133
2134 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002135
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302136 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002137 if (!link_stats_results) {
2138 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
2139 __func__, link_stats_results_size);
2140 return -ENOMEM;
2141 }
2142
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302143 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144
2145 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
2146 link_stats_results->rspId = fixed_param->request_id;
2147 link_stats_results->ifaceId = fixed_param->vdev_id;
2148 link_stats_results->num_peers = link_stats->num_peers;
2149 link_stats_results->peer_event_number = 0;
2150 link_stats_results->moreResultToFollow = 0;
2151
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002152 /* results is copied to tSirWifiIfaceStat in upper layer
2153 * tSirWifiIfaceStat
2154 * - tSirWifiInterfaceInfo (all fields except roaming is
2155 * filled by host in the upper layer)
2156 * - various members of tSirWifiIfaceStat (from wmi_iface_link_stats)
2157 * - ACs information (from wmi_wmm_ac_stats)
2158 * - num_offload_stats (from fixed param)
2159 * - offload stats (from wmi_iface_offload_stats)
2160 */
2161
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 results = (uint8_t *) link_stats_results->results;
2163 t_link_stats = (uint8_t *) link_stats;
2164 t_ac_stats = (uint8_t *) ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002165 t_offload_stats = (uint8_t *) offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166
2167 /* Copy roaming state */
2168 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002169 size = member_size(tSirWifiInterfaceInfo, roaming);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002171 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state, size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002173 next_res_offset = iface_info_size;
2174 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 t_link_stats + WMI_TLV_HDR_SIZE,
2176 link_stats_size - iface_info_size -
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002177 total_ac_size - total_offload_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002179 next_res_offset = link_stats_size - total_ac_size - total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002180 next_ac_offset = WMI_TLV_HDR_SIZE;
2181
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182 for (count = 0; count < link_stats->num_ac; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 ac_stats++;
2184
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302185 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 t_ac_stats + next_ac_offset, ac_stats_size);
2187 next_res_offset += ac_stats_size;
2188 next_ac_offset += sizeof(*ac_stats);
2189 }
2190
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002191 next_res_offset = link_stats_size - total_offload_size;
2192 /* copy num_offload_stats into result */
2193 size = member_size(tSirWifiIfaceStat, num_offload_stats);
2194 qdf_mem_copy(results + next_res_offset, &fixed_param->num_offload_stats,
2195 size);
2196
2197 next_res_offset += size;
2198 next_offload_offset = WMI_TLV_HDR_SIZE;
2199
2200 for (count = 0; count < fixed_param->num_offload_stats; count++) {
2201 qdf_mem_copy(results + next_res_offset,
2202 t_offload_stats + next_offload_offset,
2203 offload_stats_size);
2204 next_res_offset += offload_stats_size;
2205 next_offload_offset += sizeof(*offload_stats);
2206 }
2207
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 /* call hdd callback with Link Layer Statistics
2209 * vdev_id/ifacId in link_stats_results will be
2210 * used to retrieve the correct HDD context
2211 */
2212 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
2213 WMA_LINK_LAYER_STATS_RESULTS_RSP,
2214 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302215 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216
2217 return 0;
2218}
2219
Zhang Qian73c348a2017-03-13 16:15:55 +08002220/**
2221 * wma_config_stats_ext_threshold - set threthold for MAC counters
2222 * @wma: wma handler
2223 * @threshold: threhold for MAC counters
2224 *
2225 * For each MAC layer counter, FW holds two copies. One is the current value.
2226 * The other is the last report. Once a current counter's increment is larger
2227 * than the threshold, FW will indicate that counter to host even if the
2228 * monitoring timer does not expire.
2229 *
2230 * Return: None
2231 */
2232void wma_config_stats_ext_threshold(tp_wma_handle wma,
2233 struct sir_ll_ext_stats_threshold *thresh)
2234{
2235 uint32_t len, tag, hdr_len;
2236 uint8_t *buf_ptr;
2237 wmi_buf_t buf;
2238 wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
2239 wmi_chan_cca_stats_thresh *cca;
2240 wmi_peer_signal_stats_thresh *signal;
2241 wmi_tx_stats_thresh *tx;
2242 wmi_rx_stats_thresh *rx;
2243
2244 if (!thresh) {
2245 WMA_LOGE(FL("Invalid threshold input."));
2246 return;
2247 }
2248
2249 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
2250 sizeof(wmi_chan_cca_stats_thresh) +
2251 sizeof(wmi_peer_signal_stats_thresh) +
2252 sizeof(wmi_tx_stats_thresh) +
2253 sizeof(wmi_rx_stats_thresh) +
2254 5 * WMI_TLV_HDR_SIZE;
2255 buf = wmi_buf_alloc(wma->wmi_handle, len);
2256 if (!buf) {
2257 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
2258 return;
2259 }
2260
2261 buf_ptr = (u_int8_t *)wmi_buf_data(buf);
2262 tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
2263 hdr_len = WMITLV_GET_STRUCT_TLVLEN(
2264 wmi_pdev_set_stats_threshold_cmd_fixed_param);
2265 WMA_LOGD(FL("Setting fixed parameters. tag=%d, len=%d"), tag, hdr_len);
2266 cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
2267 WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
2268 cmd->enable_thresh = thresh->enable;
2269 cmd->use_thresh_bitmap = thresh->enable_bitmap;
2270 cmd->gbl_thresh = thresh->global_threshold;
2271 cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
2272 cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
2273 cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
2274 cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
2275 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
2276
2277 tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
2278 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
2279 cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
2280 WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
2281 WMA_LOGD(FL("Setting cca parameters. tag=%d, len=%d"), tag, hdr_len);
2282 cca->idle_time = thresh->cca.idle_time;
2283 cca->tx_time = thresh->cca.tx_time;
2284 cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
2285 cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
2286 cca->rx_busy_time = thresh->cca.rx_busy_time;
2287 cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
2288 cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
2289 cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
2290 WMA_LOGD(FL("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d"),
2291 cca->idle_time, cca->tx_time,
2292 cca->rx_in_bss_time, cca->rx_out_bss_time);
2293 WMA_LOGD(FL("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d"),
2294 cca->rx_busy_time, cca->rx_in_bad_cond_time,
2295 cca->tx_in_bad_cond_time, cca->wlan_not_avail_time);
2296 len += sizeof(wmi_chan_cca_stats_thresh);
2297
2298 signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
2299 tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
2300 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
2301 WMA_LOGD(FL("Setting signal parameters. tag=%d, len=%d"), tag, hdr_len);
2302 WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
2303 signal->per_chain_snr = thresh->signal.snr;
2304 signal->per_chain_nf = thresh->signal.nf;
2305 WMA_LOGD(FL("snr=%d, nf=%d"), signal->per_chain_snr,
2306 signal->per_chain_nf);
2307 len += sizeof(wmi_peer_signal_stats_thresh);
2308
2309 tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
2310 tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
2311 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
2312 WMA_LOGD(FL("Setting TX parameters. tag=%d, len=%d"), tag, len);
2313 WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
2314 tx->tx_msdu_cnt = thresh->tx.msdu;
2315 tx->tx_mpdu_cnt = thresh->tx.mpdu;
2316 tx->tx_ppdu_cnt = thresh->tx.ppdu;
2317 tx->tx_bytes = thresh->tx.bytes;
2318 tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
2319 tx->tx_drop_bytes = thresh->tx.byte_drop;
2320 tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
2321 tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
2322 tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
2323 tx->tx_mpdu_aggr = thresh->tx.aggregation;
2324 tx->tx_succ_mcs = thresh->tx.succ_mcs;
2325 tx->tx_fail_mcs = thresh->tx.fail_mcs;
2326 tx->tx_ppdu_delay = thresh->tx.delay;
2327 WMA_LOGD(FL("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d"),
2328 tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
2329 tx->tx_bytes, tx->tx_msdu_drop_cnt);
2330 WMA_LOGD(FL("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d"),
2331 tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
2332 tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
2333 WMA_LOGD(FL("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d"),
2334 tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
2335 tx->tx_ppdu_delay);
2336 len += sizeof(wmi_tx_stats_thresh);
2337
2338 rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
2339 tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
2340 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
2341 WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
2342 WMA_LOGD(FL("Setting RX parameters. tag=%d, len=%d"), tag, hdr_len);
2343 rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
2344 rx->mac_rx_bytes = thresh->rx.bytes;
2345 rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
2346 rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
2347 rx->rx_disorder_cnt = thresh->rx.disorder;
2348 rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
2349 rx->rx_mpdu_dup_cnt = thresh->rx.mpdu_dup;
2350 rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
2351 rx->rx_mpdu_aggr = thresh->rx.aggregation;
2352 rx->rx_mcs = thresh->rx.mcs;
2353 rx->sta_ps_inds = thresh->rx.ps_inds;
2354 rx->sta_ps_durs = thresh->rx.ps_durs;
2355 rx->rx_probe_reqs = thresh->rx.probe_reqs;
2356 rx->rx_oth_mgmts = thresh->rx.other_mgmt;
2357 WMA_LOGD(FL("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d"),
2358 rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
2359 rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
2360 WMA_LOGD(FL("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d"),
2361 rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
2362 rx->rx_mpdu_aggr, rx->rx_mcs);
2363 WMA_LOGD(FL("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d"),
2364 rx->sta_ps_inds, rx->sta_ps_durs,
2365 rx->rx_probe_reqs, rx->rx_oth_mgmts);
2366 len += sizeof(wmi_rx_stats_thresh);
2367
2368 WMA_LOGA("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
2369 WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
2370 if (EOK != wmi_unified_cmd_send(wma->wmi_handle,
2371 buf, len,
2372 WMI_PDEV_SET_STATS_THRESHOLD_CMDID)) {
2373 WMA_LOGE("Failed to send WMI_PDEV_SET_STATS_THRESHOLD_CMDID");
2374 wmi_buf_free(buf);
2375 }
2376}
2377
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2379
2380/**
2381 * wma_update_pdev_stats() - update pdev stats
2382 * @wma: wma handle
2383 * @pdev_stats: pdev stats
2384 *
2385 * Return: none
2386 */
2387static void wma_update_pdev_stats(tp_wma_handle wma,
2388 wmi_pdev_stats *pdev_stats)
2389{
2390 tAniGetPEStatsRsp *stats_rsp_params;
2391 uint32_t temp_mask;
2392 uint8_t *stats_buf;
2393 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2394 struct wma_txrx_node *node;
2395 uint8_t i;
2396
2397 for (i = 0; i < wma->max_bssid; i++) {
2398 node = &wma->interfaces[i];
2399 stats_rsp_params = node->stats_rsp;
2400 if (stats_rsp_params) {
2401 node->fw_stats_set |= FW_PDEV_STATS_SET;
2402 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
2403 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2404 temp_mask = stats_rsp_params->statsMask;
2405 if (temp_mask & (1 << eCsrSummaryStats))
2406 stats_buf += sizeof(tCsrSummaryStatsInfo);
2407
2408 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2409 classa_stats =
2410 (tCsrGlobalClassAStatsInfo *) stats_buf;
2411 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
2412 }
2413 }
2414 }
2415}
2416
2417/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302418 * wma_vdev_stats_lost_link_helper() - helper function to extract
2419 * lost link information from vdev statistics event while deleting BSS.
2420 * @wma: WMA handle
2421 * @vdev_stats: statistics information from firmware
2422 *
2423 * This is for informing HDD to collect lost link information while
2424 * disconnection. Following conditions to check
2425 * 1. vdev is up
2426 * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to
2427 * zero, hence add the check here to indicate the event comes during deleting
2428 * BSS
2429 * 3. DELETE_BSS is the request message queued. Put this condition check on the
2430 * last one as it consumes more resource searching entries in the list
2431 *
2432 * Return: none
2433 */
2434static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma,
2435 wmi_vdev_stats *vdev_stats)
2436{
2437 struct wma_txrx_node *node;
2438 int32_t rssi;
2439 struct wma_target_req *req_msg;
2440 static const uint8_t zero_mac[QDF_MAC_ADDR_SIZE] = {0};
Naveen Rawatf440a132017-05-05 12:27:39 -07002441 int32_t bcn_snr, dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302442
Rajeev Kumar0b071172018-02-08 18:21:57 -08002443 if (vdev_stats->vdev_id >= wma->max_bssid) {
2444 WMA_LOGE("%s: Invalid vdev_id %hu",
2445 __func__, vdev_stats->vdev_id);
2446 return;
2447 }
2448
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302449 node = &wma->interfaces[vdev_stats->vdev_id];
Mukul Sharmaf9047232017-03-02 16:58:56 +05302450 if (wma_is_vdev_up(vdev_stats->vdev_id) &&
Hanumanth Reddy Pothulaaef3c7f2017-05-18 12:19:23 +05302451 !qdf_mem_cmp(node->bssid, zero_mac, QDF_MAC_ADDR_SIZE)) {
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302452 req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id,
2453 WMA_TARGET_REQ_TYPE_VDEV_STOP);
2454 if ((NULL == req_msg) ||
2455 (WMA_DELETE_BSS_REQ != req_msg->msg_type)) {
2456 WMA_LOGD(FL("cannot find DELETE_BSS request message"));
2457 return;
2458 }
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002459 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2460 dat_snr = vdev_stats->vdev_snr.dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302461 WMA_LOGD(FL("get vdev id %d, beancon snr %d, data snr %d"),
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002462 vdev_stats->vdev_id, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302463
2464 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002465 rssi = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302466 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002467 rssi = dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302468 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302469 rssi = WMA_TGT_INVALID_SNR;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302470
2471 /* Get the absolute rssi value from the current rssi value */
2472 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2473 wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi);
2474 }
2475}
2476
2477/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 * wma_update_vdev_stats() - update vdev stats
2479 * @wma: wma handle
2480 * @vdev_stats: vdev stats
2481 *
2482 * Return: none
2483 */
2484static void wma_update_vdev_stats(tp_wma_handle wma,
2485 wmi_vdev_stats *vdev_stats)
2486{
2487 tAniGetPEStatsRsp *stats_rsp_params;
2488 tCsrSummaryStatsInfo *summary_stats = NULL;
2489 uint8_t *stats_buf;
2490 struct wma_txrx_node *node;
2491 uint8_t i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002492 int32_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302493 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002495 struct scheduler_msg sme_msg = { 0 };
Naveen Rawatf440a132017-05-05 12:27:39 -07002496 int32_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497
Rajeev Kumar0b071172018-02-08 18:21:57 -08002498 if (vdev_stats->vdev_id >= wma->max_bssid) {
2499 WMA_LOGE("%s: Invalid vdev_id %hu",
2500 __func__, vdev_stats->vdev_id);
2501 return;
2502 }
2503
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002504 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2505 dat_snr = vdev_stats->vdev_snr.dat_snr;
2506 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
2507 vdev_stats->vdev_id, bcn_snr, dat_snr);
2508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 node = &wma->interfaces[vdev_stats->vdev_id];
2510 stats_rsp_params = node->stats_rsp;
2511 if (stats_rsp_params) {
2512 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2513 node->fw_stats_set |= FW_VDEV_STATS_SET;
2514 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
2515 vdev_stats->vdev_id);
2516 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
2517 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
2518 for (i = 0; i < 4; i++) {
2519 summary_stats->tx_frm_cnt[i] =
2520 vdev_stats->tx_frm_cnt[i];
2521 summary_stats->fail_cnt[i] =
2522 vdev_stats->fail_cnt[i];
2523 summary_stats->multiple_retry_cnt[i] =
2524 vdev_stats->multiple_retry_cnt[i];
2525 }
2526
2527 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
2528 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
2529 summary_stats->rx_discard_cnt =
2530 vdev_stats->rx_discard_cnt;
2531 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
2532 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
2533 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002534 /* Update SNR and RSSI in SummaryStats */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302535 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002536 summary_stats->snr = bcn_snr;
2537 summary_stats->rssi =
2538 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302539 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002540 summary_stats->snr = dat_snr;
2541 summary_stats->rssi =
Naveen Rawatf440a132017-05-05 12:27:39 -07002542 dat_snr + WMA_TGT_NOISE_FLOOR_DBM;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002543 } else {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302544 summary_stats->snr = WMA_TGT_INVALID_SNR;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002545 summary_stats->rssi = 0;
2546 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 }
2548 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549
2550 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302551 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
2552 rssi = bcn_snr;
2553 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2554 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
2555 rssi = dat_snr;
2556 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2557 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 /*
2559 * Firmware sends invalid snr till it sees
2560 * Beacon/Data after connection since after
2561 * vdev up fw resets the snr to invalid.
2562 * In this duartion Host will return the last know
2563 * rssi during connection.
2564 */
2565 WMA_LOGE("Invalid SNR from firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 }
2567
2568 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
2569 pGetRssiReq->sessionId);
2570
2571 /* update the average rssi value to UMAC layer */
2572 if (NULL != pGetRssiReq->rssiCallback) {
2573 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
2574 pGetRssiReq->staId,
2575 pGetRssiReq->pDevContext);
2576 }
2577
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302578 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 wma->pGetRssiReq = NULL;
2580 }
2581
2582 if (node->psnr_req) {
2583 tAniGetSnrReq *p_snr_req = node->psnr_req;
2584
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302585 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07002586 p_snr_req->snr = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302587 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002588 p_snr_req->snr = dat_snr;
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002589 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302590 p_snr_req->snr = WMA_TGT_INVALID_SNR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591
2592 sme_msg.type = eWNI_SME_SNR_IND;
2593 sme_msg.bodyptr = p_snr_req;
2594 sme_msg.bodyval = 0;
2595
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002596 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302597 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002598 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302599 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 }
2601
2602 node->psnr_req = NULL;
2603 }
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302604 wma_vdev_stats_lost_link_helper(wma, vdev_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605}
2606
2607/**
2608 * wma_post_stats() - update stats to PE
2609 * @wma: wma handle
2610 * @node: txrx node
2611 *
2612 * Return: none
2613 */
2614static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
2615{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002616 /* send response to UMAC */
Naveen Rawat3c49d192017-03-02 18:43:16 -08002617 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, node->stats_rsp, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618 node->stats_rsp = NULL;
2619 node->fw_stats_set = 0;
2620}
2621
2622/**
2623 * wma_update_peer_stats() - update peer stats
2624 * @wma: wma handle
2625 * @peer_stats: peer stats
2626 *
2627 * Return: none
2628 */
2629static void wma_update_peer_stats(tp_wma_handle wma,
2630 wmi_peer_stats *peer_stats)
2631{
2632 tAniGetPEStatsRsp *stats_rsp_params;
2633 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2634 struct wma_txrx_node *node;
2635 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
2636 uint32_t temp_mask;
2637
2638 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
2639 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
2640 return;
2641
2642 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002643 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2644 if (stats_rsp_params) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 node->fw_stats_set |= FW_PEER_STATS_SET;
2646 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2648 temp_mask = stats_rsp_params->statsMask;
2649 if (temp_mask & (1 << eCsrSummaryStats))
2650 stats_buf += sizeof(tCsrSummaryStatsInfo);
2651
2652 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2653 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
2654 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002655 /* The linkspeed returned by fw is in kbps so convert
2656 * it in to units of 500kbps which is expected by UMAC
2657 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658 if (peer_stats->peer_tx_rate) {
2659 classa_stats->tx_rate =
2660 peer_stats->peer_tx_rate / 500;
2661 }
2662
2663 classa_stats->tx_rate_flags = node->rate_flags;
2664 if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) {
2665 classa_stats->mcs_index =
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002666 wma_get_mcs_idx(
2667 (peer_stats->peer_tx_rate /
2668 100), node->rate_flags,
2669 node->nss, &mcsRateFlags);
Jeff Johnsonad0b2c62017-03-16 14:37:38 -07002670 classa_stats->nss = node->nss;
2671 classa_stats->mcs_rate_flags = mcsRateFlags;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 }
2673 /* FW returns tx power in intervals of 0.5 dBm
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002674 * Convert it back to intervals of 1 dBm
2675 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 classa_stats->max_pwr =
2677 roundup(classa_stats->max_pwr, 2) >> 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002679 }
2680}
2681
2682/**
2683 * wma_post_link_status() - post link status to SME
2684 * @pGetLinkStatus: SME Link status
2685 * @link_status: Link status
2686 *
2687 * Return: none
2688 */
2689void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
2690 uint8_t link_status)
2691{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302692 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002693 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002694
2695 pGetLinkStatus->linkStatus = link_status;
2696 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
2697 sme_msg.bodyptr = pGetLinkStatus;
2698 sme_msg.bodyval = 0;
2699
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002700 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302701 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302703 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 }
2705}
2706
2707/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302708 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
2709 * @wma: wma handle
2710 * @rssi_stats: rssi stats
2711 * @rssi_per_chain_stats: buffer where rssi stats to be stored
2712 *
2713 * This function stores per chain rssi stats received from fw for all vdevs for
2714 * which the stats were requested into a csr stats structure.
2715 *
2716 * Return: void
2717 */
2718static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
2719 wmi_rssi_stats *rssi_stats,
2720 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
2721{
2722 int i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002723 int32_t bcn_snr, dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302724
2725 for (i = 0; i < NUM_CHAINS_MAX; i++) {
2726 bcn_snr = rssi_stats->rssi_avg_beacon[i];
2727 dat_snr = rssi_stats->rssi_avg_data[i];
2728 WMA_LOGD("chain %d beacon snr %d data snr %d",
2729 i, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302730 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302731 rssi_per_chain_stats->rssi[i] = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302732 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
2733 rssi_per_chain_stats->rssi[i] = dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302734 else
2735 /*
2736 * Firmware sends invalid snr till it sees
2737 * Beacon/Data after connection since after
2738 * vdev up fw resets the snr to invalid.
2739 * In this duartion Host will return an invalid rssi
2740 * value.
2741 */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302742 rssi_per_chain_stats->rssi[i] = WMA_TGT_INVALID_SNR;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302743
2744 /*
2745 * Get the absolute rssi value from the current rssi value the
2746 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
2747 */
2748 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
2749 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
2750 rssi_per_chain_stats->peer_mac_addr);
2751 }
2752}
2753
2754/**
2755 * wma_update_rssi_stats() - to update rssi stats for all vdevs
2756 * for which the stats were requested.
2757 * @wma: wma handle
2758 * @rssi_stats: rssi stats
2759 *
2760 * This function updates the rssi stats for all vdevs for which
2761 * the stats were requested.
2762 *
2763 * Return: void
2764 */
2765static void wma_update_rssi_stats(tp_wma_handle wma,
2766 wmi_rssi_stats *rssi_stats)
2767{
2768 tAniGetPEStatsRsp *stats_rsp_params;
2769 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
2770 struct wma_txrx_node *node;
2771 uint8_t *stats_buf;
2772 uint32_t temp_mask;
2773 uint8_t vdev_id;
2774
Rajeev Kumar0b071172018-02-08 18:21:57 -08002775 if (rssi_stats->vdev_id >= wma->max_bssid) {
2776 WMA_LOGE("%s: Invalid vdev_id %hu",
2777 __func__, rssi_stats->vdev_id);
2778 return;
2779 }
2780
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302781 vdev_id = rssi_stats->vdev_id;
2782 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002783 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2784 if (stats_rsp_params) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302785 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
2786 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
2787 vdev_id);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302788 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2789 temp_mask = stats_rsp_params->statsMask;
2790
2791 if (temp_mask & (1 << eCsrSummaryStats))
2792 stats_buf += sizeof(tCsrSummaryStatsInfo);
2793 if (temp_mask & (1 << eCsrGlobalClassAStats))
2794 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302795 if (temp_mask & (1 << eCsrGlobalClassDStats))
2796 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302797
2798 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
2799 rssi_per_chain_stats =
2800 (struct csr_per_chain_rssi_stats_info *)stats_buf;
2801 wma_update_per_chain_rssi_stats(wma, rssi_stats,
2802 rssi_per_chain_stats);
2803 }
2804 }
2805}
2806
2807
2808/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 * wma_link_status_event_handler() - link status event handler
2810 * @handle: wma handle
2811 * @cmd_param_info: data from event
2812 * @len: length
2813 *
2814 * Return: 0 for success or error code
2815 */
2816int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
2817 uint32_t len)
2818{
2819 tp_wma_handle wma = (tp_wma_handle) handle;
2820 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
2821 wmi_vdev_rate_stats_event_fixed_param *event;
2822 wmi_vdev_rate_ht_info *ht_info;
2823 struct wma_txrx_node *intr = wma->interfaces;
2824 uint8_t link_status = LINK_STATUS_LEGACY;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002825 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826
2827 param_buf =
2828 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2829 if (!param_buf) {
2830 WMA_LOGA("%s: Invalid stats event", __func__);
2831 return -EINVAL;
2832 }
2833
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002834 event = (wmi_vdev_rate_stats_event_fixed_param *)
2835 param_buf->fixed_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002836 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
2837
2838 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002839
2840 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
Abhinav Kumara03659c2017-12-28 15:18:07 +05302841 sizeof(*event)) / sizeof(*ht_info)) ||
2842 event->num_vdev_stats > param_buf->num_ht_info) {
2843 WMA_LOGE("%s: excess vdev_stats buffers:%d, num_ht_info:%d",
2844 __func__, event->num_vdev_stats,
2845 param_buf->num_ht_info);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002846 return -EINVAL;
2847 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
2849 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
2850 __func__, ht_info->vdevid, ht_info->tx_nss,
2851 ht_info->rx_nss, ht_info->tx_preamble,
2852 ht_info->rx_preamble);
2853 if (ht_info->vdevid < wma->max_bssid
2854 && intr[ht_info->vdevid].plink_status_req) {
2855 if (ht_info->tx_nss || ht_info->rx_nss)
2856 link_status = LINK_STATUS_MIMO;
2857
2858 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
2859 (ht_info->rx_preamble == LINK_RATE_VHT))
2860 link_status |= LINK_STATUS_VHT;
2861
2862 if (intr[ht_info->vdevid].nss == 2)
2863 link_status |= LINK_SUPPORT_MIMO;
2864
2865 if (intr[ht_info->vdevid].rate_flags &
2866 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
2867 eHAL_TX_RATE_VHT80))
2868 link_status |= LINK_SUPPORT_VHT;
2869
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002870 wma_post_link_status(
2871 intr[ht_info->vdevid].plink_status_req,
2872 link_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002873 intr[ht_info->vdevid].plink_status_req = NULL;
2874 link_status = LINK_STATUS_LEGACY;
2875 }
2876
2877 ht_info++;
2878 }
2879
2880 return 0;
2881}
2882
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302883int wma_rso_cmd_status_event_handler(wmi_roam_event_fixed_param *wmi_event)
2884{
2885 struct rso_cmd_status *rso_status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -07002886 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302887 QDF_STATUS qdf_status;
2888
2889 rso_status = qdf_mem_malloc(sizeof(*rso_status));
2890 if (!rso_status) {
2891 WMA_LOGE("%s: malloc fails for rso cmd status", __func__);
2892 return -ENOMEM;
2893 }
2894
2895 rso_status->vdev_id = wmi_event->vdev_id;
2896 if (WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS == wmi_event->notif)
2897 rso_status->status = true;
2898 else if (WMI_ROAM_NOTIF_SCAN_MODE_FAIL == wmi_event->notif)
2899 rso_status->status = false;
2900 sme_msg.type = eWNI_SME_RSO_CMD_STATUS_IND;
2901 sme_msg.bodyptr = rso_status;
2902 sme_msg.bodyval = 0;
2903 WMA_LOGI("%s: Post RSO cmd status to SME", __func__);
2904
2905 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2906 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2907 WMA_LOGE("%s: fail to post RSO cmd status to SME", __func__);
2908 qdf_mem_free(rso_status);
2909 }
2910 return 0;
2911}
2912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913/**
Will Huanga9814592017-05-24 15:47:58 +08002914 * wma_handle_sta_peer_info() - handle peer information in
2915 * peer stats
2916 * @num_peer_stats: peer number
2917 * @peer_stats: peer stats received from firmware
2918 * @peer_macaddr: the specified mac address
2919 * @sapaddr: sap mac address
2920 *
2921 * This function will send eWNI_SME_GET_PEER_INFO_IND
2922 * to sme with stations' information
2923 *
2924 */
2925static void wma_handle_sta_peer_info(uint32_t num_peer_stats,
2926 wmi_peer_stats *peer_stats,
2927 struct qdf_mac_addr peer_macaddr,
2928 uint8_t *sapaddr)
2929{
2930 QDF_STATUS qdf_status;
2931 wmi_mac_addr temp_addr;
2932 struct sir_peer_info_resp *peer_info;
2933 struct scheduler_msg sme_msg = {0};
2934 uint32_t i;
2935 uint32_t j = 0;
2936
2937 if (!qdf_is_macaddr_broadcast(&peer_macaddr)) {
2938 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_macaddr.bytes, &temp_addr);
2939 for (i = 0; i < num_peer_stats; i++) {
2940 if ((((temp_addr.mac_addr47to32) & 0x0000ffff) ==
2941 ((peer_stats->peer_macaddr.mac_addr47to32) &
2942 0x0000ffff))
2943 && (temp_addr.mac_addr31to0 ==
2944 peer_stats->peer_macaddr.mac_addr31to0)) {
2945
2946 break;
2947 }
2948 peer_stats = peer_stats + 1;
2949 }
2950 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2951 sizeof(peer_info->info[0]));
2952 if (NULL == peer_info) {
2953 WMA_LOGE("%s: Memory allocation failed.", __func__);
2954 return;
2955 }
2956 if (i < num_peer_stats) {
2957 peer_info->count = 1;
2958 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2959 peer_info->info[0].peer_macaddr.bytes);
2960 peer_info->info[0].rssi = peer_stats->peer_rssi;
2961 peer_info->info[0].tx_rate = peer_stats->peer_tx_rate;
2962 peer_info->info[0].rx_rate = peer_stats->peer_rx_rate;
2963 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2964 __func__,
2965 peer_info->info[0].peer_macaddr.bytes,
2966 peer_stats->peer_rssi,
2967 peer_stats->peer_tx_rate,
2968 peer_stats->peer_rx_rate);
2969 } else {
2970 WMA_LOGE("%s: no match mac address", __func__);
2971 peer_info->count = 0;
2972 }
2973 } else {
2974 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2975 num_peer_stats * sizeof(peer_info->info[0]));
2976 if (NULL == peer_info) {
2977 WMA_LOGE("%s: Memory allocation failed.", __func__);
2978 return;
2979 }
2980 peer_info->count = num_peer_stats;
2981
2982 for (i = 0; i < num_peer_stats; i++) {
2983 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2984 peer_info->info[j].peer_macaddr.bytes);
2985 peer_info->info[j].rssi = peer_stats->peer_rssi;
2986 peer_info->info[j].tx_rate = peer_stats->peer_tx_rate;
2987 peer_info->info[j].rx_rate = peer_stats->peer_rx_rate;
2988 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2989 __func__,
2990 peer_info->info[j].peer_macaddr.bytes,
2991 peer_stats->peer_rssi,
2992 peer_stats->peer_tx_rate,
2993 peer_stats->peer_rx_rate);
2994 if (!qdf_mem_cmp(peer_info->info[j].peer_macaddr.bytes,
2995 sapaddr, QDF_MAC_ADDR_SIZE)) {
2996 peer_info->count = peer_info->count - 1;
2997 } else {
2998 j++;
2999 }
3000 peer_stats = peer_stats + 1;
3001 }
3002 WMA_LOGD("WDA send peer num %d", peer_info->count);
3003 }
3004
3005 sme_msg.type = eWNI_SME_GET_PEER_INFO_IND;
3006 sme_msg.bodyptr = peer_info;
3007 sme_msg.bodyval = 0;
3008
3009 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3010 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3011 WMA_LOGE("%s: Fail to post get rssi msg", __func__);
3012 qdf_mem_free(peer_info);
3013 }
3014
3015 return;
3016}
3017
3018/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019 * wma_stats_event_handler() - stats event handler
3020 * @handle: wma handle
3021 * @cmd_param_info: data from event
3022 * @len: length
3023 *
3024 * Return: 0 for success or error code
3025 */
3026int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
3027 uint32_t len)
3028{
3029 tp_wma_handle wma = (tp_wma_handle) handle;
3030 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
3031 wmi_stats_event_fixed_param *event;
3032 wmi_pdev_stats *pdev_stats;
3033 wmi_vdev_stats *vdev_stats;
3034 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303035 wmi_rssi_stats *rssi_stats;
3036 wmi_per_chain_rssi_stats *rssi_event;
3037 struct wma_txrx_node *node;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003038 uint8_t *temp;
3039 uint32_t i;
3040 uint32_t buf_len = 0;
3041 bool excess_data = false;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303042 wmi_congestion_stats *congestion_stats;
3043 tpAniSirGlobal mac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
3046 if (!param_buf) {
3047 WMA_LOGA("%s: Invalid stats event", __func__);
3048 return -EINVAL;
3049 }
3050 event = param_buf->fixed_param;
3051 temp = (uint8_t *) param_buf->data;
Abhinav Kumara03659c2017-12-28 15:18:07 +05303052 if ((event->num_pdev_stats + event->num_vdev_stats +
3053 event->num_peer_stats) > param_buf->num_data) {
3054 WMA_LOGE("%s: Invalid num_pdev_stats:%d or num_vdev_stats:%d or num_peer_stats:%d",
3055 __func__, event->num_pdev_stats, event->num_vdev_stats,
3056 event->num_peer_stats);
3057 return -EINVAL;
3058 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003060 do {
3061 if (event->num_pdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
3062 sizeof(*event)) / sizeof(*pdev_stats))) {
3063 excess_data = true;
3064 break;
3065 } else {
3066 buf_len += event->num_pdev_stats * sizeof(*pdev_stats);
3067 }
3068
3069 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
3070 sizeof(*event)) / sizeof(*vdev_stats))) {
3071 excess_data = true;
3072 break;
3073 } else {
3074 buf_len += event->num_vdev_stats * sizeof(*vdev_stats);
3075 }
3076
3077 if (event->num_peer_stats > ((WMI_SVC_MSG_MAX_SIZE -
3078 sizeof(*event)) / sizeof(*peer_stats))) {
3079 excess_data = true;
3080 break;
3081 } else {
3082 buf_len += event->num_peer_stats * sizeof(*peer_stats);
3083 }
3084
3085 rssi_event =
3086 (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
bingsf9047652017-08-31 08:05:54 +08003087 if (rssi_event) {
3088 if (rssi_event->num_per_chain_rssi_stats >
3089 ((WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) /
3090 sizeof(*rssi_event))) {
3091 excess_data = true;
3092 break;
3093 } else {
3094 buf_len += sizeof(*rssi_event) *
3095 rssi_event->num_per_chain_rssi_stats;
3096 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003097 }
3098 } while (0);
3099
3100 if (excess_data ||
3101 (sizeof(*event) > WMI_SVC_MSG_MAX_SIZE - buf_len)) {
3102 WMA_LOGE("excess wmi buffer: stats pdev %d vdev %d peer %d",
3103 event->num_pdev_stats, event->num_vdev_stats,
3104 event->num_peer_stats);
3105 QDF_ASSERT(0);
3106 return -EINVAL;
3107 }
3108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 if (event->num_pdev_stats > 0) {
3110 for (i = 0; i < event->num_pdev_stats; i++) {
3111 pdev_stats = (wmi_pdev_stats *) temp;
3112 wma_update_pdev_stats(wma, pdev_stats);
3113 temp += sizeof(wmi_pdev_stats);
3114 }
3115 }
3116
3117 if (event->num_vdev_stats > 0) {
3118 for (i = 0; i < event->num_vdev_stats; i++) {
3119 vdev_stats = (wmi_vdev_stats *) temp;
3120 wma_update_vdev_stats(wma, vdev_stats);
3121 temp += sizeof(wmi_vdev_stats);
3122 }
3123 }
3124
3125 if (event->num_peer_stats > 0) {
Will Huanga9814592017-05-24 15:47:58 +08003126 if (wma->get_sta_peer_info == true) {
3127 wma_handle_sta_peer_info(event->num_peer_stats,
3128 (wmi_peer_stats *)temp,
3129 wma->peer_macaddr,
3130 wma->myaddr);
3131 } else {
3132 for (i = 0; i < event->num_peer_stats; i++) {
3133 peer_stats = (wmi_peer_stats *) temp;
3134 wma_update_peer_stats(wma, peer_stats);
3135 temp += sizeof(wmi_peer_stats);
3136 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137 }
3138 }
3139
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303140 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
3141 if (rssi_event) {
Abhinav Kumara03659c2017-12-28 15:18:07 +05303142 if (rssi_event->num_per_chain_rssi_stats >
3143 param_buf->num_rssi_stats) {
3144 WMA_LOGE("%s: Invalid num_per_chain_rssi_stats:%d",
3145 __func__, rssi_event->num_per_chain_rssi_stats);
3146 return -EINVAL;
3147 }
Himanshu Agarwalcd8a84a2016-07-21 14:59:50 +05303148 if (((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
3149 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) &&
3150 ((rssi_event->tlv_header & 0x0000FFFF) ==
3151 WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats))) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303152 if (rssi_event->num_per_chain_rssi_stats > 0) {
3153 temp = (uint8_t *) rssi_event;
3154 temp += sizeof(*rssi_event);
Dustin Brownc4a5ba22016-11-10 17:21:18 -08003155
3156 /* skip past struct array tlv header */
3157 temp += WMI_TLV_HDR_SIZE;
3158
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303159 for (i = 0;
3160 i < rssi_event->num_per_chain_rssi_stats;
3161 i++) {
3162 rssi_stats = (wmi_rssi_stats *)temp;
3163 wma_update_rssi_stats(wma, rssi_stats);
3164 temp += sizeof(wmi_rssi_stats);
3165 }
3166 }
3167 }
3168 }
3169
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303170 congestion_stats = (wmi_congestion_stats *) param_buf->congestion_stats;
3171 if (congestion_stats) {
3172 if (((congestion_stats->tlv_header & 0xFFFF0000) >> 16 ==
3173 WMITLV_TAG_STRUC_wmi_congestion_stats) &&
3174 ((congestion_stats->tlv_header & 0x0000FFFF) ==
3175 WMITLV_GET_STRUCT_TLVLEN(wmi_congestion_stats))) {
3176 mac = cds_get_context(QDF_MODULE_ID_PE);
3177 if (!mac) {
3178 WMA_LOGE("%s: Invalid mac", __func__);
3179 return -EINVAL;
3180 }
3181 if (!mac->sme.congestion_cb) {
3182 WMA_LOGE("%s: Callback not registered",
3183 __func__);
3184 return -EINVAL;
3185 }
3186 WMA_LOGI("%s: congestion %d", __func__,
3187 congestion_stats->congestion);
3188 mac->sme.congestion_cb(mac->hHdd,
3189 congestion_stats->congestion,
3190 congestion_stats->vdev_id);
3191 }
3192 }
3193
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303194 for (i = 0; i < wma->max_bssid; i++) {
3195 node = &wma->interfaces[i];
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003196 if (node->fw_stats_set & FW_PEER_STATS_SET)
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303197 wma_post_stats(wma, node);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303198 }
3199
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200 return 0;
3201}
3202
3203/**
Will Huanga9814592017-05-24 15:47:58 +08003204 * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct
3205 * @wma: wma interface
3206 * @stats_info: WMI peer info pointer
3207 * @peer_info: SIR peer info pointer
3208 *
3209 * This function will fill SIR peer info from WMI peer info struct
3210 *
3211 * Return: None
3212 */
3213static void wma_fill_peer_info(tp_wma_handle wma,
3214 wmi_peer_stats_info *stats_info,
3215 struct sir_peer_info_ext *peer_info)
3216{
3217 peer_info->tx_packets = stats_info->tx_packets.low_32;
3218 peer_info->tx_bytes = stats_info->tx_bytes.high_32;
3219 peer_info->tx_bytes <<= 32;
3220 peer_info->tx_bytes += stats_info->tx_bytes.low_32;
3221 peer_info->rx_packets = stats_info->rx_packets.low_32;
3222 peer_info->rx_bytes = stats_info->rx_bytes.high_32;
3223 peer_info->rx_bytes <<= 32;
3224 peer_info->rx_bytes += stats_info->rx_bytes.low_32;
3225 peer_info->tx_retries = stats_info->tx_retries;
3226 peer_info->tx_failed = stats_info->tx_failed;
3227 peer_info->rssi = stats_info->peer_rssi;
3228 peer_info->tx_rate = stats_info->last_tx_bitrate_kbps;
3229 peer_info->tx_rate_code = stats_info->last_tx_rate_code;
3230 peer_info->rx_rate = stats_info->last_rx_bitrate_kbps;
3231 peer_info->rx_rate_code = stats_info->last_rx_rate_code;
3232}
3233
3234/**
3235 * wma_peer_info_ext_rsp() - process peer ext info ext
3236 * @handle: wma interface
3237 * @buf: wmi event buf pointer
3238 *
3239 * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME
3240 *
3241 * Return: 0 on success, error code otherwise
3242 */
3243static QDF_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf)
3244{
3245 wmi_peer_stats_info_event_fixed_param *event;
3246 wmi_peer_stats_info *stats_info;
3247 struct sir_peer_info_ext_resp *resp;
3248 struct sir_peer_info_ext *peer_info;
3249 struct scheduler_msg sme_msg = {0};
3250 int i, j = 0;
3251 QDF_STATUS qdf_status;
3252
3253 event = (wmi_peer_stats_info_event_fixed_param *)buf;
3254 stats_info = (wmi_peer_stats_info *)(buf +
3255 sizeof(wmi_peer_stats_info_event_fixed_param));
3256
3257 if (wma->get_one_peer_info) {
3258 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3259 sizeof(resp->info[0]));
3260 if (!resp) {
3261 WMA_LOGE(FL("resp allocation failed."));
3262 return QDF_STATUS_E_NOMEM;
3263 }
3264 resp->count = 0;
3265 peer_info = &resp->info[0];
3266 for (i = 0; i < event->num_peers; i++) {
3267 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3268 peer_info->peer_macaddr.bytes);
3269
3270 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3271 wma->peer_macaddr.bytes,
3272 QDF_MAC_ADDR_SIZE)) {
3273 wma_fill_peer_info(wma, stats_info, peer_info);
3274 resp->count++;
3275 break;
3276 }
3277
3278 stats_info = stats_info + 1;
3279 }
3280 } else {
3281 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3282 event->num_peers * sizeof(resp->info[0]));
3283 if (!resp) {
3284 WMA_LOGE(FL("resp allocation failed."));
3285 return QDF_STATUS_E_NOMEM;
3286 }
3287 resp->count = event->num_peers;
3288 for (i = 0; i < event->num_peers; i++) {
3289 peer_info = &resp->info[j];
3290 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3291 peer_info->peer_macaddr.bytes);
3292
3293 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3294 wma->myaddr, QDF_MAC_ADDR_SIZE)) {
3295 resp->count = resp->count - 1;
3296 } else {
3297 wma_fill_peer_info(wma, stats_info, peer_info);
3298 j++;
3299 }
3300 stats_info = stats_info + 1;
3301 }
3302 }
3303
3304 sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND;
3305 sme_msg.bodyptr = resp;
3306 sme_msg.bodyval = 0;
3307
3308 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3309 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3310 WMA_LOGE("%s: Fail to post get peer info msg", __func__);
3311 qdf_mem_free(resp);
3312 }
3313
3314 return qdf_status;
3315}
3316
3317/**
3318 * dump_peer_stats_info() - dump wmi peer info struct
3319 * @event: wmi peer info fixed param pointer
3320 * @peer_stats: wmi peer stats info pointer
3321 *
3322 * This function will dump wmi peer info struct
3323 *
3324 * Return: None
3325 */
3326static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event,
3327 wmi_peer_stats_info *peer_stats)
3328{
3329 int i;
3330 wmi_peer_stats_info *stats = peer_stats;
3331 u_int8_t mac[6];
3332
3333 WMA_LOGI("%s vdev_id %d, num_peers %d more_data %d",
3334 __func__, event->vdev_id,
3335 event->num_peers, event->more_data);
3336
3337 for (i = 0; i < event->num_peers; i++) {
3338 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
3339 WMA_LOGI("%s mac %pM", __func__, mac);
3340 WMA_LOGI("%s tx_bytes %d %d tx_packets %d %d",
3341 __func__,
3342 stats->tx_bytes.low_32,
3343 stats->tx_bytes.high_32,
3344 stats->tx_packets.low_32,
3345 stats->tx_packets.high_32);
3346 WMA_LOGI("%s rx_bytes %d %d rx_packets %d %d",
3347 __func__,
3348 stats->rx_bytes.low_32,
3349 stats->rx_bytes.high_32,
3350 stats->rx_packets.low_32,
3351 stats->rx_packets.high_32);
3352 WMA_LOGI("%s tx_retries %d tx_failed %d",
3353 __func__, stats->tx_retries, stats->tx_failed);
3354 WMA_LOGI("%s tx_rate_code %x rx_rate_code %x",
3355 __func__,
3356 stats->last_tx_rate_code,
3357 stats->last_rx_rate_code);
3358 WMA_LOGI("%s tx_rate %x rx_rate %x",
3359 __func__,
3360 stats->last_tx_bitrate_kbps,
3361 stats->last_rx_bitrate_kbps);
3362 WMA_LOGI("%s peer_rssi %d", __func__, stats->peer_rssi);
3363 stats++;
3364 }
3365}
3366
3367int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
3368 u_int32_t len)
3369{
3370 tp_wma_handle wma = (tp_wma_handle) handle;
3371 WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
3372 wmi_peer_stats_info_event_fixed_param *event;
3373 u_int32_t buf_size;
3374 u_int8_t *buf;
3375
3376 param_buf =
3377 (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info;
3378 if (!param_buf) {
3379 WMA_LOGA("%s: Invalid stats event", __func__);
3380 return -EINVAL;
3381 }
3382
3383 WMA_LOGI("%s Recv WMI_PEER_STATS_INFO_EVENTID", __func__);
3384 event = param_buf->fixed_param;
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003385 if (event->num_peers >
Abhinav Kumara03659c2017-12-28 15:18:07 +05303386 ((WMI_SVC_MSG_MAX_SIZE -
3387 sizeof(wmi_peer_stats_info_event_fixed_param))/
3388 sizeof(wmi_peer_stats_info)) || event->num_peers >
3389 param_buf->num_peer_stats_info) {
3390 WMA_LOGE("Excess num of peers from fw: %d, num_peer_stats_info:%d",
3391 event->num_peers, param_buf->num_peer_stats_info);
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003392 return -EINVAL;
3393 }
Will Huanga9814592017-05-24 15:47:58 +08003394 buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) +
3395 sizeof(wmi_peer_stats_info) * event->num_peers;
3396 buf = qdf_mem_malloc(buf_size);
3397 if (!buf) {
3398 WMA_LOGE("%s: Failed alloc memory for buf", __func__);
3399 return -ENOMEM;
3400 }
3401
3402 qdf_mem_copy(buf, param_buf->fixed_param,
3403 sizeof(wmi_peer_stats_info_event_fixed_param));
3404 qdf_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)),
3405 param_buf->peer_stats_info,
3406 sizeof(wmi_peer_stats_info) * event->num_peers);
3407 WMA_LOGI("%s dump peer stats info", __func__);
3408 dump_peer_stats_info(event, param_buf->peer_stats_info);
3409
3410 wma_peer_info_ext_rsp(wma, buf);
3411 qdf_mem_free(buf);
3412
3413 return 0;
3414}
3415
3416/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 * wma_send_link_speed() - send link speed to SME
3418 * @link_speed: link speed
3419 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303420 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303422QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303424 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303425 tpAniSirGlobal mac_ctx;
3426 tSirLinkSpeedInfo *ls_ind;
3427
3428 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
3429 if (!mac_ctx) {
3430 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
3431 return QDF_STATUS_E_INVAL;
3432 }
3433
3434 ls_ind = (tSirLinkSpeedInfo *)qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 if (!ls_ind) {
3436 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303437 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 } else {
3439 ls_ind->estLinkSpeed = link_speed;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303440 if (mac_ctx->sme.pLinkSpeedIndCb)
3441 mac_ctx->sme.pLinkSpeedIndCb(ls_ind,
3442 mac_ctx->sme.pLinkSpeedCbContext);
3443 else
3444 WMA_LOGD("%s: pLinkSpeedIndCb is null", __func__);
3445 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003446
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303448 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003449}
3450
3451/**
3452 * wma_link_speed_event_handler() - link speed event handler
3453 * @handle: wma handle
3454 * @cmd_param_info: event data
3455 * @len: length
3456 *
3457 * Return: 0 for success or error code
3458 */
3459int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
3460 uint32_t len)
3461{
3462 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
3463 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303464 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003466 param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)
3467 cmd_param_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468 if (!param_buf) {
3469 WMA_LOGE("%s: Invalid linkspeed event", __func__);
3470 return -EINVAL;
3471 }
3472 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303473 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003474 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 return 0;
3477}
3478
3479/**
3480 * wma_wni_cfg_dnld() - cfg download request
3481 * @handle: wma handle
3482 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303483 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303485QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303487 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303488 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489
3490 WMA_LOGD("%s: Enter", __func__);
3491
3492 if (NULL == mac) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003493 WMA_LOGE("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303494 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303495 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003496 }
3497
3498 process_cfg_download_req(mac);
3499
3500 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303501 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003502}
3503
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303504#define BIG_ENDIAN_MAX_DEBUG_BUF 500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505/**
3506 * wma_unified_debug_print_event_handler() - debug print event handler
3507 * @handle: wma handle
3508 * @datap: data pointer
3509 * @len: length
3510 *
3511 * Return: 0 for success or error code
3512 */
3513int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
3514 uint32_t len)
3515{
3516 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
3517 uint8_t *data;
3518 uint32_t datalen;
3519
3520 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303521 if (!param_buf || !param_buf->data) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522 WMA_LOGE("Get NULL point message from FW");
3523 return -ENOMEM;
3524 }
3525 data = param_buf->data;
3526 datalen = param_buf->num_data;
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303527 if (datalen > WMI_SVC_MSG_MAX_SIZE) {
3528 WMA_LOGE("Received data len %d exceeds max value %d",
3529 datalen, WMI_SVC_MSG_MAX_SIZE);
3530 return QDF_STATUS_E_FAILURE;
3531 }
3532 data[datalen - 1] = '\0';
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533
3534#ifdef BIG_ENDIAN_HOST
3535 {
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303536 if (datalen >= BIG_ENDIAN_MAX_DEBUG_BUF) {
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303537 WMA_LOGE("%s Invalid data len %d, limiting to max",
3538 __func__, datalen);
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303539 datalen = BIG_ENDIAN_MAX_DEBUG_BUF - 1;
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303540 }
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003541 char dbgbuf[BIG_ENDIAN_MAX_DEBUG_BUF] = { 0 };
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003542
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003543 memcpy(dbgbuf, data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003544 SWAPME(dbgbuf, datalen);
3545 WMA_LOGD("FIRMWARE:%s", dbgbuf);
3546 return 0;
3547 }
3548#else
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003549 WMA_LOGD("FIRMWARE:%s", data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003550 return 0;
3551#endif /* BIG_ENDIAN_HOST */
3552}
3553
3554/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555 * wma_is_sap_active() - check sap is active or not
3556 * @handle: wma handle
3557 *
3558 * Return: true/false
3559 */
3560bool wma_is_sap_active(tp_wma_handle wma_handle)
3561{
3562 int i;
3563
3564 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303565 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 continue;
3567 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3568 wma_handle->interfaces[i].sub_type == 0)
3569 return true;
3570 }
3571 return false;
3572}
3573
3574/**
3575 * wma_is_p2p_go_active() - check p2p go is active or not
3576 * @handle: wma handle
3577 *
3578 * Return: true/false
3579 */
3580bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
3581{
3582 int i;
3583
3584 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303585 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586 continue;
3587 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3588 wma_handle->interfaces[i].sub_type ==
3589 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
3590 return true;
3591 }
3592 return false;
3593}
3594
3595/**
3596 * wma_is_p2p_cli_active() - check p2p cli is active or not
3597 * @handle: wma handle
3598 *
3599 * Return: true/false
3600 */
3601bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
3602{
3603 int i;
3604
3605 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303606 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 continue;
3608 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3609 wma_handle->interfaces[i].sub_type ==
3610 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
3611 return true;
3612 }
3613 return false;
3614}
3615
3616/**
3617 * wma_is_sta_active() - check sta is active or not
3618 * @handle: wma handle
3619 *
3620 * Return: true/false
3621 */
3622bool wma_is_sta_active(tp_wma_handle wma_handle)
3623{
3624 int i;
3625
3626 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303627 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003628 continue;
3629 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3630 wma_handle->interfaces[i].sub_type == 0)
3631 return true;
3632 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
3633 return true;
3634 }
3635 return false;
3636}
3637
3638/**
3639 * wma_peer_phymode() - get phymode
3640 * @nw_type: nw type
3641 * @sta_type: sta type
3642 * @is_ht: is ht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003643 * @ch_width: supported channel width
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 * @is_vht: is vht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003645 * @is_he: is HE supported
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646 *
3647 * Return: WLAN_PHY_MODE
3648 */
3649WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
3650 uint8_t is_ht, uint8_t ch_width,
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003651 uint8_t is_vht, bool is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003652{
3653 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
3654
3655 switch (nw_type) {
3656 case eSIR_11B_NW_TYPE:
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003657#ifdef FEATURE_WLAN_TDLS
3658 if (STA_ENTRY_TDLS_PEER == sta_type) {
3659 if (is_vht) {
3660 if (CH_WIDTH_80MHZ == ch_width)
3661 phymode = MODE_11AC_VHT80;
3662 else
3663 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3664 MODE_11AC_VHT40 :
3665 MODE_11AC_VHT20;
3666 } else if (is_ht) {
3667 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3668 MODE_11NG_HT40 : MODE_11NG_HT20;
3669 } else
3670 phymode = MODE_11B;
3671 } else
3672#endif /* FEATURE_WLAN_TDLS */
3673 {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674 phymode = MODE_11B;
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003675 if (is_ht || is_vht || is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003676 WMA_LOGE("HT/VHT is enabled with 11B NW type");
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003677 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678 break;
3679 case eSIR_11G_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003680 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 phymode = MODE_11G;
3682 break;
3683 }
3684 if (CH_WIDTH_40MHZ < ch_width)
3685 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
3686 if (ch_width)
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003687 phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ?
3688 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 else
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003690 phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ?
3691 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 break;
3693 case eSIR_11A_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003694 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003695 phymode = MODE_11A;
3696 break;
3697 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003698 if (is_he) {
3699 if (ch_width == CH_WIDTH_160MHZ)
3700 phymode = MODE_11AX_HE160;
3701 else if (ch_width == CH_WIDTH_80P80MHZ)
3702 phymode = MODE_11AX_HE80_80;
3703 else if (ch_width == CH_WIDTH_80MHZ)
3704 phymode = MODE_11AX_HE80;
3705 else
3706 phymode = (ch_width) ?
3707 MODE_11AX_HE40 : MODE_11AX_HE20;
3708 } else if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 if (ch_width == CH_WIDTH_160MHZ)
3710 phymode = MODE_11AC_VHT160;
3711 else if (ch_width == CH_WIDTH_80P80MHZ)
3712 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07003713 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003714 phymode = MODE_11AC_VHT80;
3715 else
3716 phymode = (ch_width) ?
3717 MODE_11AC_VHT40 : MODE_11AC_VHT20;
3718 } else
3719 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
3720 break;
3721 default:
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003722 WMA_LOGE("%s: Invalid nw type %d", __func__, nw_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723 break;
3724 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003725 WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"),
3726 nw_type, is_ht, ch_width, is_vht, is_he, phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003727
3728 return phymode;
3729}
3730
3731/**
3732 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
3733 * @wma_handle: wma handle
3734 * @vdev_id: vdev id
3735 * @value: value
3736 *
3737 * Return: 0 for success or return error
3738 */
3739int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
3740 uint8_t vdev_id, uint32_t value)
3741{
3742 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003743 struct cdp_vdev *vdev;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303744 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3745
3746 if (!soc) {
3747 WMA_LOGE("%s:SOC context is NULL", __func__);
3748 return -EINVAL;
3749 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750
3751 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3752 if (!vdev) {
3753 WMA_LOGE("%s:Invalid vdev handle", __func__);
3754 return -EINVAL;
3755 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303756 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757 req.stats_type_reset_mask = value;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003758 cdp_fw_stats_get(soc, vdev, &req, false, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003759
3760 return 0;
3761}
3762
3763#ifdef HELIUMPLUS
Jeff Johnson560dc562017-03-17 15:19:31 -07003764#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765 ((_mask) = 1 << (_rate_info ## _V2))
3766#else /* !HELIUMPLUS */
Jeff Johnson560dc562017-03-17 15:19:31 -07003767#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 ((_mask) = 1 << (_rate_info))
3769#endif
3770
Nirav Shah93e789e2016-04-14 19:47:43 +05303771#ifdef HELIUMPLUS
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003772static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303773{
3774 if (value > (HTT_DBG_NUM_STATS + 1) ||
3775 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
3776 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
3777 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3778 WMA_LOGE("%s: Not supported", __func__);
3779 return false;
3780 }
3781 return true;
3782}
3783#else
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003784static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303785{
3786 if (value > (HTT_DBG_NUM_STATS + 1) ||
3787 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
3788 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
3789 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3790 WMA_LOGE("%s: Not supported", __func__);
3791 return false;
3792 }
3793 return true;
3794}
3795#endif
3796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797/**
3798 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
3799 * @wma_handle: wma handle
3800 * @vdev_id: vdev id
3801 * @value: value
3802 *
3803 * Return: 0 for success or return error
3804 */
3805int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
3806 uint8_t vdev_id, uint32_t value)
3807{
3808 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003809 struct cdp_vdev *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 uint32_t l_up_mask;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303811 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3812
3813 if (!soc) {
3814 WMA_LOGE("%s:SOC context is NULL", __func__);
3815 return -EINVAL;
3816 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817
3818 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3819 if (!vdev) {
3820 WMA_LOGE("%s:Invalid vdev handle", __func__);
3821 return -EINVAL;
3822 }
Nirav Shah93e789e2016-04-14 19:47:43 +05303823
3824 if (wma_is_valid_fw_stats_cmd(value) == false)
3825 return -EINVAL;
3826
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303827 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828 req.print.verbose = 1;
3829
Nirav Shah93e789e2016-04-14 19:47:43 +05303830 /* TODO: Need to check how to avoid mem leak*/
3831 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003832 req.stats_type_upload_mask = l_up_mask;
3833
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003834 cdp_fw_stats_get(soc, vdev, &req, false, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003835
3836 return 0;
3837}
3838
3839/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 * wma_get_stats_rsp_buf() - fill get stats response buffer
3841 * @get_stats_param: get stats parameters
3842 *
3843 * Return: stats response buffer
3844 */
3845static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
3846 (tAniGetPEStatsReq *get_stats_param)
3847{
3848 tAniGetPEStatsRsp *stats_rsp_params;
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003849 uint32_t len, temp_mask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850
3851 len = sizeof(tAniGetPEStatsRsp);
3852 temp_mask = get_stats_param->statsMask;
3853
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003854 if (temp_mask & (1 << eCsrSummaryStats))
3855 len += sizeof(tCsrSummaryStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003857 if (temp_mask & (1 << eCsrGlobalClassAStats))
3858 len += sizeof(tCsrGlobalClassAStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003860 if (temp_mask & (1 << eCsrGlobalClassDStats))
3861 len += sizeof(tCsrGlobalClassDStatsInfo);
3862
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003863 if (temp_mask & (1 << csr_per_chain_rssi_stats))
3864 len += sizeof(struct csr_per_chain_rssi_stats_info);
3865
3866 stats_rsp_params = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003867 if (!stats_rsp_params) {
3868 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303869 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003870 return NULL;
3871 }
3872
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003873 stats_rsp_params->staId = get_stats_param->staId;
3874 stats_rsp_params->statsMask = get_stats_param->statsMask;
3875 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
3876 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303877 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 return stats_rsp_params;
3879}
3880
3881/**
3882 * wma_get_stats_req() - get stats request
3883 * @handle: wma handle
3884 * @get_stats_param: stats params
3885 *
3886 * Return: none
3887 */
3888void wma_get_stats_req(WMA_HANDLE handle,
3889 tAniGetPEStatsReq *get_stats_param)
3890{
3891 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3892 struct wma_txrx_node *node;
Dustin Brown35619492017-10-03 15:16:12 -07003893 struct stats_request_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05303895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896
3897 WMA_LOGD("%s: Enter", __func__);
3898 node = &wma_handle->interfaces[get_stats_param->sessionId];
3899 if (node->stats_rsp) {
3900 pGetPEStatsRspParams = node->stats_rsp;
3901 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
3902 pGetPEStatsRspParams->statsMask ==
3903 get_stats_param->statsMask) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003904 WMA_LOGD("Stats for staId %d with stats mask %d is pending.. ignore new request",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 get_stats_param->staId,
3906 get_stats_param->statsMask);
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303907 pGetPEStatsRspParams =
3908 wma_get_stats_rsp_buf(get_stats_param);
3909 if (!pGetPEStatsRspParams) {
3910 WMA_LOGE("failed to allocate memory for stats response");
3911 goto end;
3912 }
3913 goto req_pending;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003914 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303915 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916 node->stats_rsp = NULL;
3917 node->fw_stats_set = 0;
3918 }
3919 }
3920
3921 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
3922 if (!pGetPEStatsRspParams)
3923 goto end;
3924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925 node->fw_stats_set = 0;
Naveen Rawat3c49d192017-03-02 18:43:16 -08003926 if (node->stats_rsp) {
Jeff Johnsonadba3962017-09-18 08:12:35 -07003927 WMA_LOGD(FL("stats_rsp is not null, prev_value: %pK"),
Naveen Rawat3c49d192017-03-02 18:43:16 -08003928 node->stats_rsp);
3929 qdf_mem_free(node->stats_rsp);
3930 node->stats_rsp = NULL;
3931 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003932 node->stats_rsp = pGetPEStatsRspParams;
Will Huanga9814592017-05-24 15:47:58 +08003933 wma_handle->get_sta_peer_info = false;
Jeff Johnsonadba3962017-09-18 08:12:35 -07003934 WMA_LOGD("stats_rsp allocated: %pK, sta_id: %d, mask: %d, vdev_id: %d",
Naveen Rawat3c49d192017-03-02 18:43:16 -08003935 node->stats_rsp, node->stats_rsp->staId,
3936 node->stats_rsp->statsMask, get_stats_param->sessionId);
Govind Singh4863da42016-03-08 11:45:00 +05303937
Dustin Brown35619492017-10-03 15:16:12 -07003938 cmd.vdev_id = get_stats_param->sessionId;
3939 cmd.stats_id = get_stats_param->statsMask;
3940 if (wmi_unified_stats_request_send(wma_handle->wmi_handle,
3941 node->bssid,
3942 &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
3944 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945 goto failed;
3946 }
3947
3948 goto end;
3949failed:
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303950 node->stats_rsp = NULL;
3951req_pending:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303952 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003953 /* send response to UMAC */
3954 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
3955 0);
3956end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303957 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958 WMA_LOGD("%s: Exit", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003959}
3960
3961/**
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303962 * wma_get_cca_stats() - send request to fw to get CCA
3963 * @wma_handle: wma handle
3964 * @vdev_id: vdev id
3965 *
3966 * Return: QDF status
3967 */
3968QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
3969 uint8_t vdev_id)
3970{
3971 if (wmi_unified_congestion_request_cmd(wma_handle->wmi_handle,
3972 vdev_id)) {
3973 WMA_LOGE("Failed to congestion request to fw");
3974 return QDF_STATUS_E_FAILURE;
3975 }
3976 return QDF_STATUS_SUCCESS;
3977}
3978
3979/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003980 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
3981 * @vdev_id: vdev id
3982 * @buffer_size: size of buffer
3983 *
3984 * Return: none
3985 */
3986void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
3987{
3988 tp_wma_handle wma;
3989 struct beacon_info *beacon;
3990 uint8_t *buf;
3991 uint32_t buf_size;
3992
Anurag Chouhan6d760662016-02-20 16:05:43 +05303993 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994 if (!wma) {
3995 WMA_LOGE("%s: Invalid WMA handle", __func__);
3996 return NULL;
3997 }
3998
3999 if (vdev_id >= wma->max_bssid) {
4000 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
4001 return NULL;
4002 }
4003
4004 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
4005 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
4006 return NULL;
4007 }
4008
4009 beacon = wma->interfaces[vdev_id].beacon;
4010
4011 if (!beacon) {
4012 WMA_LOGE("%s: beacon invalid", __func__);
4013 return NULL;
4014 }
4015
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304016 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017
Nirav Shahcbc6d722016-03-01 16:24:53 +05304018 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304019 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020
4021 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304022 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
4024 return NULL;
4025 }
4026
Nirav Shahcbc6d722016-03-01 16:24:53 +05304027 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304029 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030
4031 if (buffer_size)
4032 *buffer_size = buf_size;
4033
4034 return buf;
4035}
4036
4037/**
4038 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
4039 * @vdev_id: vdev id
4040 *
4041 * Return: mac address
4042 */
4043uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
4044{
4045 tp_wma_handle wma;
4046
Anurag Chouhan6d760662016-02-20 16:05:43 +05304047 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 if (!wma) {
4049 WMA_LOGE("%s: Invalid WMA handle", __func__);
4050 return NULL;
4051 }
4052
4053 if (vdev_id >= wma->max_bssid) {
4054 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
4055 return NULL;
4056 }
4057
4058 return wma->interfaces[vdev_id].addr;
4059}
4060
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004061QDF_STATUS wma_get_connection_info(uint8_t vdev_id,
4062 struct policy_mgr_vdev_entry_info *conn_table_entry)
4063{
4064 struct wma_txrx_node *wma_conn_table_entry;
4065
4066 wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id);
4067 if (NULL == wma_conn_table_entry) {
4068 WMA_LOGE("%s: can't find vdev_id %d in WMA table", __func__, vdev_id);
4069 return QDF_STATUS_E_FAILURE;
4070 }
4071 conn_table_entry->chan_width = wma_conn_table_entry->chan_width;
4072 conn_table_entry->mac_id = wma_conn_table_entry->mac_id;
4073 conn_table_entry->mhz = wma_conn_table_entry->mhz;
4074 conn_table_entry->sub_type = wma_conn_table_entry->sub_type;
4075 conn_table_entry->type = wma_conn_table_entry->type;
4076
4077 return QDF_STATUS_SUCCESS;
4078}
4079
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004080/**
4081 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
4082 * @vdev_id: vdev id
4083 *
4084 * Return: entry from vdev table
4085 */
4086struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
4087{
4088 tp_wma_handle wma;
4089
Anurag Chouhan6d760662016-02-20 16:05:43 +05304090 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 if (!wma) {
4092 WMA_LOGE("%s: Invalid WMA handle", __func__);
4093 return NULL;
4094 }
4095
4096 if (vdev_id >= wma->max_bssid) {
4097 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
4098 return NULL;
4099 }
4100
4101 return &wma->interfaces[vdev_id];
4102}
4103
Jeff Johnsonabb74042017-08-31 11:44:55 -07004104QDF_STATUS wma_get_wcnss_software_version(uint8_t *version,
4105 uint32_t version_buffer_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004107 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304108 struct target_psoc_info *tgt_hdl;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109
4110 if (NULL == wma_handle) {
4111 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304112 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113 }
4114
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304115 tgt_hdl = wlan_psoc_get_tgt_if_handle(wma_handle->psoc);
4116 if (!tgt_hdl) {
4117 WMA_LOGE("%s: Failed to get wma", __func__);
4118 return QDF_STATUS_E_FAULT;
4119 }
4120
Jeff Johnsonabb74042017-08-31 11:44:55 -07004121 snprintf(version, version_buffer_size, "%x",
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304122 target_if_get_fw_version(tgt_hdl));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304123 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124}
4125
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004126/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
4128 * @vdev_id: VDEV whose MAC ID is required
4129 *
4130 * Get MAC id corresponding to a vdev id from the WMA structure
4131 *
4132 * Return: Negative value on failure and MAC id on success
4133 */
4134int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
4135{
4136 tp_wma_handle wma;
4137
Anurag Chouhan6d760662016-02-20 16:05:43 +05304138 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 if (!wma) {
4140 WMA_LOGE("%s: Invalid WMA handle", __func__);
4141 return -EINVAL;
4142 }
4143
4144 if (wma->interfaces)
4145 return wma->interfaces[vdev_id].mac_id;
4146
4147 return -EINVAL;
4148}
4149
4150/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151 * wma_update_intf_hw_mode_params() - Update WMA params
4152 * @vdev_id: VDEV id whose params needs to be updated
4153 * @mac_id: MAC id to be updated
4154 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
4155 *
4156 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
4157 *
4158 * Return: None
4159 */
4160void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
4161 uint32_t cfgd_hw_mode_index)
4162{
4163 tp_wma_handle wma;
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004164 uint32_t param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004165
Anurag Chouhan6d760662016-02-20 16:05:43 +05304166 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004167 if (!wma) {
4168 WMA_LOGE("%s: Invalid WMA handle", __func__);
4169 return;
4170 }
4171
4172 if (!wma->interfaces) {
4173 WMA_LOGE("%s: Interface is NULL", __func__);
4174 return;
4175 }
4176
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004177 if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) {
4178 WMA_LOGE("%s: Invalid index", __func__);
4179 return;
4180 }
4181
4182 param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 wma->interfaces[vdev_id].mac_id = mac_id;
4184 if (mac_id == 0) {
4185 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304186 WMA_HW_MODE_MAC0_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304188 WMA_HW_MODE_MAC0_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189 } else {
4190 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304191 WMA_HW_MODE_MAC1_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304193 WMA_HW_MODE_MAC1_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004194 }
4195}
4196
4197/**
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004198 * wma_get_vht_ch_width - return vht channel width
4199 *
4200 * Return: return vht channel width
4201 */
4202uint32_t wma_get_vht_ch_width(void)
4203{
4204 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304205 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304206 struct target_psoc_info *tgt_hdl;
4207 int vht_cap_info;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004208
4209 if (NULL == wm_hdl)
4210 return fw_ch_wd;
4211
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304212 tgt_hdl = wlan_psoc_get_tgt_if_handle(wm_hdl->psoc);
4213 if (!tgt_hdl)
4214 return fw_ch_wd;
4215
4216 vht_cap_info = target_if_get_vht_cap_info(tgt_hdl);
4217 if (vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004218 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304219 else if (vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004220 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004221
4222 return fw_ch_wd;
4223}
Govind Singhd76a5b02016-03-08 15:12:14 +05304224
4225/**
Krunal Soniaa664da2016-06-15 23:46:40 -07004226 * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
4227 * @mask: given bitmask
4228 *
4229 * This helper function should return number of setbits from bitmask
4230 *
4231 * Return: number of setbits from bitmask
4232 */
4233uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
4234{
4235 uint32_t num_of_setbits = 0;
4236
4237 while (mask) {
4238 mask &= (mask - 1);
4239 num_of_setbits++;
4240 }
4241 return num_of_setbits;
4242}
4243
4244/**
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004245 * wma_is_csa_offload_enabled - checks fw CSA offload capability
4246 *
4247 * Return: true or false
4248 */
4249
4250bool wma_is_csa_offload_enabled(void)
4251{
4252 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4253
4254 if (!wma)
4255 return false;
4256
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304257 return wmi_service_enabled(wma->wmi_handle,
4258 wmi_service_csa_offload);
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004259}
4260/**
Govind Singhd76a5b02016-03-08 15:12:14 +05304261 * wma_config_debug_module_cmd - set debug log config
4262 * @wmi_handle: wmi layer handle
4263 * @param: debug log parameter
4264 * @val: debug log value
4265 * @module_id_bitmap: debug module id bitmap
4266 * @bitmap_len: debug module bitmap length
4267 *
4268 * Return: QDF_STATUS_SUCCESS for success or error code
4269 */
4270QDF_STATUS
4271wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
4272 A_UINT32 val, A_UINT32 *module_id_bitmap,
4273 A_UINT32 bitmap_len)
4274{
4275 struct dbglog_params dbg_param;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004276
Govind Singhd76a5b02016-03-08 15:12:14 +05304277 dbg_param.param = param;
4278 dbg_param.val = val;
4279 dbg_param.module_id_bitmap = module_id_bitmap;
4280 dbg_param.bitmap_len = bitmap_len;
4281
4282 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
4283}
Peng Xu8fdaa492016-06-22 10:20:47 -07004284
4285/**
4286 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
4287 *
4288 * This function checks if driver is capable of p2p listen offload
4289 * true: capable of p2p offload
4290 * false: not capable
4291 *
4292 * Return: true - capable, false - not capable
4293 */
4294bool wma_is_p2p_lo_capable(void)
4295{
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304296 return wma_is_service_enabled(wmi_service_p2p_listen_offload_support);
Peng Xu8fdaa492016-06-22 10:20:47 -07004297}
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004298
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004299bool wma_capability_enhanced_mcast_filter(void)
4300{
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304301 return wma_is_service_enabled(wmi_service_enhanced_mcast_filter);
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004302}
4303
4304
Mukul Sharmaf9047232017-03-02 16:58:56 +05304305bool wma_is_vdev_up(uint8_t vdev_id)
4306{
4307 struct wlan_objmgr_vdev *vdev;
4308 tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
4309 enum wlan_vdev_state state = WLAN_VDEV_S_INIT;
4310
4311 if (!wma) {
4312 WMA_LOGE("%s: WMA context is invald!", __func__);
4313 return false;
4314 }
4315
4316 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
4317 WLAN_LEGACY_WMA_ID);
4318 if (vdev) {
4319 wlan_vdev_obj_lock(vdev);
4320 state = wlan_vdev_mlme_get_state(vdev);
4321 wlan_vdev_obj_unlock(vdev);
4322 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4323 }
Mukul Sharmaf9047232017-03-02 16:58:56 +05304324 return (state == WLAN_VDEV_S_RUN) ? true : false;
4325}
4326
Dustin Brownec2c92e2017-07-26 11:13:49 -07004327void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004328{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004329 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4330
4331 cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4332 qdf_wake_lock_timeout_acquire(wl, msec);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004333 qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004334}
4335
Dustin Brownec2c92e2017-07-26 11:13:49 -07004336void wma_release_wakelock(qdf_wake_lock_t *wl)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004337{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004338 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4339
4340 qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004341 qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004342}
4343
Dustin Brownd5f12942017-03-10 11:06:25 -08004344QDF_STATUS
4345wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
4346{
4347 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004348 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
Dustin Brownd5f12942017-03-10 11:06:25 -08004349
Dustin Brownec2c92e2017-07-26 11:13:49 -07004350 wma_acquire_wakelock(&vdev->vdev_start_wakelock,
4351 WMA_VDEV_START_REQUEST_TIMEOUT);
Dustin Brownd5f12942017-03-10 11:06:25 -08004352 status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
4353 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004354 wma_release_wakelock(&vdev->vdev_start_wakelock);
Dustin Brownd5f12942017-03-10 11:06:25 -08004355
4356 return status;
4357}
4358
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004359QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4360{
4361 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004362 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004363
Dustin Brownec2c92e2017-07-26 11:13:49 -07004364 wma_acquire_wakelock(&vdev->vdev_stop_wakelock,
4365 WMA_VDEV_STOP_REQUEST_TIMEOUT);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004366 status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id);
4367 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004368 wma_release_wakelock(&vdev->vdev_stop_wakelock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004369
4370 return status;
4371}
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004372
Rajeev Kumar Sirasanagandla996e5292016-11-22 21:20:33 +05304373QDF_STATUS wma_get_rcpi_req(WMA_HANDLE handle,
4374 struct sme_rcpi_req *rcpi_request)
4375{
4376 tp_wma_handle wma_handle = (tp_wma_handle) handle;
4377 struct rcpi_req cmd = {0};
4378 struct wma_txrx_node *iface;
4379 struct sme_rcpi_req *node_rcpi_req;
4380
4381 WMA_LOGD("%s: Enter", __func__);
4382 iface = &wma_handle->interfaces[rcpi_request->session_id];
4383 /* command is in progress */
4384 if (iface->rcpi_req != NULL) {
4385 WMA_LOGE("%s : previous rcpi request is pending", __func__);
4386 return QDF_STATUS_SUCCESS;
4387 }
4388
4389 node_rcpi_req = qdf_mem_malloc(sizeof(*node_rcpi_req));
4390 if (!node_rcpi_req) {
4391 WMA_LOGE("Failed to allocate memory for rcpi_request");
4392 return QDF_STATUS_E_NOMEM;
4393 }
4394
4395 *node_rcpi_req = *rcpi_request;
4396 iface->rcpi_req = node_rcpi_req;
4397
4398 cmd.vdev_id = rcpi_request->session_id;
4399 qdf_mem_copy(cmd.mac_addr, &rcpi_request->mac_addr, QDF_MAC_ADDR_SIZE);
Tushnim Bhattacharyya0725f1a2018-03-28 13:01:45 -07004400 cmd.measurement_type = rcpi_request->measurement_type;
Rajeev Kumar Sirasanagandla996e5292016-11-22 21:20:33 +05304401
4402 if (wmi_unified_send_request_get_rcpi_cmd(wma_handle->wmi_handle,
4403 &cmd)) {
4404 WMA_LOGE("%s: Failed to send WMI_REQUEST_RCPI_CMDID",
4405 __func__);
4406 iface->rcpi_req = NULL;
4407 qdf_mem_free(node_rcpi_req);
4408 return QDF_STATUS_E_FAILURE;
4409 }
4410
4411 WMA_LOGD("%s: Exit", __func__);
4412
4413 return QDF_STATUS_SUCCESS;
4414}
4415
4416int wma_rcpi_event_handler(void *handle, uint8_t *cmd_param_info,
4417 uint32_t len)
4418{
4419 struct rcpi_res res = {0};
4420 struct sme_rcpi_req *rcpi_req;
4421 struct qdf_mac_addr qdf_mac;
4422 struct wma_txrx_node *iface;
4423 QDF_STATUS status = QDF_STATUS_SUCCESS;
4424 tp_wma_handle wma_handle = (tp_wma_handle)handle;
4425
4426 status = wmi_extract_rcpi_response_event(wma_handle->wmi_handle,
4427 cmd_param_info, &res);
4428 if (status == QDF_STATUS_E_INVAL)
4429 return -EINVAL;
4430
4431 iface = &wma_handle->interfaces[res.vdev_id];
4432 if (!iface->rcpi_req) {
4433 WMI_LOGE("rcpi_req buffer not available");
4434 return 0;
4435 }
4436
4437 rcpi_req = iface->rcpi_req;
4438 if (!rcpi_req->rcpi_callback) {
4439 iface->rcpi_req = NULL;
4440 qdf_mem_free(rcpi_req);
4441 return 0;
4442 }
4443
4444 if ((res.measurement_type == RCPI_MEASUREMENT_TYPE_INVALID) ||
4445 (res.vdev_id != rcpi_req->session_id) ||
4446 (res.measurement_type != rcpi_req->measurement_type) ||
4447 (qdf_mem_cmp(res.mac_addr, &rcpi_req->mac_addr,
4448 QDF_MAC_ADDR_SIZE))) {
4449 WMI_LOGE("invalid rcpi_response");
4450 iface->rcpi_req = NULL;
4451 qdf_mem_free(rcpi_req);
4452 return 0;
4453 }
4454
4455 qdf_mem_copy(&qdf_mac, res.mac_addr, QDF_MAC_ADDR_SIZE);
4456 (rcpi_req->rcpi_callback)(rcpi_req->rcpi_context, qdf_mac,
4457 res.rcpi_value, status);
4458 iface->rcpi_req = NULL;
4459 qdf_mem_free(rcpi_req);
4460
4461 return 0;
4462}
4463
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304464bool wma_is_service_enabled(uint32_t service_type)
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004465{
4466 tp_wma_handle wma;
Srinivas Girigowda4d65ebe2017-10-13 21:41:42 -07004467
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004468 wma = cds_get_context(QDF_MODULE_ID_WMA);
4469 if (!wma) {
4470 WMA_LOGE("%s: Invalid WMA handle", __func__);
4471 return false;
4472 }
4473
Yun Park01a45f72018-01-04 15:30:59 -08004474 if (service_type >= WMI_MAX_SERVICE) {
4475 WMA_LOGE("%s: Invalid service type %d", __func__, service_type);
4476 return false;
4477 }
4478
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304479 return wmi_service_enabled(wma->wmi_handle, service_type);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004480}
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004481
Dustin Brownec2c92e2017-07-26 11:13:49 -07004482QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
4483 struct vdev_up_params *params,
4484 uint8_t bssid[IEEE80211_ADDR_LEN])
4485{
4486 QDF_STATUS status;
4487 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
4488
Varun Reddy Yeturu5303e082017-10-24 14:20:00 -07004489 if (wma_is_vdev_up(params->vdev_id)) {
4490 WMA_LOGD("vdev %d is already up for bssid %pM. Do not send",
4491 params->vdev_id, bssid);
4492 return QDF_STATUS_SUCCESS;
4493 }
Dustin Brownec2c92e2017-07-26 11:13:49 -07004494 status = wmi_unified_vdev_up_send(wma->wmi_handle, bssid, params);
4495 wma_release_wakelock(&vdev->vdev_start_wakelock);
4496
4497 return status;
4498}
4499
4500QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4501{
4502 QDF_STATUS status;
4503 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
4504
Tushnim Bhattacharyyaeb622b02018-05-07 13:50:51 -07004505 wma->interfaces[vdev_id].roaming_in_progress = false;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004506 status = wmi_unified_vdev_down_send(wma->wmi_handle, vdev_id);
4507 wma_release_wakelock(&vdev->vdev_start_wakelock);
4508
4509 return status;
4510}
4511
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004512tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
4513{
4514 switch (type) {
4515 case WMI_PEER_TYPE_DEFAULT:
4516 return WIFI_PEER_STA;
4517 case WMI_PEER_TYPE_BSS:
4518 return WIFI_PEER_AP;
4519 case WMI_PEER_TYPE_TDLS:
4520 return WIFI_PEER_TDLS;
4521 case WMI_PEER_TYPE_NAN_DATA:
4522 return WIFI_PEER_NAN;
4523 default:
4524 WMA_LOGE("Cannot map wmi_peer_type %d to HAL peer type", type);
4525 return WIFI_PEER_INVALID;
4526 }
4527}
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304528
Nachiket Kukade8983cf62017-10-12 18:14:48 +05304529/**
4530 * wma_set_vc_mode_config() - set voltage corner mode config to FW.
4531 * @wma_handle: pointer to wma handle.
4532 * @vc_bitmap: value needs to set to firmware.
4533 *
4534 * At the time of driver startup, set operating voltage corner mode
4535 * for differenet phymode and bw configurations.
4536 *
4537 * Return: QDF_STATUS.
4538 */
4539QDF_STATUS wma_set_vc_mode_config(void *wma_handle,
4540 uint32_t vc_bitmap)
4541{
4542 int32_t ret;
4543 tp_wma_handle wma = (tp_wma_handle)wma_handle;
4544 struct pdev_params pdevparam;
4545
4546 pdevparam.param_id = WMI_PDEV_UPDATE_WDCVS_ALGO;
4547 pdevparam.param_value = vc_bitmap;
4548
4549 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
4550 &pdevparam,
4551 WMA_WILDCARD_PDEV_ID);
4552 if (ret) {
4553 WMA_LOGE("Fail to Set Voltage Corner config (0x%x)",
4554 vc_bitmap);
4555 return QDF_STATUS_E_FAILURE;
4556 }
4557
4558 WMA_LOGD("Successfully Set Voltage Corner config (0x%x)",
4559 vc_bitmap);
4560
4561 return QDF_STATUS_SUCCESS;
4562}
4563
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304564int wma_chip_power_save_failure_detected_handler(void *handle,
4565 uint8_t *cmd_param_info,
4566 uint32_t len)
4567{
4568 tp_wma_handle wma = (tp_wma_handle)handle;
4569 WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
4570 wmi_chip_power_save_failure_detected_fixed_param *event;
4571 struct chip_pwr_save_fail_detected_params pwr_save_fail_params;
4572 tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(
4573 QDF_MODULE_ID_PE);
4574 if (wma == NULL) {
4575 WMA_LOGE("%s: wma_handle is NULL", __func__);
4576 return -EINVAL;
4577 }
4578 if (!mac) {
4579 WMA_LOGE("%s: Invalid mac context", __func__);
4580 return -EINVAL;
4581 }
4582 if (!mac->sme.chip_power_save_fail_cb) {
4583 WMA_LOGE("%s: Callback not registered", __func__);
4584 return -EINVAL;
4585 }
4586
4587 param_buf =
4588 (WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
4589 cmd_param_info;
4590 if (!param_buf) {
4591 WMA_LOGE("%s: Invalid pwr_save_fail_params breached event",
4592 __func__);
4593 return -EINVAL;
4594 }
4595 event = param_buf->fixed_param;
4596 pwr_save_fail_params.failure_reason_code =
4597 event->power_save_failure_reason_code;
4598 pwr_save_fail_params.wake_lock_bitmap[0] =
4599 event->protocol_wake_lock_bitmap[0];
4600 pwr_save_fail_params.wake_lock_bitmap[1] =
4601 event->protocol_wake_lock_bitmap[1];
4602 pwr_save_fail_params.wake_lock_bitmap[2] =
4603 event->protocol_wake_lock_bitmap[2];
4604 pwr_save_fail_params.wake_lock_bitmap[3] =
4605 event->protocol_wake_lock_bitmap[3];
4606 mac->sme.chip_power_save_fail_cb(mac->hHdd,
4607 &pwr_save_fail_params);
4608
4609 WMA_LOGD("%s: Invoke HDD pwr_save_fail callback", __func__);
4610 return 0;
4611}