blob: 6b26d0e829a4e82e3332766bc9d337ad7bd473f7 [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
Naveen Rawatfa2a1002018-05-17 16:06:37 -0700186uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
187 uint8_t nss, uint8_t *mcsRateFlag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800189 uint8_t index = 0;
Arif Hussainb8fef842016-07-19 09:43:13 -0700190 uint16_t match_rate = 0;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800191 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800193 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
194 __func__, maxRate, rate_flags, nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195
196 *mcsRateFlag = rate_flags;
Naveen Rawatea1564b2018-05-17 15:56:11 -0700197 *mcsRateFlag &= ~TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800198 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700199 if (rate_flags & TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800200 /* check for vht80 nss1/2 rate set */
201 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
202 vht_mcs_nss1[index].ht80_rate[0],
203 vht_mcs_nss1[index].ht80_rate[1],
204 vht_mcs_nss2[index].ht80_rate[0],
205 vht_mcs_nss2[index].ht80_rate[1]);
206 if (match_rate)
207 goto rate_found;
208 }
Naveen Rawatea1564b2018-05-17 15:56:11 -0700209 if ((rate_flags & TX_RATE_VHT40) |
210 (rate_flags & TX_RATE_VHT80)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800211 /* check for vht40 nss1/2 rate set */
212 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
213 vht_mcs_nss1[index].ht40_rate[0],
214 vht_mcs_nss1[index].ht40_rate[1],
215 vht_mcs_nss2[index].ht40_rate[0],
216 vht_mcs_nss2[index].ht40_rate[1]);
217 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700218 *mcsRateFlag &= ~TX_RATE_VHT80;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800219 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220 }
221 }
Naveen Rawatea1564b2018-05-17 15:56:11 -0700222 if ((rate_flags & TX_RATE_VHT20) |
223 (rate_flags & TX_RATE_VHT40) |
224 (rate_flags & TX_RATE_VHT80)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800225 /* check for vht20 nss1/2 rate set */
226 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
227 vht_mcs_nss1[index].ht20_rate[0],
228 vht_mcs_nss1[index].ht20_rate[1],
229 vht_mcs_nss2[index].ht20_rate[0],
230 vht_mcs_nss2[index].ht20_rate[1]);
231 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700232 *mcsRateFlag &= ~(TX_RATE_VHT80 |
233 TX_RATE_VHT40);
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800234 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235 }
236 }
237 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800238 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700239 if (rate_flags & TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800240 /* check for ht40 nss1/2 rate set */
241 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
242 mcs_nss1[index].ht40_rate[0],
243 mcs_nss1[index].ht40_rate[1],
244 mcs_nss2[index].ht40_rate[0],
245 mcs_nss2[index].ht40_rate[1]);
246 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700247 *mcsRateFlag = TX_RATE_HT40;
Yeshwanth Sriram Guntukad18c7a22018-02-02 15:22:30 +0530248 if (nss == 2)
249 index += MAX_HT_MCS_IDX;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800250 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251 }
252 }
Naveen Rawatea1564b2018-05-17 15:56:11 -0700253 if ((rate_flags & TX_RATE_HT20) ||
254 (rate_flags & TX_RATE_HT40)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800255 /* check for ht20 nss1/2 rate set */
256 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
257 mcs_nss1[index].ht20_rate[0],
258 mcs_nss1[index].ht20_rate[1],
259 mcs_nss2[index].ht20_rate[0],
260 mcs_nss2[index].ht20_rate[1]);
261 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700262 *mcsRateFlag = TX_RATE_HT20;
Yeshwanth Sriram Guntukad18c7a22018-02-02 15:22:30 +0530263 if (nss == 2)
264 index += MAX_HT_MCS_IDX;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800265 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 }
267 }
268 }
269
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800270rate_found:
271 /* set SGI flag only if this is SGI rate */
272 if (match_rate && is_sgi == true)
Naveen Rawatea1564b2018-05-17 15:56:11 -0700273 *mcsRateFlag |= TX_RATE_SGI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800274
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800275 WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
276 __func__, match_rate, index, *mcsRateFlag, is_sgi);
277
278 return match_rate ? index : INVALID_MCS_IDX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279}
280
Naveen Rawatfa2a1002018-05-17 16:06:37 -0700281#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800282/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530283 * wma_peek_vdev_req() - peek what request message is queued for response.
284 * the function does not delete the node after found
285 * @wma: WMA handle
286 * @vdev_id: vdev ID
287 * @type: request message type
288 *
289 * Return: the request message found
290 */
291static struct wma_target_req *wma_peek_vdev_req(tp_wma_handle wma,
292 uint8_t vdev_id, uint8_t type)
293{
294 struct wma_target_req *req_msg = NULL;
295 bool found = false;
296 qdf_list_node_t *node1 = NULL, *node2 = NULL;
297
298 qdf_spin_lock_bh(&wma->vdev_respq_lock);
299 if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&wma->vdev_resp_queue,
300 &node2)) {
301 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530302 return NULL;
303 }
304
305 do {
306 node1 = node2;
307 req_msg = qdf_container_of(node1, struct wma_target_req, node);
308 if (req_msg->vdev_id != vdev_id)
309 continue;
310 if (req_msg->type != type)
311 continue;
312
313 found = true;
314 break;
315 } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&wma->vdev_resp_queue,
316 node1, &node2));
317 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
318 if (!found) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800319 WMA_LOGE(FL("target request not found for vdev_id %d type %d"),
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530320 vdev_id, type);
321 return NULL;
322 }
323 WMA_LOGD(FL("target request found for vdev id: %d type %d msg %d"),
324 vdev_id, type, req_msg->msg_type);
325 return req_msg;
326}
Naveen Rawatfa2a1002018-05-17 16:06:37 -0700327#endif /* QCA_SUPPORT_CP_STATS */
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530328
329void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id,
330 int32_t rssi)
331{
332 struct sir_lost_link_info *lost_link_info;
333 QDF_STATUS qdf_status;
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800334 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530335
336 /* report lost link information only for STA mode */
Mukul Sharmaf9047232017-03-02 16:58:56 +0530337 if (wma_is_vdev_up(vdev_id) &&
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530338 (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) &&
339 (0 == wma->interfaces[vdev_id].sub_type)) {
340 lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
341 if (NULL == lost_link_info) {
342 WMA_LOGE("%s: failed to allocate memory", __func__);
343 return;
344 }
345 lost_link_info->vdev_id = vdev_id;
346 lost_link_info->rssi = rssi;
347 sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
348 sme_msg.bodyptr = lost_link_info;
349 sme_msg.bodyval = 0;
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800350 WMA_LOGD("%s: post msg to SME, bss_idx %d, rssi %d", __func__,
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530351 lost_link_info->vdev_id, lost_link_info->rssi);
352
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800353 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530354 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
355 WMA_LOGE("%s: fail to post msg to SME", __func__);
356 qdf_mem_free(lost_link_info);
357 }
358 }
359}
360
361/**
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700362 * host_map_smps_mode() - map fw smps mode to enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 * @fw_smps_mode: fw smps mode
364 *
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700365 * Return: return enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700367enum eSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700369 enum eSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 switch (fw_smps_mode) {
372 case WMI_SMPS_FORCED_MODE_STATIC:
373 smps_mode = STATIC_SMPS_MODE;
374 break;
375 case WMI_SMPS_FORCED_MODE_DYNAMIC:
376 smps_mode = DYNAMIC_SMPS_MODE;
377 break;
378 default:
379 smps_mode = SMPS_MODE_DISABLED;
380 }
381
382 return smps_mode;
383}
384
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800385/**
386 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
387 * mode commmand param
388 * @smps_mode: SMPS mode according to the protocol
389 *
390 * Return: int > 0 for success else failure
391 */
392int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
393{
394 int param = -EINVAL;
395
396 switch (smps_mode) {
397 case STATIC_SMPS_MODE:
398 param = WMI_SMPS_FORCED_MODE_STATIC;
399 break;
400 case DYNAMIC_SMPS_MODE:
401 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
402 break;
403 case SMPS_MODE_DISABLED:
404 param = WMI_SMPS_FORCED_MODE_DISABLED;
405 break;
406 default:
407 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
408 smps_mode);
409 }
410 return param;
411}
412
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413#ifdef WLAN_FEATURE_STATS_EXT
414/**
415 * wma_stats_ext_event_handler() - extended stats event handler
416 * @handle: wma handle
417 * @event_buf: event buffer received from fw
418 * @len: length of data
419 *
420 * Return: 0 for success or error code
421 */
422int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
423 uint32_t len)
424{
425 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
426 tSirStatsExtEvent *stats_ext_event;
427 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530428 QDF_STATUS status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -0700429 struct scheduler_msg cds_msg = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430 uint8_t *buf_ptr;
431 uint32_t alloc_len;
432
433 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
434
435 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
436 if (!param_buf) {
437 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
438 return -EINVAL;
439 }
440
441 stats_ext_info = param_buf->fixed_param;
442 buf_ptr = (uint8_t *) stats_ext_info;
443
444 alloc_len = sizeof(tSirStatsExtEvent);
445 alloc_len += stats_ext_info->data_len;
446
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700447 if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE -
Yeshwanth Sriram Guntukaf71b48e2018-04-20 15:18:08 +0530448 WMI_TLV_HDR_SIZE - sizeof(*stats_ext_info)) ||
449 stats_ext_info->data_len > param_buf->num_data) {
Abhinav Kumara03659c2017-12-28 15:18:07 +0530450 WMA_LOGE("Excess data_len:%d, num_data:%d",
451 stats_ext_info->data_len, param_buf->num_data);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700452 return -EINVAL;
453 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530454 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800455 if (NULL == stats_ext_event) {
456 WMA_LOGE("%s: Memory allocation failure", __func__);
457 return -ENOMEM;
458 }
459
460 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
461
462 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
463 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530464 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465 buf_ptr, stats_ext_event->event_data_len);
466
467 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
468 cds_msg.bodyptr = (void *)stats_ext_event;
469 cds_msg.bodyval = 0;
470
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800471 status = scheduler_post_msg(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530472 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530474 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 return -EFAULT;
476 }
477
478 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
479 return 0;
480}
481#endif /* WLAN_FEATURE_STATS_EXT */
482
Nirav Shah93e789e2016-04-14 19:47:43 +0530483
Govind Singha471e5e2015-10-12 17:11:14 +0530484/**
485 * wma_profile_data_report_event_handler() - fw profiling handler
486 * @handle: wma handle
487 * @event_buf: event buffer received from fw
488 * @len: length of data
489 *
490 * Return: 0 for success or error code
491 */
492int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
493 uint32_t len)
494{
495 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
496 wmi_wlan_profile_ctx_t *profile_ctx;
497 wmi_wlan_profile_t *profile_data;
498 uint32_t i = 0;
499 uint32_t entries;
500 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530501 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530502
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700503 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
Govind Singha471e5e2015-10-12 17:11:14 +0530504 if (!param_buf) {
505 WMA_LOGE("%s: Invalid profile data event buf", __func__);
506 return -EINVAL;
507 }
508 profile_ctx = param_buf->profile_ctx;
509 buf_ptr = (uint8_t *)profile_ctx;
510 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
511 profile_data = (wmi_wlan_profile_t *) buf_ptr;
512 entries = profile_ctx->bin_count;
Amar Singhal4bd22232017-10-04 13:24:00 -0700513
514 if (entries > param_buf->num_profile_data) {
515 WMA_LOGE("FW bin count %d more than data %d in TLV hdr",
516 entries,
517 param_buf->num_profile_data);
518 return -EINVAL;
519 }
520
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530521 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530522 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530523 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530524 "TOT: %d\n"
525 "tx_msdu_cnt: %d\n"
526 "tx_mpdu_cnt: %d\n"
527 "tx_ppdu_cnt: %d\n"
528 "rx_msdu_cnt: %d\n"
529 "rx_mpdu_cnt: %d\n"
530 "bin_count: %d\n",
531 profile_ctx->tot,
532 profile_ctx->tx_msdu_cnt,
533 profile_ctx->tx_mpdu_cnt,
534 profile_ctx->tx_ppdu_cnt,
535 profile_ctx->rx_msdu_cnt,
536 profile_ctx->rx_mpdu_cnt,
537 profile_ctx->bin_count);
538
Nirav Shah93e789e2016-04-14 19:47:43 +0530539 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
540 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
541
Govind Singha471e5e2015-10-12 17:11:14 +0530542 for (i = 0; i < entries; i++) {
543 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
544 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530545 snprintf(temp_str, sizeof(temp_str),
546 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530547 profile_data[i].id,
548 profile_data[i].cnt,
549 profile_data[i].tot,
550 profile_data[i].min,
551 profile_data[i].max,
552 profile_data[i].hist_intvl,
553 profile_data[i].hist[0],
554 profile_data[i].hist[1],
555 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530556 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
557 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530558 }
559
560 return 0;
561}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562
563#ifdef WLAN_FEATURE_LINK_LAYER_STATS
564
Zhang Qian73c348a2017-03-13 16:15:55 +0800565#define WMA_FILL_TX_STATS(eve, msg) do {\
566 (msg)->msdus = (eve)->tx_msdu_cnt;\
567 (msg)->mpdus = (eve)->tx_mpdu_cnt;\
568 (msg)->ppdus = (eve)->tx_ppdu_cnt;\
569 (msg)->bytes = (eve)->tx_bytes;\
570 (msg)->drops = (eve)->tx_msdu_drop_cnt;\
571 (msg)->drop_bytes = (eve)->tx_drop_bytes;\
572 (msg)->retries = (eve)->tx_mpdu_retry_cnt;\
573 (msg)->failed = (eve)->tx_mpdu_fail_cnt;\
574} while (0)
575
576#define WMA_FILL_RX_STATS(eve, msg) do {\
577 (msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
578 (msg)->bytes = (eve)->mac_rx_bytes;\
579 (msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
580 (msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
581 (msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
582 (msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
583 (msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
584} while (0)
585
586/**
587 * wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
588 * @len: buffer length output
589 * @peer_num: peer number
590 * @fixed_param: fixed parameters in WMI event
591 *
592 * Structure of the stats message
593 * LL_EXT_STATS
594 * |
595 * |--Channel stats[1~n]
596 * |--Peer[1~n]
597 * |
598 * +---Signal
599 * +---TX
600 * | +---BE
601 * | +---BK
602 * | +---VI
603 * | +---VO
604 * |
605 * +---RX
606 * +---BE
607 * +---BK
608 * +---VI
609 * +---VO
610 * For each Access Category, the arregation and mcs
611 * stats are as this:
612 * TX
613 * +-BE/BK/VI/VO
614 * +----tx_mpdu_aggr_array
615 * +----tx_succ_mcs_array
616 * +----tx_fail_mcs_array
617 * +----tx_delay_array
618 * RX
619 * +-BE/BK/VI/VO
620 * +----rx_mpdu_aggr_array
621 * +----rx_mcs_array
622 *
623 * return: Address for result buffer.
624 */
625static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
626 uint32_t peer_num,
627 wmi_report_stats_event_fixed_param *fixed_param)
628{
629 tSirLLStatsResults *buf;
630 uint32_t buf_len;
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530631 uint32_t total_array_len, total_peer_len;
632 bool excess_data = false;
Zhang Qian73c348a2017-03-13 16:15:55 +0800633
634 if (!len || !fixed_param) {
635 WMA_LOGE(FL("Invalid input parameters."));
636 return NULL;
637 }
638
639 /*
640 * Result buffer has a structure like this:
641 * ---------------------------------
642 * | trigger_cond_i |
643 * +-------------------------------+
644 * | cca_chgd_bitmap |
645 * +-------------------------------+
646 * | sig_chgd_bitmap |
647 * +-------------------------------+
648 * | tx_chgd_bitmap |
649 * +-------------------------------+
650 * | rx_chgd_bitmap |
651 * +-------------------------------+
652 * | peer_num |
653 * +-------------------------------+
654 * | channel_num |
655 * +-------------------------------+
656 * | tx_mpdu_aggr_array_len |
657 * +-------------------------------+
658 * | tx_succ_mcs_array_len |
659 * +-------------------------------+
660 * | tx_fail_mcs_array_len |
661 * +-------------------------------+
662 * | tx_delay_array_len |
663 * +-------------------------------+
664 * | rx_mpdu_aggr_array_len |
665 * +-------------------------------+
666 * | rx_mcs_array_len |
667 * +-------------------------------+
668 * | pointer to CCA stats |
669 * +-------------------------------+
670 * | CCA stats |
671 * +-------------------------------+
672 * | peer_stats |----+
673 * +-------------------------------+ |
674 * | TX aggr/mcs parameters array | |
675 * | Length of this buffer is | |
676 * | not fixed. |<-+ |
677 * +-------------------------------+ | |
678 * | per peer tx stats |--+ |
679 * | BE | <--+
680 * | BK | |
681 * | VI | |
682 * | VO | |
683 * +-------------------------------+ |
684 * | TX aggr/mcs parameters array | |
685 * | Length of this buffer is | |
686 * | not fixed. |<-+ |
687 * +-------------------------------+ | |
688 * | peer peer rx stats |--+ |
689 * | BE | <--+
690 * | BK |
691 * | VI |
692 * | VO |
693 * ---------------------------------
694 */
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530695
Zhang Qian73c348a2017-03-13 16:15:55 +0800696 buf_len = sizeof(tSirLLStatsResults) +
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530697 sizeof(struct sir_wifi_ll_ext_stats);
698 do {
699 if (fixed_param->num_chan_cca_stats > (WMI_SVC_MSG_MAX_SIZE /
700 sizeof(struct sir_wifi_chan_cca_stats))) {
701 excess_data = true;
702 break;
703 }
704 buf_len += (fixed_param->num_chan_cca_stats *
705 sizeof(struct sir_wifi_chan_cca_stats));
706 if (fixed_param->tx_mpdu_aggr_array_len >
707 WMI_SVC_MSG_MAX_SIZE) {
708 excess_data = true;
709 break;
710 } else {
711 total_array_len = fixed_param->tx_mpdu_aggr_array_len;
712 }
713 if (fixed_param->tx_succ_mcs_array_len >
714 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
715 excess_data = true;
716 break;
717 } else {
718 total_array_len += fixed_param->tx_succ_mcs_array_len;
719 }
720 if (fixed_param->tx_fail_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_fail_mcs_array_len;
726 }
727 if (fixed_param->tx_ppdu_delay_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_ppdu_delay_array_len;
733 }
734 if (fixed_param->rx_mpdu_aggr_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->rx_mpdu_aggr_array_len;
740 }
741 if (fixed_param->rx_mcs_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_mcs_array_len;
747 }
748
749 if (total_array_len > (WMI_SVC_MSG_MAX_SIZE /
750 (sizeof(uint32_t) * WLAN_MAX_AC))) {
751 excess_data = true;
752 break;
753 } else {
754 total_peer_len = (sizeof(uint32_t) * WLAN_MAX_AC *
755 total_array_len) +
756 (WLAN_MAX_AC *
757 (sizeof(struct sir_wifi_tx) +
758 sizeof(struct sir_wifi_rx)));
759 }
Vignesh Viswanathanca67e362017-10-04 23:42:00 +0530760 if (total_peer_len > WMI_SVC_MSG_MAX_SIZE) {
761 excess_data = true;
762 break;
763 }
Vignesh Viswanathanbd1ad032017-11-15 15:13:56 +0530764 if (peer_num > WMI_SVC_MSG_MAX_SIZE / (total_peer_len +
765 sizeof(struct sir_wifi_ll_ext_peer_stats))) {
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530766 excess_data = true;
767 break;
768 } else {
769 buf_len += peer_num *
770 (sizeof(struct sir_wifi_ll_ext_peer_stats) +
771 total_peer_len);
772 }
773 } while (0);
774
775 if (excess_data || (buf_len > WMI_SVC_MSG_MAX_SIZE)) {
776 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",
777 __func__, peer_num, fixed_param->num_chan_cca_stats,
778 fixed_param->tx_mpdu_aggr_array_len,
779 fixed_param->tx_succ_mcs_array_len,
780 fixed_param->tx_fail_mcs_array_len,
781 fixed_param->tx_ppdu_delay_array_len,
782 fixed_param->rx_mpdu_aggr_array_len,
783 fixed_param->rx_mcs_array_len);
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530784 return NULL;
785 }
Zhang Qian73c348a2017-03-13 16:15:55 +0800786
787 buf = (tSirLLStatsResults *)qdf_mem_malloc(buf_len);
788 if (buf == NULL) {
789 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
790 buf_len = 0;
791 return NULL;
792 }
793
794 *len = buf_len;
795 return buf;
796}
797
798/**
799 * wma_fill_tx_stats() - Fix TX stats into result buffer
800 * @ll_stats: LL stats buffer
801 * @fix_param: parameters with fixed length in WMI event
802 * @param_buf: parameters without fixed length in WMI event
803 * @buf: buffer for TLV parameters
804 *
805 * Return: None
806 */
807static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
808 wmi_report_stats_event_fixed_param *fix_param,
809 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
810 uint8_t **buf, uint32_t *buf_length)
811{
812 uint8_t *result;
813 uint32_t i, j, k;
814 wmi_peer_ac_tx_stats *wmi_peer_tx;
815 wmi_tx_stats *wmi_tx;
816 struct sir_wifi_tx *tx_stats;
817 struct sir_wifi_ll_ext_peer_stats *peer_stats;
818 uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
819 uint32_t len, dst_len, tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
820 tx_fail_mcs_array_len, tx_delay_array_len;
821
822 result = *buf;
823 dst_len = *buf_length;
824 tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
825 ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
826 tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
827 ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
828 tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
829 ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
830 tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
831 ll_stats->tx_delay_array_len = tx_delay_array_len;
832 wmi_peer_tx = param_buf->peer_ac_tx_stats;
833 wmi_tx = param_buf->tx_stats;
834
835 len = fix_param->num_peer_ac_tx_stats *
836 WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
837 if (len <= dst_len) {
838 tx_mpdu_aggr = (uint32_t *)result;
839 qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
840 result += len;
841 dst_len -= len;
842 } else {
843 WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong."));
844 tx_mpdu_aggr = NULL;
845 }
846
847 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
848 tx_succ_mcs_array_len * sizeof(uint32_t);
849 if (len <= dst_len) {
850 tx_succ_mcs = (uint32_t *)result;
851 qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
852 result += len;
853 dst_len -= len;
854 } else {
855 WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong."));
856 tx_succ_mcs = NULL;
857 }
858
859 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
860 tx_fail_mcs_array_len * sizeof(uint32_t);
861 if (len <= dst_len) {
862 tx_fail_mcs = (uint32_t *)result;
863 qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
864 result += len;
865 dst_len -= len;
866 } else {
867 WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong."));
868 tx_fail_mcs = NULL;
869 }
870
871 len = fix_param->num_peer_ac_tx_stats *
872 WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
873 if (len <= dst_len) {
874 tx_delay = (uint32_t *)result;
875 qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
876 result += len;
877 dst_len -= len;
878 } else {
879 WMA_LOGE(FL("TX_DELAY buffer length is wrong."));
880 tx_delay = NULL;
881 }
882
883 /* per peer tx stats */
884 peer_stats = ll_stats->peer_stats;
885
886 for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
887 uint32_t peer_id = wmi_peer_tx[i].peer_id;
888 struct sir_wifi_tx *ac;
889 wmi_tx_stats *wmi_tx_stats;
890
891 for (j = 0; j < ll_stats->peer_num; j++) {
892 peer_stats += j;
893 if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
894 peer_stats->peer_id == peer_id)
895 break;
896 }
897
898 if (j < ll_stats->peer_num) {
899 peer_stats->peer_id = wmi_peer_tx[i].peer_id;
900 peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
901 tx_stats = (struct sir_wifi_tx *)result;
902 for (k = 0; k < WLAN_MAX_AC; k++) {
903 wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
904 ac = &tx_stats[k];
905 WMA_FILL_TX_STATS(wmi_tx_stats, ac);
906 ac->mpdu_aggr_size = tx_mpdu_aggr;
907 ac->aggr_len = tx_mpdu_aggr_array_len *
908 sizeof(uint32_t);
909 ac->success_mcs_len = tx_succ_mcs_array_len *
910 sizeof(uint32_t);
911 ac->success_mcs = tx_succ_mcs;
912 ac->fail_mcs = tx_fail_mcs;
913 ac->fail_mcs_len = tx_fail_mcs_array_len *
914 sizeof(uint32_t);
915 ac->delay = tx_delay;
916 ac->delay_len = tx_delay_array_len *
917 sizeof(uint32_t);
918 peer_stats->ac_stats[k].tx_stats = ac;
919 peer_stats->ac_stats[k].type = k;
920 tx_mpdu_aggr += tx_mpdu_aggr_array_len;
921 tx_succ_mcs += tx_succ_mcs_array_len;
922 tx_fail_mcs += tx_fail_mcs_array_len;
923 tx_delay += tx_delay_array_len;
924 }
925 result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
926 } else {
927 /*
928 * Buffer for Peer TX counter overflow.
929 * There is peer ID mismatch between TX, RX,
930 * signal counters.
931 */
932 WMA_LOGE(FL("One peer TX info is dropped."));
933
934 tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
935 tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
936 tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
937 tx_delay += tx_delay_array_len * WLAN_MAX_AC;
938 }
939 }
940 *buf = result;
941 *buf_length = dst_len;
942}
943
944/**
945 * wma_fill_rx_stats() - Fix RX stats into result buffer
946 * @ll_stats: LL stats buffer
947 * @fix_param: parameters with fixed length in WMI event
948 * @param_buf: parameters without fixed length in WMI event
949 * @buf: buffer for TLV parameters
950 *
951 * Return: None
952 */
953static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
954 wmi_report_stats_event_fixed_param *fix_param,
955 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
956 uint8_t **buf, uint32_t *buf_length)
957{
958 uint8_t *result;
959 uint32_t i, j, k;
960 uint32_t *rx_mpdu_aggr, *rx_mcs;
961 wmi_rx_stats *wmi_rx;
962 wmi_peer_ac_rx_stats *wmi_peer_rx;
963 struct sir_wifi_rx *rx_stats;
964 struct sir_wifi_ll_ext_peer_stats *peer_stats;
965 uint32_t len, dst_len, rx_mpdu_aggr_array_len, rx_mcs_array_len;
966
967 rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
968 ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
969 rx_mcs_array_len = fix_param->rx_mcs_array_len;
970 ll_stats->rx_mcs_array_len = rx_mcs_array_len;
971 wmi_peer_rx = param_buf->peer_ac_rx_stats;
972 wmi_rx = param_buf->rx_stats;
973
974 result = *buf;
975 dst_len = *buf_length;
976 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
977 WLAN_MAX_AC * rx_mpdu_aggr_array_len);
978 if (len <= dst_len) {
979 rx_mpdu_aggr = (uint32_t *)result;
980 qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
981 result += len;
982 dst_len -= len;
983 } else {
984 WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong."));
985 rx_mpdu_aggr = NULL;
986 }
987
988 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
989 WLAN_MAX_AC * rx_mcs_array_len);
990 if (len <= dst_len) {
991 rx_mcs = (uint32_t *)result;
992 qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len);
993 result += len;
994 dst_len -= len;
995 } else {
996 WMA_LOGE(FL("RX_MCS array length is wrong."));
997 rx_mcs = NULL;
998 }
999
1000 /* per peer rx stats */
1001 peer_stats = ll_stats->peer_stats;
1002 for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) {
1003 uint32_t peer_id = wmi_peer_rx[i].peer_id;
1004 struct sir_wifi_rx *ac;
1005 wmi_rx_stats *wmi_rx_stats;
1006
1007 for (j = 0; j < ll_stats->peer_num; j++) {
1008 peer_stats += j;
1009 if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
1010 (peer_stats->peer_id == peer_id))
1011 break;
1012 }
1013
1014 if (j < ll_stats->peer_num) {
1015 peer_stats->peer_id = wmi_peer_rx[i].peer_id;
1016 peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
1017 peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
1018 peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
1019 peer_stats->rx_probe_reqs =
1020 wmi_peer_rx[i].rx_probe_reqs;
1021 peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
1022 rx_stats = (struct sir_wifi_rx *)result;
1023
1024 for (k = 0; k < WLAN_MAX_AC; k++) {
1025 wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
1026 ac = &rx_stats[k];
1027 WMA_FILL_RX_STATS(wmi_rx_stats, ac);
1028 ac->mpdu_aggr = rx_mpdu_aggr;
1029 ac->aggr_len = rx_mpdu_aggr_array_len *
1030 sizeof(uint32_t);
1031 ac->mcs = rx_mcs;
1032 ac->mcs_len = rx_mcs_array_len *
1033 sizeof(uint32_t);
1034 peer_stats->ac_stats[k].rx_stats = ac;
1035 peer_stats->ac_stats[k].type = k;
1036 rx_mpdu_aggr += rx_mpdu_aggr_array_len;
1037 rx_mcs += rx_mcs_array_len;
1038 }
1039 result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
1040 } else {
1041 /*
1042 * Buffer for Peer RX counter overflow.
1043 * There is peer ID mismatch between TX, RX,
1044 * signal counters.
1045 */
1046 WMA_LOGE(FL("One peer RX info is dropped."));
1047 rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
1048 rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
1049 }
1050 }
1051 *buf = result;
1052 *buf_length = dst_len;
1053}
1054
1055/**
1056 * wma_ll_stats_evt_handler() - handler for MAC layer counters.
1057 * @handle - wma handle
1058 * @event - FW event
1059 * @len - length of FW event
1060 *
1061 * return: 0 success.
1062 */
1063static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
1064 u_int32_t len)
1065{
1066 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
1067 wmi_report_stats_event_fixed_param *fixed_param;
1068 tSirLLStatsResults *link_stats_results;
1069 wmi_chan_cca_stats *wmi_cca_stats;
1070 wmi_peer_signal_stats *wmi_peer_signal;
1071 wmi_peer_ac_rx_stats *wmi_peer_rx;
1072 struct sir_wifi_ll_ext_stats *ll_stats;
1073 struct sir_wifi_ll_ext_peer_stats *peer_stats;
1074 struct sir_wifi_chan_cca_stats *cca_stats;
1075 struct sir_wifi_peer_signal_stats *peer_signal;
1076 uint8_t *result;
1077 uint32_t i, peer_num, result_size, dst_len;
1078 tpAniSirGlobal mac;
1079 struct scheduler_msg sme_msg = { 0 };
1080 QDF_STATUS qdf_status;
1081
1082 mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
1083 if (!mac) {
1084 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1085 return -EINVAL;
1086 }
1087
1088 if (!mac->sme.link_layer_stats_ext_cb) {
1089 WMA_LOGD("%s: HDD callback is null", __func__);
1090 return -EINVAL;
1091 }
1092
1093 WMA_LOGD("%s: Posting MAC counters event to HDD", __func__);
1094
1095 param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
1096 fixed_param = param_buf->fixed_param;
1097 wmi_cca_stats = param_buf->chan_cca_stats;
1098 wmi_peer_signal = param_buf->peer_signal_stats;
1099 wmi_peer_rx = param_buf->peer_ac_rx_stats;
Abhinav Kumara03659c2017-12-28 15:18:07 +05301100 if (fixed_param->num_peer_signal_stats >
1101 param_buf->num_peer_signal_stats ||
1102 fixed_param->num_peer_ac_tx_stats >
1103 param_buf->num_peer_ac_tx_stats ||
1104 fixed_param->num_peer_ac_rx_stats >
1105 param_buf->num_peer_ac_rx_stats) {
1106 WMA_LOGE("%s: excess num_peer_signal_stats:%d, num_peer_ac_tx_stats:%d, num_peer_ac_rx_stats:%d",
1107 __func__, fixed_param->num_peer_signal_stats,
1108 fixed_param->num_peer_ac_tx_stats,
1109 fixed_param->num_peer_ac_rx_stats);
1110 return -EINVAL;
1111 }
Zhang Qian73c348a2017-03-13 16:15:55 +08001112
1113 /* Get the MAX of three peer numbers */
1114 peer_num = fixed_param->num_peer_signal_stats >
1115 fixed_param->num_peer_ac_tx_stats ?
1116 fixed_param->num_peer_signal_stats :
1117 fixed_param->num_peer_ac_tx_stats;
1118 peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
1119 peer_num : fixed_param->num_peer_ac_rx_stats;
1120
1121 if (peer_num == 0)
1122 return -EINVAL;
1123
1124 link_stats_results = wma_get_ll_stats_ext_buf(&result_size,
1125 peer_num,
1126 fixed_param);
1127 if (!link_stats_results) {
1128 WMA_LOGE("%s: Fail to allocate stats buffer", __func__);
1129 return -EINVAL;
1130 }
1131 link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
1132 link_stats_results->num_peers = peer_num;
1133 link_stats_results->peer_event_number = 1;
1134 link_stats_results->moreResultToFollow = 0;
1135
1136 ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
1137 ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
1138 ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
1139 ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
1140 ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
1141 ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
1142 ll_stats->channel_num = fixed_param->num_chan_cca_stats;
1143 ll_stats->peer_num = peer_num;
1144
1145 result = (uint8_t *)ll_stats->stats;
1146 peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
1147 ll_stats->peer_stats = peer_stats;
1148
1149 for (i = 0; i < peer_num; i++) {
1150 peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
1151 peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
1152 }
1153
1154 /* Per peer signal */
1155 result_size -= sizeof(struct sir_wifi_ll_ext_stats);
1156 dst_len = sizeof(struct sir_wifi_peer_signal_stats);
1157 for (i = 0; i < fixed_param->num_peer_signal_stats; i++) {
1158 peer_stats[i].peer_id = wmi_peer_signal->peer_id;
1159 peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
1160 peer_signal = &peer_stats[i].peer_signal_stats;
1161
Zhang Qian303ebe92017-05-18 13:59:07 +08001162 WMA_LOGD("%d antennas for peer %d",
1163 wmi_peer_signal->num_chains_valid,
1164 wmi_peer_signal->peer_id);
Zhang Qian73c348a2017-03-13 16:15:55 +08001165 if (dst_len <= result_size) {
Zhang Qian303ebe92017-05-18 13:59:07 +08001166 peer_signal->vdev_id = wmi_peer_signal->vdev_id;
1167 peer_signal->peer_id = wmi_peer_signal->peer_id;
1168 peer_signal->num_chain =
1169 wmi_peer_signal->num_chains_valid;
1170 qdf_mem_copy(peer_signal->per_ant_snr,
1171 wmi_peer_signal->per_chain_snr,
1172 sizeof(peer_signal->per_ant_snr));
1173 qdf_mem_copy(peer_signal->nf,
1174 wmi_peer_signal->per_chain_nf,
1175 sizeof(peer_signal->nf));
1176 qdf_mem_copy(peer_signal->per_ant_rx_mpdus,
1177 wmi_peer_signal->per_antenna_rx_mpdus,
1178 sizeof(peer_signal->per_ant_rx_mpdus));
1179 qdf_mem_copy(peer_signal->per_ant_tx_mpdus,
1180 wmi_peer_signal->per_antenna_tx_mpdus,
1181 sizeof(peer_signal->per_ant_tx_mpdus));
Zhang Qian73c348a2017-03-13 16:15:55 +08001182 result_size -= dst_len;
1183 } else {
1184 WMA_LOGE(FL("Invalid length of PEER signal."));
1185 }
1186 wmi_peer_signal++;
1187 }
1188
1189 result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
1190 cca_stats = (struct sir_wifi_chan_cca_stats *)result;
1191 ll_stats->cca = cca_stats;
1192 dst_len = sizeof(struct sir_wifi_chan_cca_stats);
1193 for (i = 0; i < ll_stats->channel_num; i++) {
1194 if (dst_len <= result_size) {
1195 qdf_mem_copy(&cca_stats[i], &wmi_cca_stats->vdev_id,
1196 dst_len);
1197 result_size -= dst_len;
1198 } else {
1199 WMA_LOGE(FL("Invalid length of CCA."));
1200 }
1201 }
1202
1203 result += i * sizeof(struct sir_wifi_chan_cca_stats);
1204 wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
1205 &result, &result_size);
1206 wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
1207 &result, &result_size);
1208 sme_msg.type = eWMI_SME_LL_STATS_IND;
1209 sme_msg.bodyptr = (void *)link_stats_results;
1210 sme_msg.bodyval = 0;
1211 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1212 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1213 WMA_LOGP(FL("Failed to post peer stat change msg!"));
1214 qdf_mem_free(link_stats_results);
1215 return -EINVAL;
1216 }
1217
1218 return 0;
1219}
1220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221/**
1222 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
1223 * @handle: wma handle
1224 * @cmd_param_info: data received with event from fw
1225 * @len: length of data
1226 *
1227 * Return: 0 for success or error code
1228 */
1229static int wma_unified_link_peer_stats_event_handler(void *handle,
1230 uint8_t *cmd_param_info,
1231 uint32_t len)
1232{
1233 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1234 wmi_peer_stats_event_fixed_param *fixed_param;
1235 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
1236 wmi_rate_stats *rate_stats;
1237 tSirLLStatsResults *link_stats_results;
1238 uint8_t *results, *t_peer_stats, *t_rate_stats;
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301239 uint32_t count, rate_cnt;
1240 uint32_t total_num_rates = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001241 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
1242 size_t peer_info_size, peer_stats_size, rate_stats_size;
1243 size_t link_stats_results_size;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001244 bool excess_data = false;
jitiphil06b539a2018-06-07 16:31:48 +05301245 uint32_t buf_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246
Anurag Chouhan6d760662016-02-20 16:05:43 +05301247 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248
1249 if (!pMac) {
1250 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1251 return -EINVAL;
1252 }
1253
1254 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1255 WMA_LOGD("%s: HDD callback is null", __func__);
1256 return -EINVAL;
1257 }
1258
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1260 if (!param_tlvs) {
1261 WMA_LOGA("%s: Invalid stats event", __func__);
1262 return -EINVAL;
1263 }
1264 /*
1265 * cmd_param_info contains
1266 * wmi_peer_stats_event_fixed_param fixed_param;
1267 * num_peers * size of(struct wmi_peer_link_stats)
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301268 * total_num_rates * size of(struct wmi_rate_stats)
1269 * total_num_rates is the sum of the rates of all the peers.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001270 */
1271 fixed_param = param_tlvs->fixed_param;
1272 peer_stats = param_tlvs->peer_stats;
1273 rate_stats = param_tlvs->peer_rate_stats;
1274
1275 if (!fixed_param || !peer_stats ||
1276 (peer_stats->num_rates && !rate_stats)) {
1277 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
1278 return -EINVAL;
1279 }
1280
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001281 do {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001282 if (fixed_param->num_peers >
Abhinav Kumara03659c2017-12-28 15:18:07 +05301283 WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats) ||
1284 fixed_param->num_peers > param_tlvs->num_peer_stats) {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001285 excess_data = true;
1286 break;
1287 } else {
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301288 buf_len = fixed_param->num_peers *
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001289 sizeof(wmi_peer_link_stats);
1290 }
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301291 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
1292 for (count = 0; count < fixed_param->num_peers; count++) {
1293 if (temp_peer_stats->num_rates >
1294 WMI_SVC_MSG_MAX_SIZE / sizeof(wmi_rate_stats)) {
1295 excess_data = true;
1296 break;
1297 } else {
1298 total_num_rates += temp_peer_stats->num_rates;
1299 if (total_num_rates >
1300 WMI_SVC_MSG_MAX_SIZE /
Abhinav Kumara03659c2017-12-28 15:18:07 +05301301 sizeof(wmi_rate_stats) || total_num_rates >
1302 param_tlvs->num_peer_rate_stats) {
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301303 excess_data = true;
1304 break;
1305 }
1306 buf_len += temp_peer_stats->num_rates *
1307 sizeof(wmi_rate_stats);
1308 }
1309 temp_peer_stats++;
1310 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001311 } while (0);
1312
1313 if (excess_data ||
jitiphil9fa0e8e2018-05-25 17:40:41 +05301314 (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_param))) {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001315 WMA_LOGE("excess wmi buffer: rates:%d, peers:%d",
1316 peer_stats->num_rates, fixed_param->num_peers);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001317 return -EINVAL;
1318 }
1319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001320 peer_stats_size = sizeof(tSirWifiPeerStat);
1321 peer_info_size = sizeof(tSirWifiPeerInfo);
1322 rate_stats_size = sizeof(tSirWifiRateStat);
1323 link_stats_results_size =
1324 sizeof(*link_stats_results) + peer_stats_size +
1325 (fixed_param->num_peers * peer_info_size) +
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301326 (total_num_rates * rate_stats_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301328 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329 if (NULL == link_stats_results) {
1330 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1331 __func__, link_stats_results_size);
1332 return -ENOMEM;
1333 }
1334
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301335 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336
1337 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
1338 link_stats_results->rspId = fixed_param->request_id;
1339 link_stats_results->ifaceId = 0;
1340 link_stats_results->num_peers = fixed_param->num_peers;
1341 link_stats_results->peer_event_number = fixed_param->peer_event_number;
1342 link_stats_results->moreResultToFollow = fixed_param->more_data;
1343
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301344 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001345 &fixed_param->num_peers, peer_stats_size);
1346
1347 results = (uint8_t *) link_stats_results->results;
1348 t_peer_stats = (uint8_t *) peer_stats;
1349 t_rate_stats = (uint8_t *) rate_stats;
1350 next_res_offset = peer_stats_size;
1351 next_peer_offset = WMI_TLV_HDR_SIZE;
1352 next_rate_offset = WMI_TLV_HDR_SIZE;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301353 for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301354 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355 t_peer_stats + next_peer_offset, peer_info_size);
1356 next_res_offset += peer_info_size;
1357
1358 /* Copy rate stats associated with this peer */
1359 for (count = 0; count < peer_stats->num_rates; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360 rate_stats++;
1361
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301362 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 t_rate_stats + next_rate_offset,
1364 rate_stats_size);
1365 next_res_offset += rate_stats_size;
1366 next_rate_offset += sizeof(*rate_stats);
1367 }
1368 next_peer_offset += sizeof(*peer_stats);
1369 peer_stats++;
1370 }
1371
1372 /* call hdd callback with Link Layer Statistics
1373 * vdev_id/ifacId in link_stats_results will be
1374 * used to retrieve the correct HDD context
1375 */
1376 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1377 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1378 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301379 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380
1381 return 0;
1382}
1383
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001384/**
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001385 * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
1386 * @handle: WMI handle
1387 *
1388 * Return: 0 on success, error number otherwise.
1389 */
yeshwanth sriram guntuka584c2332017-07-29 12:50:25 +05301390int wma_unified_radio_tx_mem_free(void *handle)
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001391{
1392 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1393 tSirWifiRadioStat *rs_results;
1394 uint32_t i = 0;
1395
1396 if (!wma_handle->link_stats_results)
1397 return 0;
1398
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001399 rs_results = (tSirWifiRadioStat *)
1400 &wma_handle->link_stats_results->results[0];
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001401 for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
1402 rs_results += i;
1403 if (rs_results->tx_time_per_power_level) {
1404 qdf_mem_free(rs_results->tx_time_per_power_level);
1405 rs_results->tx_time_per_power_level = NULL;
1406 }
1407
1408 if (rs_results->channels) {
1409 qdf_mem_free(rs_results->channels);
1410 rs_results->channels = NULL;
1411 }
1412 }
1413
1414 qdf_mem_free(wma_handle->link_stats_results);
1415 wma_handle->link_stats_results = NULL;
1416
1417 return 0;
1418}
1419
1420/**
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001421 * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
1422 * @handle: WMI handle
1423 * @cmd_param_info: command param info
1424 * @len: Length of @cmd_param_info
1425 *
1426 * This is the WMI event handler function to receive radio stats tx
1427 * power level stats.
1428 *
1429 * Return: 0 on success, error number otherwise.
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001430 */
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001431static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
1432 u_int8_t *cmd_param_info, u_int32_t len)
1433{
1434 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1435 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
1436 wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
1437 uint8_t *tx_power_level_values;
1438 tSirLLStatsResults *link_stats_results;
1439 tSirWifiRadioStat *rs_results;
Vignesh Viswanathan59f0fad2018-01-25 17:04:46 +05301440 uint32_t max_total_num_tx_power_levels = MAX_TPC_LEVELS * NUM_OF_BANDS *
1441 MAX_SPATIAL_STREAM_ANY_V3;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001442
1443 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1444
1445 if (!mac) {
1446 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1447 return -EINVAL;
1448 }
1449
1450 if (!mac->sme.pLinkLayerStatsIndCallback) {
1451 WMA_LOGD("%s: HDD callback is null", __func__);
1452 return -EINVAL;
1453 }
1454
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001455 param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)
1456 cmd_param_info;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001457 if (!param_tlvs) {
1458 WMA_LOGA("%s: Invalid tx power level stats event", __func__);
1459 return -EINVAL;
1460 }
1461
1462 fixed_param = param_tlvs->fixed_param;
1463 if (!fixed_param) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001464 WMA_LOGA("%s:Invalid param_tlvs for Radio tx_power level Stats",
1465 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001466 return -EINVAL;
1467 }
1468
1469 link_stats_results = wma_handle->link_stats_results;
Srinivas Girigowda52cbce42016-10-25 14:11:58 -07001470 if (!link_stats_results) {
1471 WMA_LOGA("%s: link_stats_results is NULL", __func__);
1472 return -EINVAL;
1473 }
1474
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001475 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 -07001476 __func__, fixed_param->total_num_tx_power_levels,
1477 fixed_param->num_tx_power_levels,
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001478 fixed_param->power_level_offset,
1479 fixed_param->radio_id);
1480
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001481 if (fixed_param->num_tx_power_levels > ((WMI_SVC_MSG_MAX_SIZE -
Abhinav Kumara03659c2017-12-28 15:18:07 +05301482 sizeof(*fixed_param)) / sizeof(uint32_t)) ||
1483 fixed_param->num_tx_power_levels >
1484 param_tlvs->num_tx_time_per_power_level) {
1485 WMA_LOGE("%s: excess tx_power buffers:%d, num_tx_time_per_power_level:%d",
1486 __func__, fixed_param->num_tx_power_levels,
1487 param_tlvs->num_tx_time_per_power_level);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001488 return -EINVAL;
1489 }
Vignesh Viswanathanad7eded2017-11-28 16:58:24 +05301490
Vignesh Viswanathan01e1adb2018-03-23 20:22:38 +05301491 if (fixed_param->radio_id >= link_stats_results->num_radio) {
1492 WMA_LOGE("%s: Invalid radio_id %d num_radio %d",
Vignesh Viswanathan59f0fad2018-01-25 17:04:46 +05301493 __func__, fixed_param->radio_id,
1494 link_stats_results->num_radio);
1495 return -EINVAL;
1496 }
1497
1498 if (fixed_param->total_num_tx_power_levels >
1499 max_total_num_tx_power_levels) {
1500 WMA_LOGD("Invalid total_num_tx_power_levels %d",
1501 fixed_param->total_num_tx_power_levels);
1502 return -EINVAL;
1503 }
1504
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001505 rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] +
1506 fixed_param->radio_id;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001507 tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001508
1509 rs_results->total_num_tx_power_levels =
1510 fixed_param->total_num_tx_power_levels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001511 if (!rs_results->total_num_tx_power_levels) {
1512 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001513 goto post_stats;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001514 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001515
Vignesh Viswanathanad7eded2017-11-28 16:58:24 +05301516 if ((fixed_param->power_level_offset >
1517 rs_results->total_num_tx_power_levels) ||
1518 (fixed_param->num_tx_power_levels >
1519 rs_results->total_num_tx_power_levels -
1520 fixed_param->power_level_offset)) {
1521 WMA_LOGE("%s: Invalid offset %d total_num %d num %d",
1522 __func__, fixed_param->power_level_offset,
1523 rs_results->total_num_tx_power_levels,
1524 fixed_param->num_tx_power_levels);
1525 return -EINVAL;
1526 }
1527
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001528 if (!rs_results->tx_time_per_power_level) {
1529 rs_results->tx_time_per_power_level = qdf_mem_malloc(
1530 sizeof(uint32_t) *
1531 rs_results->total_num_tx_power_levels);
1532 if (!rs_results->tx_time_per_power_level) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001533 WMA_LOGA("%s: Mem alloc fail for tx power level stats",
1534 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001535 /* In error case, atleast send the radio stats without
1536 * tx_power_level stats */
1537 rs_results->total_num_tx_power_levels = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001538 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001539 goto post_stats;
1540 }
1541 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001542 qdf_mem_copy(&rs_results->tx_time_per_power_level[
1543 fixed_param->power_level_offset],
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001544 tx_power_level_values,
1545 sizeof(uint32_t) * fixed_param->num_tx_power_levels);
1546 if (rs_results->total_num_tx_power_levels ==
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001547 (fixed_param->num_tx_power_levels +
1548 fixed_param->power_level_offset)) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001549 link_stats_results->moreResultToFollow = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001550 link_stats_results->nr_received++;
1551 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001552
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001553 WMA_LOGD("%s: moreResultToFollow: %u nr: %u nr_received: %u",
1554 __func__, link_stats_results->moreResultToFollow,
1555 link_stats_results->num_radio,
1556 link_stats_results->nr_received);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001557
1558 /* If still data to receive, return from here */
1559 if (link_stats_results->moreResultToFollow)
1560 return 0;
1561
1562post_stats:
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001563 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1564 /* Not received all radio stats yet, don't post yet */
1565 return 0;
1566 }
1567
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001568 /* call hdd callback with Link Layer Statistics
1569 * vdev_id/ifacId in link_stats_results will be
1570 * used to retrieve the correct HDD context
1571 */
1572 mac->sme.pLinkLayerStatsIndCallback(mac->hHdd,
1573 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1574 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001575 wma_unified_radio_tx_mem_free(handle);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001576
1577 return 0;
1578}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579
1580/**
1581 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
1582 * @handle: wma handle
1583 * @cmd_param_info: data received with event from fw
1584 * @len: length of data
1585 *
1586 * Return: 0 for success or error code
1587 */
1588static int wma_unified_link_radio_stats_event_handler(void *handle,
1589 uint8_t *cmd_param_info,
1590 uint32_t len)
1591{
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001592 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001593 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1594 wmi_radio_link_stats_event_fixed_param *fixed_param;
1595 wmi_radio_link_stats *radio_stats;
1596 wmi_channel_stats *channel_stats;
1597 tSirLLStatsResults *link_stats_results;
1598 uint8_t *results, *t_radio_stats, *t_channel_stats;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001599 uint32_t next_chan_offset, count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001600 size_t radio_stats_size, chan_stats_size;
1601 size_t link_stats_results_size;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001602 tSirWifiRadioStat *rs_results;
1603 tSirWifiChannelStats *chn_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604
Anurag Chouhan6d760662016-02-20 16:05:43 +05301605 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606
1607 if (!pMac) {
1608 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1609 return -EINVAL;
1610 }
1611
1612 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1613 WMA_LOGD("%s: HDD callback is null", __func__);
1614 return -EINVAL;
1615 }
1616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001617 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1618 if (!param_tlvs) {
1619 WMA_LOGA("%s: Invalid stats event", __func__);
1620 return -EINVAL;
1621 }
1622
1623 /*
1624 * cmd_param_info contains
1625 * wmi_radio_link_stats_event_fixed_param fixed_param;
1626 * size of(struct wmi_radio_link_stats);
1627 * num_channels * size of(struct wmi_channel_stats)
1628 */
1629 fixed_param = param_tlvs->fixed_param;
1630 radio_stats = param_tlvs->radio_stats;
1631 channel_stats = param_tlvs->channel_stats;
1632
1633 if (!fixed_param || !radio_stats ||
1634 (radio_stats->num_channels && !channel_stats)) {
1635 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
1636 return -EINVAL;
1637 }
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001638 if (radio_stats->num_channels >
Abhinav Kumara03659c2017-12-28 15:18:07 +05301639 (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS) ||
1640 radio_stats->num_channels > param_tlvs->num_channel_stats) {
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001641 WMA_LOGE("%s: Too many channels %d",
1642 __func__, radio_stats->num_channels);
1643 return -EINVAL;
1644 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001645
1646 radio_stats_size = sizeof(tSirWifiRadioStat);
1647 chan_stats_size = sizeof(tSirWifiChannelStats);
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001648 if (fixed_param->num_radio >
1649 (UINT_MAX - sizeof(*link_stats_results))/radio_stats_size) {
1650 WMA_LOGE("excess num_radio %d is leading to int overflow",
1651 fixed_param->num_radio);
1652 return -EINVAL;
1653 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001654 link_stats_results_size = sizeof(*link_stats_results) +
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001655 fixed_param->num_radio * radio_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656
Vignesh Viswanathan01e1adb2018-03-23 20:22:38 +05301657 if (radio_stats->radio_id >= fixed_param->num_radio) {
1658 WMA_LOGE("%s, invalid radio id:%d, num radio:%d",
1659 __func__, radio_stats->radio_id,
1660 fixed_param->num_radio);
1661 return -EINVAL;
1662 }
1663
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001664 if (!wma_handle->link_stats_results) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001665 wma_handle->link_stats_results = qdf_mem_malloc(
1666 link_stats_results_size);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001667 if (NULL == wma_handle->link_stats_results) {
1668 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1669 __func__, link_stats_results_size);
1670 return -ENOMEM;
1671 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001672 }
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001673 link_stats_results = wma_handle->link_stats_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001674
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001675 WMA_LOGD("Radio stats Fixed Param:");
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001676 WMA_LOGD("req_id: %u num_radio: %u more_radio_events: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677 fixed_param->request_id, fixed_param->num_radio,
1678 fixed_param->more_radio_events);
1679
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001680 WMA_LOGD("Radio Info: radio_id: %u on_time: %u tx_time: %u rx_time: %u on_time_scan: %u",
1681 radio_stats->radio_id, radio_stats->on_time,
1682 radio_stats->tx_time, radio_stats->rx_time,
1683 radio_stats->on_time_scan);
1684 WMA_LOGD("on_time_nbd: %u on_time_gscan: %u on_time_roam_scan: %u",
1685 radio_stats->on_time_nbd,
1686 radio_stats->on_time_gscan, radio_stats->on_time_roam_scan);
1687 WMA_LOGD("on_time_pno_scan: %u on_time_hs20: %u num_channels: %u",
1688 radio_stats->on_time_pno_scan, radio_stats->on_time_hs20,
1689 radio_stats->num_channels);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001690 WMA_LOGD("on_time_host_scan: %u, on_time_lpi_scan: %u",
1691 radio_stats->on_time_host_scan, radio_stats->on_time_lpi_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001692
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001693 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
1694 link_stats_results->rspId = fixed_param->request_id;
1695 link_stats_results->ifaceId = 0;
1696 link_stats_results->num_radio = fixed_param->num_radio;
1697 link_stats_results->peer_event_number = 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001698
1699 /*
1700 * Backward compatibility:
1701 * There are firmware(s) which will send Radio stats only with
1702 * more_radio_events set to 0 and firmware which sends Radio stats
1703 * followed by tx_power level stats with more_radio_events set to 1.
1704 * if more_radio_events is set to 1, buffer the radio stats and
1705 * wait for tx_power_level stats.
1706 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001707 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
1708
1709 results = (uint8_t *) link_stats_results->results;
1710 t_radio_stats = (uint8_t *) radio_stats;
1711 t_channel_stats = (uint8_t *) channel_stats;
1712
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001713 rs_results = (tSirWifiRadioStat *) &results[0] + radio_stats->radio_id;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001714 rs_results->radio = radio_stats->radio_id;
1715 rs_results->onTime = radio_stats->on_time;
1716 rs_results->txTime = radio_stats->tx_time;
1717 rs_results->rxTime = radio_stats->rx_time;
1718 rs_results->onTimeScan = radio_stats->on_time_scan;
1719 rs_results->onTimeNbd = radio_stats->on_time_nbd;
1720 rs_results->onTimeGscan = radio_stats->on_time_gscan;
1721 rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
1722 rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
1723 rs_results->onTimeHs20 = radio_stats->on_time_hs20;
1724 rs_results->total_num_tx_power_levels = 0;
gaurank kathpalia247554c2017-11-30 19:12:01 +05301725 if (rs_results->tx_time_per_power_level) {
1726 qdf_mem_free(rs_results->tx_time_per_power_level);
1727 rs_results->tx_time_per_power_level = NULL;
1728 }
1729 if (rs_results->channels) {
1730 qdf_mem_free(rs_results->channels);
1731 rs_results->channels = NULL;
1732 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001733 rs_results->numChannels = radio_stats->num_channels;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001734 rs_results->on_time_host_scan = radio_stats->on_time_host_scan;
1735 rs_results->on_time_lpi_scan = radio_stats->on_time_lpi_scan;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001736 if (rs_results->numChannels) {
1737 rs_results->channels = (tSirWifiChannelStats *) qdf_mem_malloc(
1738 radio_stats->num_channels *
1739 chan_stats_size);
1740 if (rs_results->channels == NULL) {
1741 WMA_LOGD("%s: could not allocate mem for channel stats (size=%zu)",
1742 __func__, radio_stats->num_channels * chan_stats_size);
1743 wma_unified_radio_tx_mem_free(handle);
1744 return -ENOMEM;
1745 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001746
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001747 chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
1748 next_chan_offset = WMI_TLV_HDR_SIZE;
1749 WMA_LOGD("Channel Stats Info");
1750 for (count = 0; count < radio_stats->num_channels; count++) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001751 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001752 channel_stats->channel_width,
1753 channel_stats->center_freq,
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001754 channel_stats->center_freq0);
1755 WMA_LOGD("center_freq1 %u radio_awake_time %u cca_busy_time %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001756 channel_stats->center_freq1,
1757 channel_stats->radio_awake_time,
1758 channel_stats->cca_busy_time);
1759 channel_stats++;
1760
1761 qdf_mem_copy(chn_results,
1762 t_channel_stats + next_chan_offset,
1763 chan_stats_size);
1764 chn_results++;
1765 next_chan_offset += sizeof(*channel_stats);
1766 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 }
1768
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001769 if (link_stats_results->moreResultToFollow) {
1770 /* More results coming, don't post yet */
1771 return 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001772 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001773 link_stats_results->nr_received++;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001774
1775 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1776 /* Not received all radio stats yet, don't post yet */
1777 return 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001778 }
1779
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1781 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1782 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001783 wma_unified_radio_tx_mem_free(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784
1785 return 0;
1786}
1787
Zhang Qiana6e9c102016-12-22 16:47:24 +08001788#ifdef WLAN_PEER_PS_NOTIFICATION
1789/**
1790 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1791 * @handle: wma handle
1792 * @event: FW event
1793 * @len: length of FW event
1794 *
1795 * Once peer STA power state changes, an event will be indicated by
1796 * FW. This function send a link layer state change msg to HDD. HDD
1797 * link layer callback will converts the event to NL msg.
1798 *
1799 * Return: 0 Success. Others fail.
1800 */
1801static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1802 u_int32_t len)
1803{
1804 WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *param_buf;
1805 wmi_peer_sta_ps_statechange_event_fixed_param *fixed_param;
1806 tSirWifiPeerStat *peer_stat;
1807 tSirWifiPeerInfo *peer_info;
1808 tSirLLStatsResults *link_stats_results;
1809 tSirMacAddr mac_address;
1810 uint32_t result_len;
1811 cds_msg_t sme_msg = { 0 };
1812 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1813
1814 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1815
1816 if (!mac) {
1817 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1818 return -EINVAL;
1819 }
1820
1821 if (!mac->sme.link_layer_stats_ext_cb) {
1822 WMA_LOGD("%s: HDD callback is null", __func__);
1823 return -EINVAL;
1824 }
1825
1826 WMA_LOGD("%s: Posting Peer Stats PS event to HDD", __func__);
1827
1828 param_buf = (WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *)event;
1829 fixed_param = param_buf->fixed_param;
1830
1831 result_len = sizeof(tSirLLStatsResults) +
1832 sizeof(tSirWifiPeerStat) +
1833 sizeof(tSirWifiPeerInfo);
1834 link_stats_results = qdf_mem_malloc(result_len);
1835 if (link_stats_results == NULL) {
1836 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1837 return -EINVAL;
1838 }
1839
1840 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->peer_macaddr, &mac_address[0]);
1841 WMA_LOGD("Peer power state change event from FW");
1842 WMA_LOGD("Fixed Param:");
1843 WMA_LOGD("MAC address: %2x:%2x:%2x:%2x:%2x:%2x, Power state: %d",
1844 mac_address[0], mac_address[1], mac_address[2],
1845 mac_address[3], mac_address[4], mac_address[5],
1846 fixed_param->peer_ps_state);
1847
1848 link_stats_results->paramId = WMI_LL_STATS_EXT_PS_CHG;
1849 link_stats_results->num_peers = 1;
1850 link_stats_results->peer_event_number = 1;
1851 link_stats_results->moreResultToFollow = 0;
1852
1853 peer_stat = (tSirWifiPeerStat *)link_stats_results->results;
1854 peer_stat->numPeers = 1;
1855 peer_info = (tSirWifiPeerInfo *)peer_stat->peerInfo;
1856 qdf_mem_copy(&peer_info->peerMacAddress,
1857 &mac_address,
1858 sizeof(tSirMacAddr));
1859 peer_info->power_saving = fixed_param->peer_ps_state;
1860
1861 sme_msg.type = eWMI_SME_LL_STATS_IND;
1862 sme_msg.bodyptr = link_stats_results;
1863 sme_msg.bodyval = 0;
1864
Zhang Qian73c348a2017-03-13 16:15:55 +08001865 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001866 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1867 WMA_LOGE("%s: Fail to post ps change ind msg", __func__);
1868 qdf_mem_free(link_stats_results);
1869 }
1870
1871 return 0;
1872}
1873#else
1874/**
1875 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1876 * @handle: wma handle
1877 * @event: FW event
1878 * @len: length of FW event
1879 *
1880 * Once peer STA power state changes, an event will be indicated by
1881 * FW. This function send a link layer state change msg to HDD. HDD
1882 * link layer callback will converts the event to NL msg.
1883 *
1884 * Return: 0 Success. Others fail.
1885 */
1886static inline int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1887 u_int32_t len)
1888{
1889 return 0;
1890}
1891#endif
1892
1893/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 * wma_register_ll_stats_event_handler() - register link layer stats related
1895 * event handler
1896 * @wma_handle: wma handle
1897 *
1898 * Return: none
1899 */
1900void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
1901{
1902 if (NULL == wma_handle) {
1903 WMA_LOGE("%s: wma_handle is NULL", __func__);
1904 return;
1905 }
1906
1907 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301908 wmi_iface_link_stats_event_id,
Govind Singhd76a5b02016-03-08 15:12:14 +05301909 wma_unified_link_iface_stats_event_handler,
1910 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301912 wmi_peer_link_stats_event_id,
Govind Singhd76a5b02016-03-08 15:12:14 +05301913 wma_unified_link_peer_stats_event_handler,
1914 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001915 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301916 wmi_radio_link_stats_link,
Govind Singhd76a5b02016-03-08 15:12:14 +05301917 wma_unified_link_radio_stats_event_handler,
1918 WMA_RX_SERIALIZER_CTX);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001919 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301920 wmi_radio_tx_power_level_stats_event_id,
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001921 wma_unified_radio_tx_power_level_stats_event_handler,
1922 WMA_RX_SERIALIZER_CTX);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001923 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301924 wmi_peer_sta_ps_statechg_event_id,
Zhang Qiana6e9c102016-12-22 16:47:24 +08001925 wma_peer_ps_evt_handler,
1926 WMA_RX_SERIALIZER_CTX);
Zhang Qian73c348a2017-03-13 16:15:55 +08001927 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301928 wmi_report_stats_event_id,
Zhang Qian73c348a2017-03-13 16:15:55 +08001929 wma_ll_stats_evt_handler,
1930 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932}
1933
1934
1935/**
1936 * wma_process_ll_stats_clear_req() - clear link layer stats
1937 * @wma: wma handle
1938 * @clearReq: ll stats clear request command params
1939 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301940 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001942QDF_STATUS wma_process_ll_stats_clear_req(tp_wma_handle wma,
1943 const tpSirLLStatsClearReq clearReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001944{
Govind Singh4863da42016-03-08 11:45:00 +05301945 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 int ret;
1947
1948 if (!clearReq || !wma) {
1949 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301950 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 }
1952
Deepak Dhamdhere6adc08e2017-07-27 09:33:22 -07001953 if (!wma->interfaces[clearReq->staId].handle) {
1954 WMA_LOGE("%s: vdev_id %d handle is NULL",
1955 __func__, clearReq->staId);
1956 return QDF_STATUS_E_FAILURE;
1957 }
1958
Govind Singh4863da42016-03-08 11:45:00 +05301959 cmd.stop_req = clearReq->stopReq;
1960 cmd.sta_id = clearReq->staId;
1961 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962
Govind Singh4863da42016-03-08 11:45:00 +05301963 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
1964 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 if (ret) {
1966 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301967 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 }
1969
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301970 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971}
1972
1973/**
1974 * wma_process_ll_stats_set_req() - link layer stats set request
1975 * @wma: wma handle
1976 * @setReq: ll stats set request command params
1977 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301978 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001980QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma,
1981 const tpSirLLStatsSetReq setReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982{
Govind Singh4863da42016-03-08 11:45:00 +05301983 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 int ret;
1985
1986 if (!setReq || !wma) {
1987 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301988 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 }
1990
Govind Singh4863da42016-03-08 11:45:00 +05301991 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
1992 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 setReq->aggressiveStatisticsGathering;
1994
Govind Singh4863da42016-03-08 11:45:00 +05301995 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
1996 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 if (ret) {
1998 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301999 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 }
2001
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302002 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003}
2004
2005/**
2006 * wma_process_ll_stats_get_req() - link layer stats get request
2007 * @wma:wma handle
2008 * @getReq:ll stats get request command params
2009 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302010 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002012QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
2013 const tpSirLLStatsGetReq getReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014{
Govind Singh4863da42016-03-08 11:45:00 +05302015 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 int ret;
2017
2018 if (!getReq || !wma) {
2019 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302020 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 }
2022
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +05302023 if (!wma->interfaces[getReq->staId].vdev_active) {
2024 WMA_LOGE("%s: vdev not created yet", __func__);
2025 return QDF_STATUS_E_FAILURE;
2026 }
2027
Govind Singh4863da42016-03-08 11:45:00 +05302028 cmd.req_id = getReq->reqId;
2029 cmd.param_id_mask = getReq->paramIdMask;
2030 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002031
Govind Singh4863da42016-03-08 11:45:00 +05302032 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
2033 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 if (ret) {
2035 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302036 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 }
2038
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302039 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040}
2041
2042/**
2043 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
2044 * @wma:wma handle
2045 * @cmd_param_info: data from event
2046 * @len: length
2047 *
2048 * Return: 0 for success or error code
2049 */
2050int wma_unified_link_iface_stats_event_handler(void *handle,
2051 uint8_t *cmd_param_info,
2052 uint32_t len)
2053{
2054 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
2055 wmi_iface_link_stats_event_fixed_param *fixed_param;
2056 wmi_iface_link_stats *link_stats;
2057 wmi_wmm_ac_stats *ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002058 wmi_iface_offload_stats *offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059 tSirLLStatsResults *link_stats_results;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002060 uint8_t *results, *t_link_stats, *t_ac_stats, *t_offload_stats;
2061 uint32_t next_res_offset, next_ac_offset, next_offload_offset, count;
2062 uint32_t roaming_offset, size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 size_t link_stats_size, ac_stats_size, iface_info_size;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002064 size_t link_stats_results_size, offload_stats_size;
2065 size_t total_ac_size, total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066
Anurag Chouhan6d760662016-02-20 16:05:43 +05302067 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068
2069 if (!pMac) {
2070 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
2071 return -EINVAL;
2072 }
2073
2074 if (!pMac->sme.pLinkLayerStatsIndCallback) {
2075 WMA_LOGD("%s: HDD callback is null", __func__);
2076 return -EINVAL;
2077 }
2078
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
2080 if (!param_tlvs) {
2081 WMA_LOGA("%s: Invalid stats event", __func__);
2082 return -EINVAL;
2083 }
2084
2085 /*
2086 * cmd_param_info contains
2087 * wmi_iface_link_stats_event_fixed_param fixed_param;
2088 * wmi_iface_link_stats iface_link_stats;
2089 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002090 * fixed_param->num_offload_stats * size of(wmi_iface_offload_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002091 */
2092 fixed_param = param_tlvs->fixed_param;
2093 link_stats = param_tlvs->iface_link_stats;
2094 ac_stats = param_tlvs->ac;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002095 offload_stats = param_tlvs->iface_offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002096
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002097 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats) ||
2098 (fixed_param->num_offload_stats && !offload_stats)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
2100 return -EINVAL;
2101 }
Abhinav Kumara03659c2017-12-28 15:18:07 +05302102 if (link_stats->num_ac > WIFI_AC_MAX || link_stats->num_ac >
2103 param_tlvs->num_ac) {
2104 WMA_LOGE("%s: Excess data received from firmware num_ac %d, param_tlvs->num_ac %d",
2105 __func__, link_stats->num_ac, param_tlvs->num_ac);
Vignesh Viswanathan37794ae2017-09-28 15:26:56 +05302106 return -EINVAL;
2107 }
Abhinav Kumara03659c2017-12-28 15:18:07 +05302108 if (fixed_param->num_offload_stats > WMI_OFFLOAD_STATS_TYPE_MAX ||
2109 fixed_param->num_offload_stats >
2110 param_tlvs->num_iface_offload_stats) {
2111 WMA_LOGE("%s: Excess num offload stats recvd from fw: %d, um_iface_offload_stats: %d",
2112 __func__, fixed_param->num_offload_stats,
2113 param_tlvs->num_iface_offload_stats);
Vignesh Viswanathan37794ae2017-09-28 15:26:56 +05302114 return -EINVAL;
2115 }
2116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117 link_stats_size = sizeof(tSirWifiIfaceStat);
2118 iface_info_size = sizeof(tSirWifiInterfaceInfo);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002120 ac_stats_size = sizeof(tSirWifiWmmAcStat);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002121 offload_stats_size = sizeof(struct wifi_iface_offload_stat);
2122
2123 total_ac_size = ac_stats_size * WIFI_AC_MAX;
2124 total_offload_size = offload_stats_size * WMI_OFFLOAD_STATS_TYPE_MAX +
2125 member_size(tSirWifiIfaceStat, num_offload_stats);
2126
2127 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002128
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302129 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 if (!link_stats_results) {
2131 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
2132 __func__, link_stats_results_size);
2133 return -ENOMEM;
2134 }
2135
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302136 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002137
2138 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
2139 link_stats_results->rspId = fixed_param->request_id;
2140 link_stats_results->ifaceId = fixed_param->vdev_id;
2141 link_stats_results->num_peers = link_stats->num_peers;
2142 link_stats_results->peer_event_number = 0;
2143 link_stats_results->moreResultToFollow = 0;
2144
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002145 /* results is copied to tSirWifiIfaceStat in upper layer
2146 * tSirWifiIfaceStat
2147 * - tSirWifiInterfaceInfo (all fields except roaming is
2148 * filled by host in the upper layer)
2149 * - various members of tSirWifiIfaceStat (from wmi_iface_link_stats)
2150 * - ACs information (from wmi_wmm_ac_stats)
2151 * - num_offload_stats (from fixed param)
2152 * - offload stats (from wmi_iface_offload_stats)
2153 */
2154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002155 results = (uint8_t *) link_stats_results->results;
2156 t_link_stats = (uint8_t *) link_stats;
2157 t_ac_stats = (uint8_t *) ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002158 t_offload_stats = (uint8_t *) offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002159
2160 /* Copy roaming state */
2161 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002162 size = member_size(tSirWifiInterfaceInfo, roaming);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002163
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002164 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state, size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002166 next_res_offset = iface_info_size;
2167 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 t_link_stats + WMI_TLV_HDR_SIZE,
2169 link_stats_size - iface_info_size -
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002170 total_ac_size - total_offload_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002172 next_res_offset = link_stats_size - total_ac_size - total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 next_ac_offset = WMI_TLV_HDR_SIZE;
2174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 for (count = 0; count < link_stats->num_ac; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 ac_stats++;
2177
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302178 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 t_ac_stats + next_ac_offset, ac_stats_size);
2180 next_res_offset += ac_stats_size;
2181 next_ac_offset += sizeof(*ac_stats);
2182 }
2183
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002184 next_res_offset = link_stats_size - total_offload_size;
2185 /* copy num_offload_stats into result */
2186 size = member_size(tSirWifiIfaceStat, num_offload_stats);
2187 qdf_mem_copy(results + next_res_offset, &fixed_param->num_offload_stats,
2188 size);
2189
2190 next_res_offset += size;
2191 next_offload_offset = WMI_TLV_HDR_SIZE;
2192
2193 for (count = 0; count < fixed_param->num_offload_stats; count++) {
2194 qdf_mem_copy(results + next_res_offset,
2195 t_offload_stats + next_offload_offset,
2196 offload_stats_size);
2197 next_res_offset += offload_stats_size;
2198 next_offload_offset += sizeof(*offload_stats);
2199 }
2200
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201 /* call hdd callback with Link Layer Statistics
2202 * vdev_id/ifacId in link_stats_results will be
2203 * used to retrieve the correct HDD context
2204 */
2205 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
2206 WMA_LINK_LAYER_STATS_RESULTS_RSP,
2207 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302208 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209
2210 return 0;
2211}
2212
Zhang Qian73c348a2017-03-13 16:15:55 +08002213/**
2214 * wma_config_stats_ext_threshold - set threthold for MAC counters
2215 * @wma: wma handler
2216 * @threshold: threhold for MAC counters
2217 *
2218 * For each MAC layer counter, FW holds two copies. One is the current value.
2219 * The other is the last report. Once a current counter's increment is larger
2220 * than the threshold, FW will indicate that counter to host even if the
2221 * monitoring timer does not expire.
2222 *
2223 * Return: None
2224 */
2225void wma_config_stats_ext_threshold(tp_wma_handle wma,
2226 struct sir_ll_ext_stats_threshold *thresh)
2227{
2228 uint32_t len, tag, hdr_len;
2229 uint8_t *buf_ptr;
2230 wmi_buf_t buf;
2231 wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
2232 wmi_chan_cca_stats_thresh *cca;
2233 wmi_peer_signal_stats_thresh *signal;
2234 wmi_tx_stats_thresh *tx;
2235 wmi_rx_stats_thresh *rx;
2236
2237 if (!thresh) {
2238 WMA_LOGE(FL("Invalid threshold input."));
2239 return;
2240 }
2241
2242 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
2243 sizeof(wmi_chan_cca_stats_thresh) +
2244 sizeof(wmi_peer_signal_stats_thresh) +
2245 sizeof(wmi_tx_stats_thresh) +
2246 sizeof(wmi_rx_stats_thresh) +
2247 5 * WMI_TLV_HDR_SIZE;
2248 buf = wmi_buf_alloc(wma->wmi_handle, len);
2249 if (!buf) {
2250 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
2251 return;
2252 }
2253
2254 buf_ptr = (u_int8_t *)wmi_buf_data(buf);
2255 tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
2256 hdr_len = WMITLV_GET_STRUCT_TLVLEN(
2257 wmi_pdev_set_stats_threshold_cmd_fixed_param);
2258 WMA_LOGD(FL("Setting fixed parameters. tag=%d, len=%d"), tag, hdr_len);
2259 cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
2260 WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
2261 cmd->enable_thresh = thresh->enable;
2262 cmd->use_thresh_bitmap = thresh->enable_bitmap;
2263 cmd->gbl_thresh = thresh->global_threshold;
2264 cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
2265 cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
2266 cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
2267 cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
2268 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
2269
2270 tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
2271 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
2272 cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
2273 WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
2274 WMA_LOGD(FL("Setting cca parameters. tag=%d, len=%d"), tag, hdr_len);
2275 cca->idle_time = thresh->cca.idle_time;
2276 cca->tx_time = thresh->cca.tx_time;
2277 cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
2278 cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
2279 cca->rx_busy_time = thresh->cca.rx_busy_time;
2280 cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
2281 cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
2282 cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
2283 WMA_LOGD(FL("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d"),
2284 cca->idle_time, cca->tx_time,
2285 cca->rx_in_bss_time, cca->rx_out_bss_time);
2286 WMA_LOGD(FL("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d"),
2287 cca->rx_busy_time, cca->rx_in_bad_cond_time,
2288 cca->tx_in_bad_cond_time, cca->wlan_not_avail_time);
2289 len += sizeof(wmi_chan_cca_stats_thresh);
2290
2291 signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
2292 tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
2293 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
2294 WMA_LOGD(FL("Setting signal parameters. tag=%d, len=%d"), tag, hdr_len);
2295 WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
2296 signal->per_chain_snr = thresh->signal.snr;
2297 signal->per_chain_nf = thresh->signal.nf;
2298 WMA_LOGD(FL("snr=%d, nf=%d"), signal->per_chain_snr,
2299 signal->per_chain_nf);
2300 len += sizeof(wmi_peer_signal_stats_thresh);
2301
2302 tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
2303 tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
2304 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
2305 WMA_LOGD(FL("Setting TX parameters. tag=%d, len=%d"), tag, len);
2306 WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
2307 tx->tx_msdu_cnt = thresh->tx.msdu;
2308 tx->tx_mpdu_cnt = thresh->tx.mpdu;
2309 tx->tx_ppdu_cnt = thresh->tx.ppdu;
2310 tx->tx_bytes = thresh->tx.bytes;
2311 tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
2312 tx->tx_drop_bytes = thresh->tx.byte_drop;
2313 tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
2314 tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
2315 tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
2316 tx->tx_mpdu_aggr = thresh->tx.aggregation;
2317 tx->tx_succ_mcs = thresh->tx.succ_mcs;
2318 tx->tx_fail_mcs = thresh->tx.fail_mcs;
2319 tx->tx_ppdu_delay = thresh->tx.delay;
2320 WMA_LOGD(FL("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d"),
2321 tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
2322 tx->tx_bytes, tx->tx_msdu_drop_cnt);
2323 WMA_LOGD(FL("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d"),
2324 tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
2325 tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
2326 WMA_LOGD(FL("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d"),
2327 tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
2328 tx->tx_ppdu_delay);
2329 len += sizeof(wmi_tx_stats_thresh);
2330
2331 rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
2332 tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
2333 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
2334 WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
2335 WMA_LOGD(FL("Setting RX parameters. tag=%d, len=%d"), tag, hdr_len);
2336 rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
2337 rx->mac_rx_bytes = thresh->rx.bytes;
2338 rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
2339 rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
2340 rx->rx_disorder_cnt = thresh->rx.disorder;
2341 rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
2342 rx->rx_mpdu_dup_cnt = thresh->rx.mpdu_dup;
2343 rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
2344 rx->rx_mpdu_aggr = thresh->rx.aggregation;
2345 rx->rx_mcs = thresh->rx.mcs;
2346 rx->sta_ps_inds = thresh->rx.ps_inds;
2347 rx->sta_ps_durs = thresh->rx.ps_durs;
2348 rx->rx_probe_reqs = thresh->rx.probe_reqs;
2349 rx->rx_oth_mgmts = thresh->rx.other_mgmt;
2350 WMA_LOGD(FL("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d"),
2351 rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
2352 rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
2353 WMA_LOGD(FL("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d"),
2354 rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
2355 rx->rx_mpdu_aggr, rx->rx_mcs);
2356 WMA_LOGD(FL("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d"),
2357 rx->sta_ps_inds, rx->sta_ps_durs,
2358 rx->rx_probe_reqs, rx->rx_oth_mgmts);
2359 len += sizeof(wmi_rx_stats_thresh);
2360
2361 WMA_LOGA("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
2362 WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
2363 if (EOK != wmi_unified_cmd_send(wma->wmi_handle,
2364 buf, len,
2365 WMI_PDEV_SET_STATS_THRESHOLD_CMDID)) {
2366 WMA_LOGE("Failed to send WMI_PDEV_SET_STATS_THRESHOLD_CMDID");
2367 wmi_buf_free(buf);
2368 }
2369}
2370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2372
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002373#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374/**
2375 * wma_update_pdev_stats() - update pdev stats
2376 * @wma: wma handle
2377 * @pdev_stats: pdev stats
2378 *
2379 * Return: none
2380 */
2381static void wma_update_pdev_stats(tp_wma_handle wma,
2382 wmi_pdev_stats *pdev_stats)
2383{
2384 tAniGetPEStatsRsp *stats_rsp_params;
2385 uint32_t temp_mask;
2386 uint8_t *stats_buf;
2387 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2388 struct wma_txrx_node *node;
2389 uint8_t i;
2390
2391 for (i = 0; i < wma->max_bssid; i++) {
2392 node = &wma->interfaces[i];
2393 stats_rsp_params = node->stats_rsp;
2394 if (stats_rsp_params) {
2395 node->fw_stats_set |= FW_PDEV_STATS_SET;
2396 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
2397 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2398 temp_mask = stats_rsp_params->statsMask;
2399 if (temp_mask & (1 << eCsrSummaryStats))
2400 stats_buf += sizeof(tCsrSummaryStatsInfo);
2401
2402 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2403 classa_stats =
2404 (tCsrGlobalClassAStatsInfo *) stats_buf;
2405 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
2406 }
2407 }
2408 }
2409}
2410
2411/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302412 * wma_vdev_stats_lost_link_helper() - helper function to extract
2413 * lost link information from vdev statistics event while deleting BSS.
2414 * @wma: WMA handle
2415 * @vdev_stats: statistics information from firmware
2416 *
2417 * This is for informing HDD to collect lost link information while
2418 * disconnection. Following conditions to check
2419 * 1. vdev is up
2420 * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to
2421 * zero, hence add the check here to indicate the event comes during deleting
2422 * BSS
2423 * 3. DELETE_BSS is the request message queued. Put this condition check on the
2424 * last one as it consumes more resource searching entries in the list
2425 *
2426 * Return: none
2427 */
2428static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma,
2429 wmi_vdev_stats *vdev_stats)
2430{
2431 struct wma_txrx_node *node;
2432 int32_t rssi;
2433 struct wma_target_req *req_msg;
2434 static const uint8_t zero_mac[QDF_MAC_ADDR_SIZE] = {0};
Naveen Rawatf440a132017-05-05 12:27:39 -07002435 int32_t bcn_snr, dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302436
Rajeev Kumar0b071172018-02-08 18:21:57 -08002437 if (vdev_stats->vdev_id >= wma->max_bssid) {
2438 WMA_LOGE("%s: Invalid vdev_id %hu",
2439 __func__, vdev_stats->vdev_id);
2440 return;
2441 }
2442
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302443 node = &wma->interfaces[vdev_stats->vdev_id];
Mukul Sharmaf9047232017-03-02 16:58:56 +05302444 if (wma_is_vdev_up(vdev_stats->vdev_id) &&
Hanumanth Reddy Pothulaaef3c7f2017-05-18 12:19:23 +05302445 !qdf_mem_cmp(node->bssid, zero_mac, QDF_MAC_ADDR_SIZE)) {
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302446 req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id,
2447 WMA_TARGET_REQ_TYPE_VDEV_STOP);
2448 if ((NULL == req_msg) ||
2449 (WMA_DELETE_BSS_REQ != req_msg->msg_type)) {
2450 WMA_LOGD(FL("cannot find DELETE_BSS request message"));
2451 return;
2452 }
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002453 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2454 dat_snr = vdev_stats->vdev_snr.dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302455 WMA_LOGD(FL("get vdev id %d, beancon snr %d, data snr %d"),
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002456 vdev_stats->vdev_id, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302457
2458 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002459 rssi = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302460 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002461 rssi = dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302462 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302463 rssi = WMA_TGT_INVALID_SNR;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302464
2465 /* Get the absolute rssi value from the current rssi value */
2466 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2467 wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi);
2468 }
2469}
2470
2471/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 * wma_update_vdev_stats() - update vdev stats
2473 * @wma: wma handle
2474 * @vdev_stats: vdev stats
2475 *
2476 * Return: none
2477 */
2478static void wma_update_vdev_stats(tp_wma_handle wma,
2479 wmi_vdev_stats *vdev_stats)
2480{
2481 tAniGetPEStatsRsp *stats_rsp_params;
2482 tCsrSummaryStatsInfo *summary_stats = NULL;
2483 uint8_t *stats_buf;
2484 struct wma_txrx_node *node;
2485 uint8_t i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002486 int32_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302487 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002489 struct scheduler_msg sme_msg = { 0 };
Naveen Rawatf440a132017-05-05 12:27:39 -07002490 int32_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491
Rajeev Kumar0b071172018-02-08 18:21:57 -08002492 if (vdev_stats->vdev_id >= wma->max_bssid) {
2493 WMA_LOGE("%s: Invalid vdev_id %hu",
2494 __func__, vdev_stats->vdev_id);
2495 return;
2496 }
2497
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002498 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2499 dat_snr = vdev_stats->vdev_snr.dat_snr;
2500 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
2501 vdev_stats->vdev_id, bcn_snr, dat_snr);
2502
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 node = &wma->interfaces[vdev_stats->vdev_id];
2504 stats_rsp_params = node->stats_rsp;
2505 if (stats_rsp_params) {
2506 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2507 node->fw_stats_set |= FW_VDEV_STATS_SET;
2508 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
2509 vdev_stats->vdev_id);
2510 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
2511 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
2512 for (i = 0; i < 4; i++) {
2513 summary_stats->tx_frm_cnt[i] =
2514 vdev_stats->tx_frm_cnt[i];
2515 summary_stats->fail_cnt[i] =
2516 vdev_stats->fail_cnt[i];
2517 summary_stats->multiple_retry_cnt[i] =
2518 vdev_stats->multiple_retry_cnt[i];
2519 }
2520
2521 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
2522 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
2523 summary_stats->rx_discard_cnt =
2524 vdev_stats->rx_discard_cnt;
2525 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
2526 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
2527 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002528 /* Update SNR and RSSI in SummaryStats */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302529 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002530 summary_stats->snr = bcn_snr;
2531 summary_stats->rssi =
2532 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302533 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002534 summary_stats->snr = dat_snr;
2535 summary_stats->rssi =
Naveen Rawatf440a132017-05-05 12:27:39 -07002536 dat_snr + WMA_TGT_NOISE_FLOOR_DBM;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002537 } else {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302538 summary_stats->snr = WMA_TGT_INVALID_SNR;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002539 summary_stats->rssi = 0;
2540 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 }
2542 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543
2544 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302545 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
2546 rssi = bcn_snr;
2547 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2548 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
2549 rssi = dat_snr;
2550 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2551 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552 /*
2553 * Firmware sends invalid snr till it sees
2554 * Beacon/Data after connection since after
2555 * vdev up fw resets the snr to invalid.
2556 * In this duartion Host will return the last know
2557 * rssi during connection.
2558 */
2559 WMA_LOGE("Invalid SNR from firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 }
2561
2562 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
2563 pGetRssiReq->sessionId);
2564
2565 /* update the average rssi value to UMAC layer */
2566 if (NULL != pGetRssiReq->rssiCallback) {
2567 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
2568 pGetRssiReq->staId,
2569 pGetRssiReq->pDevContext);
2570 }
2571
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302572 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573 wma->pGetRssiReq = NULL;
2574 }
2575
2576 if (node->psnr_req) {
2577 tAniGetSnrReq *p_snr_req = node->psnr_req;
2578
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302579 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07002580 p_snr_req->snr = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302581 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002582 p_snr_req->snr = dat_snr;
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002583 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302584 p_snr_req->snr = WMA_TGT_INVALID_SNR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585
2586 sme_msg.type = eWNI_SME_SNR_IND;
2587 sme_msg.bodyptr = p_snr_req;
2588 sme_msg.bodyval = 0;
2589
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002590 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302591 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302593 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594 }
2595
2596 node->psnr_req = NULL;
2597 }
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302598 wma_vdev_stats_lost_link_helper(wma, vdev_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599}
2600
2601/**
2602 * wma_post_stats() - update stats to PE
2603 * @wma: wma handle
2604 * @node: txrx node
2605 *
2606 * Return: none
2607 */
2608static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
2609{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002610 /* send response to UMAC */
Naveen Rawat3c49d192017-03-02 18:43:16 -08002611 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, node->stats_rsp, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 node->stats_rsp = NULL;
2613 node->fw_stats_set = 0;
2614}
2615
2616/**
2617 * wma_update_peer_stats() - update peer stats
2618 * @wma: wma handle
2619 * @peer_stats: peer stats
2620 *
2621 * Return: none
2622 */
2623static void wma_update_peer_stats(tp_wma_handle wma,
2624 wmi_peer_stats *peer_stats)
2625{
2626 tAniGetPEStatsRsp *stats_rsp_params;
2627 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2628 struct wma_txrx_node *node;
2629 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
2630 uint32_t temp_mask;
2631
2632 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
2633 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
2634 return;
2635
2636 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002637 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2638 if (stats_rsp_params) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639 node->fw_stats_set |= FW_PEER_STATS_SET;
2640 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2642 temp_mask = stats_rsp_params->statsMask;
2643 if (temp_mask & (1 << eCsrSummaryStats))
2644 stats_buf += sizeof(tCsrSummaryStatsInfo);
2645
2646 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2647 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
2648 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002649 /* The linkspeed returned by fw is in kbps so convert
2650 * it in to units of 500kbps which is expected by UMAC
2651 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002652 if (peer_stats->peer_tx_rate) {
2653 classa_stats->tx_rate =
2654 peer_stats->peer_tx_rate / 500;
2655 }
2656
2657 classa_stats->tx_rate_flags = node->rate_flags;
Naveen Rawatea1564b2018-05-17 15:56:11 -07002658 if (!(node->rate_flags & TX_RATE_LEGACY)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002659 classa_stats->mcs_index =
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002660 wma_get_mcs_idx(
2661 (peer_stats->peer_tx_rate /
2662 100), node->rate_flags,
2663 node->nss, &mcsRateFlags);
Jeff Johnsonad0b2c62017-03-16 14:37:38 -07002664 classa_stats->nss = node->nss;
2665 classa_stats->mcs_rate_flags = mcsRateFlags;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 }
2667 /* FW returns tx power in intervals of 0.5 dBm
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002668 * Convert it back to intervals of 1 dBm
2669 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 classa_stats->max_pwr =
2671 roundup(classa_stats->max_pwr, 2) >> 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 }
2674}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002675#endif /* WMA_GET_STATISTICS_RSP */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676
2677/**
2678 * wma_post_link_status() - post link status to SME
2679 * @pGetLinkStatus: SME Link status
2680 * @link_status: Link status
2681 *
2682 * Return: none
2683 */
2684void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
2685 uint8_t link_status)
2686{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302687 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002688 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689
2690 pGetLinkStatus->linkStatus = link_status;
2691 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
2692 sme_msg.bodyptr = pGetLinkStatus;
2693 sme_msg.bodyval = 0;
2694
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002695 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302696 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302698 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 }
2700}
2701
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002702#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302704 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
2705 * @wma: wma handle
2706 * @rssi_stats: rssi stats
2707 * @rssi_per_chain_stats: buffer where rssi stats to be stored
2708 *
2709 * This function stores per chain rssi stats received from fw for all vdevs for
2710 * which the stats were requested into a csr stats structure.
2711 *
2712 * Return: void
2713 */
2714static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
2715 wmi_rssi_stats *rssi_stats,
2716 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
2717{
2718 int i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002719 int32_t bcn_snr, dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302720
2721 for (i = 0; i < NUM_CHAINS_MAX; i++) {
2722 bcn_snr = rssi_stats->rssi_avg_beacon[i];
2723 dat_snr = rssi_stats->rssi_avg_data[i];
2724 WMA_LOGD("chain %d beacon snr %d data snr %d",
2725 i, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302726 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302727 rssi_per_chain_stats->rssi[i] = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302728 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
2729 rssi_per_chain_stats->rssi[i] = dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302730 else
2731 /*
2732 * Firmware sends invalid snr till it sees
2733 * Beacon/Data after connection since after
2734 * vdev up fw resets the snr to invalid.
2735 * In this duartion Host will return an invalid rssi
2736 * value.
2737 */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302738 rssi_per_chain_stats->rssi[i] = WMA_TGT_INVALID_SNR;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302739
2740 /*
2741 * Get the absolute rssi value from the current rssi value the
2742 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
2743 */
2744 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
2745 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
2746 rssi_per_chain_stats->peer_mac_addr);
2747 }
2748}
2749
2750/**
2751 * wma_update_rssi_stats() - to update rssi stats for all vdevs
2752 * for which the stats were requested.
2753 * @wma: wma handle
2754 * @rssi_stats: rssi stats
2755 *
2756 * This function updates the rssi stats for all vdevs for which
2757 * the stats were requested.
2758 *
2759 * Return: void
2760 */
2761static void wma_update_rssi_stats(tp_wma_handle wma,
2762 wmi_rssi_stats *rssi_stats)
2763{
2764 tAniGetPEStatsRsp *stats_rsp_params;
2765 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
2766 struct wma_txrx_node *node;
2767 uint8_t *stats_buf;
2768 uint32_t temp_mask;
2769 uint8_t vdev_id;
2770
Rajeev Kumar0b071172018-02-08 18:21:57 -08002771 if (rssi_stats->vdev_id >= wma->max_bssid) {
2772 WMA_LOGE("%s: Invalid vdev_id %hu",
2773 __func__, rssi_stats->vdev_id);
2774 return;
2775 }
2776
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302777 vdev_id = rssi_stats->vdev_id;
2778 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002779 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2780 if (stats_rsp_params) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302781 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
2782 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
2783 vdev_id);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302784 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2785 temp_mask = stats_rsp_params->statsMask;
2786
2787 if (temp_mask & (1 << eCsrSummaryStats))
2788 stats_buf += sizeof(tCsrSummaryStatsInfo);
2789 if (temp_mask & (1 << eCsrGlobalClassAStats))
2790 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302791 if (temp_mask & (1 << eCsrGlobalClassDStats))
2792 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302793
2794 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
2795 rssi_per_chain_stats =
2796 (struct csr_per_chain_rssi_stats_info *)stats_buf;
2797 wma_update_per_chain_rssi_stats(wma, rssi_stats,
2798 rssi_per_chain_stats);
2799 }
2800 }
2801}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002802#endif /* QCA_SUPPORT_CP_STATS */
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302803
2804/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 * wma_link_status_event_handler() - link status event handler
2806 * @handle: wma handle
2807 * @cmd_param_info: data from event
2808 * @len: length
2809 *
2810 * Return: 0 for success or error code
2811 */
2812int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
2813 uint32_t len)
2814{
2815 tp_wma_handle wma = (tp_wma_handle) handle;
2816 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
2817 wmi_vdev_rate_stats_event_fixed_param *event;
2818 wmi_vdev_rate_ht_info *ht_info;
2819 struct wma_txrx_node *intr = wma->interfaces;
2820 uint8_t link_status = LINK_STATUS_LEGACY;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002821 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822
2823 param_buf =
2824 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2825 if (!param_buf) {
2826 WMA_LOGA("%s: Invalid stats event", __func__);
2827 return -EINVAL;
2828 }
2829
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002830 event = (wmi_vdev_rate_stats_event_fixed_param *)
2831 param_buf->fixed_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
2833
2834 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002835
2836 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
Abhinav Kumara03659c2017-12-28 15:18:07 +05302837 sizeof(*event)) / sizeof(*ht_info)) ||
2838 event->num_vdev_stats > param_buf->num_ht_info) {
2839 WMA_LOGE("%s: excess vdev_stats buffers:%d, num_ht_info:%d",
2840 __func__, event->num_vdev_stats,
2841 param_buf->num_ht_info);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002842 return -EINVAL;
2843 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002844 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
2845 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
2846 __func__, ht_info->vdevid, ht_info->tx_nss,
2847 ht_info->rx_nss, ht_info->tx_preamble,
2848 ht_info->rx_preamble);
2849 if (ht_info->vdevid < wma->max_bssid
2850 && intr[ht_info->vdevid].plink_status_req) {
2851 if (ht_info->tx_nss || ht_info->rx_nss)
2852 link_status = LINK_STATUS_MIMO;
2853
2854 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
2855 (ht_info->rx_preamble == LINK_RATE_VHT))
2856 link_status |= LINK_STATUS_VHT;
2857
2858 if (intr[ht_info->vdevid].nss == 2)
2859 link_status |= LINK_SUPPORT_MIMO;
2860
2861 if (intr[ht_info->vdevid].rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -07002862 (TX_RATE_VHT20 | TX_RATE_VHT40 |
2863 TX_RATE_VHT80))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002864 link_status |= LINK_SUPPORT_VHT;
2865
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002866 wma_post_link_status(
2867 intr[ht_info->vdevid].plink_status_req,
2868 link_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002869 intr[ht_info->vdevid].plink_status_req = NULL;
2870 link_status = LINK_STATUS_LEGACY;
2871 }
2872
2873 ht_info++;
2874 }
2875
2876 return 0;
2877}
2878
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302879int wma_rso_cmd_status_event_handler(wmi_roam_event_fixed_param *wmi_event)
2880{
2881 struct rso_cmd_status *rso_status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -07002882 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302883 QDF_STATUS qdf_status;
2884
2885 rso_status = qdf_mem_malloc(sizeof(*rso_status));
2886 if (!rso_status) {
2887 WMA_LOGE("%s: malloc fails for rso cmd status", __func__);
2888 return -ENOMEM;
2889 }
2890
2891 rso_status->vdev_id = wmi_event->vdev_id;
2892 if (WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS == wmi_event->notif)
2893 rso_status->status = true;
2894 else if (WMI_ROAM_NOTIF_SCAN_MODE_FAIL == wmi_event->notif)
2895 rso_status->status = false;
2896 sme_msg.type = eWNI_SME_RSO_CMD_STATUS_IND;
2897 sme_msg.bodyptr = rso_status;
2898 sme_msg.bodyval = 0;
2899 WMA_LOGI("%s: Post RSO cmd status to SME", __func__);
2900
2901 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2902 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2903 WMA_LOGE("%s: fail to post RSO cmd status to SME", __func__);
2904 qdf_mem_free(rso_status);
2905 }
2906 return 0;
2907}
2908
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002909#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910/**
Will Huanga9814592017-05-24 15:47:58 +08002911 * wma_handle_sta_peer_info() - handle peer information in
2912 * peer stats
2913 * @num_peer_stats: peer number
2914 * @peer_stats: peer stats received from firmware
2915 * @peer_macaddr: the specified mac address
2916 * @sapaddr: sap mac address
2917 *
2918 * This function will send eWNI_SME_GET_PEER_INFO_IND
2919 * to sme with stations' information
2920 *
2921 */
2922static void wma_handle_sta_peer_info(uint32_t num_peer_stats,
2923 wmi_peer_stats *peer_stats,
2924 struct qdf_mac_addr peer_macaddr,
2925 uint8_t *sapaddr)
2926{
2927 QDF_STATUS qdf_status;
2928 wmi_mac_addr temp_addr;
2929 struct sir_peer_info_resp *peer_info;
2930 struct scheduler_msg sme_msg = {0};
2931 uint32_t i;
2932 uint32_t j = 0;
2933
2934 if (!qdf_is_macaddr_broadcast(&peer_macaddr)) {
2935 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_macaddr.bytes, &temp_addr);
2936 for (i = 0; i < num_peer_stats; i++) {
2937 if ((((temp_addr.mac_addr47to32) & 0x0000ffff) ==
2938 ((peer_stats->peer_macaddr.mac_addr47to32) &
2939 0x0000ffff))
2940 && (temp_addr.mac_addr31to0 ==
2941 peer_stats->peer_macaddr.mac_addr31to0)) {
2942
2943 break;
2944 }
2945 peer_stats = peer_stats + 1;
2946 }
2947 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2948 sizeof(peer_info->info[0]));
2949 if (NULL == peer_info) {
2950 WMA_LOGE("%s: Memory allocation failed.", __func__);
2951 return;
2952 }
2953 if (i < num_peer_stats) {
2954 peer_info->count = 1;
2955 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2956 peer_info->info[0].peer_macaddr.bytes);
2957 peer_info->info[0].rssi = peer_stats->peer_rssi;
2958 peer_info->info[0].tx_rate = peer_stats->peer_tx_rate;
2959 peer_info->info[0].rx_rate = peer_stats->peer_rx_rate;
2960 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2961 __func__,
2962 peer_info->info[0].peer_macaddr.bytes,
2963 peer_stats->peer_rssi,
2964 peer_stats->peer_tx_rate,
2965 peer_stats->peer_rx_rate);
2966 } else {
2967 WMA_LOGE("%s: no match mac address", __func__);
2968 peer_info->count = 0;
2969 }
2970 } else {
2971 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2972 num_peer_stats * sizeof(peer_info->info[0]));
2973 if (NULL == peer_info) {
2974 WMA_LOGE("%s: Memory allocation failed.", __func__);
2975 return;
2976 }
2977 peer_info->count = num_peer_stats;
2978
2979 for (i = 0; i < num_peer_stats; i++) {
2980 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2981 peer_info->info[j].peer_macaddr.bytes);
2982 peer_info->info[j].rssi = peer_stats->peer_rssi;
2983 peer_info->info[j].tx_rate = peer_stats->peer_tx_rate;
2984 peer_info->info[j].rx_rate = peer_stats->peer_rx_rate;
2985 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2986 __func__,
2987 peer_info->info[j].peer_macaddr.bytes,
2988 peer_stats->peer_rssi,
2989 peer_stats->peer_tx_rate,
2990 peer_stats->peer_rx_rate);
2991 if (!qdf_mem_cmp(peer_info->info[j].peer_macaddr.bytes,
2992 sapaddr, QDF_MAC_ADDR_SIZE)) {
2993 peer_info->count = peer_info->count - 1;
2994 } else {
2995 j++;
2996 }
2997 peer_stats = peer_stats + 1;
2998 }
2999 WMA_LOGD("WDA send peer num %d", peer_info->count);
3000 }
3001
3002 sme_msg.type = eWNI_SME_GET_PEER_INFO_IND;
3003 sme_msg.bodyptr = peer_info;
3004 sme_msg.bodyval = 0;
3005
3006 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3007 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3008 WMA_LOGE("%s: Fail to post get rssi msg", __func__);
3009 qdf_mem_free(peer_info);
3010 }
3011
3012 return;
3013}
3014
3015/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 * wma_stats_event_handler() - stats event handler
3017 * @handle: wma handle
3018 * @cmd_param_info: data from event
3019 * @len: length
3020 *
3021 * Return: 0 for success or error code
3022 */
3023int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
3024 uint32_t len)
3025{
3026 tp_wma_handle wma = (tp_wma_handle) handle;
3027 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
3028 wmi_stats_event_fixed_param *event;
3029 wmi_pdev_stats *pdev_stats;
3030 wmi_vdev_stats *vdev_stats;
3031 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303032 wmi_rssi_stats *rssi_stats;
3033 wmi_per_chain_rssi_stats *rssi_event;
3034 struct wma_txrx_node *node;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003035 uint8_t *temp;
3036 uint32_t i;
3037 uint32_t buf_len = 0;
3038 bool excess_data = false;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303039 wmi_congestion_stats *congestion_stats;
3040 tpAniSirGlobal mac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
3043 if (!param_buf) {
3044 WMA_LOGA("%s: Invalid stats event", __func__);
3045 return -EINVAL;
3046 }
3047 event = param_buf->fixed_param;
3048 temp = (uint8_t *) param_buf->data;
Abhinav Kumara03659c2017-12-28 15:18:07 +05303049 if ((event->num_pdev_stats + event->num_vdev_stats +
3050 event->num_peer_stats) > param_buf->num_data) {
3051 WMA_LOGE("%s: Invalid num_pdev_stats:%d or num_vdev_stats:%d or num_peer_stats:%d",
3052 __func__, event->num_pdev_stats, event->num_vdev_stats,
3053 event->num_peer_stats);
3054 return -EINVAL;
3055 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003057 do {
3058 if (event->num_pdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
3059 sizeof(*event)) / sizeof(*pdev_stats))) {
3060 excess_data = true;
3061 break;
3062 } else {
3063 buf_len += event->num_pdev_stats * sizeof(*pdev_stats);
3064 }
3065
3066 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
3067 sizeof(*event)) / sizeof(*vdev_stats))) {
3068 excess_data = true;
3069 break;
3070 } else {
3071 buf_len += event->num_vdev_stats * sizeof(*vdev_stats);
3072 }
3073
3074 if (event->num_peer_stats > ((WMI_SVC_MSG_MAX_SIZE -
3075 sizeof(*event)) / sizeof(*peer_stats))) {
3076 excess_data = true;
3077 break;
3078 } else {
3079 buf_len += event->num_peer_stats * sizeof(*peer_stats);
3080 }
3081
3082 rssi_event =
3083 (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
bingsf9047652017-08-31 08:05:54 +08003084 if (rssi_event) {
3085 if (rssi_event->num_per_chain_rssi_stats >
3086 ((WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) /
3087 sizeof(*rssi_event))) {
3088 excess_data = true;
3089 break;
3090 } else {
3091 buf_len += sizeof(*rssi_event) *
3092 rssi_event->num_per_chain_rssi_stats;
3093 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003094 }
3095 } while (0);
3096
3097 if (excess_data ||
Rakshith Suresh Patkar90517362018-05-25 14:09:10 +05303098 (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*event))) {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003099 WMA_LOGE("excess wmi buffer: stats pdev %d vdev %d peer %d",
3100 event->num_pdev_stats, event->num_vdev_stats,
3101 event->num_peer_stats);
3102 QDF_ASSERT(0);
3103 return -EINVAL;
3104 }
3105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003106 if (event->num_pdev_stats > 0) {
3107 for (i = 0; i < event->num_pdev_stats; i++) {
3108 pdev_stats = (wmi_pdev_stats *) temp;
3109 wma_update_pdev_stats(wma, pdev_stats);
3110 temp += sizeof(wmi_pdev_stats);
3111 }
3112 }
3113
3114 if (event->num_vdev_stats > 0) {
3115 for (i = 0; i < event->num_vdev_stats; i++) {
3116 vdev_stats = (wmi_vdev_stats *) temp;
3117 wma_update_vdev_stats(wma, vdev_stats);
3118 temp += sizeof(wmi_vdev_stats);
3119 }
3120 }
3121
3122 if (event->num_peer_stats > 0) {
Will Huanga9814592017-05-24 15:47:58 +08003123 if (wma->get_sta_peer_info == true) {
3124 wma_handle_sta_peer_info(event->num_peer_stats,
3125 (wmi_peer_stats *)temp,
3126 wma->peer_macaddr,
3127 wma->myaddr);
3128 } else {
3129 for (i = 0; i < event->num_peer_stats; i++) {
3130 peer_stats = (wmi_peer_stats *) temp;
3131 wma_update_peer_stats(wma, peer_stats);
3132 temp += sizeof(wmi_peer_stats);
3133 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134 }
3135 }
3136
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303137 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
3138 if (rssi_event) {
Abhinav Kumara03659c2017-12-28 15:18:07 +05303139 if (rssi_event->num_per_chain_rssi_stats >
3140 param_buf->num_rssi_stats) {
3141 WMA_LOGE("%s: Invalid num_per_chain_rssi_stats:%d",
3142 __func__, rssi_event->num_per_chain_rssi_stats);
3143 return -EINVAL;
3144 }
Himanshu Agarwalcd8a84a2016-07-21 14:59:50 +05303145 if (((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
3146 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) &&
3147 ((rssi_event->tlv_header & 0x0000FFFF) ==
3148 WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats))) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303149 if (rssi_event->num_per_chain_rssi_stats > 0) {
3150 temp = (uint8_t *) rssi_event;
3151 temp += sizeof(*rssi_event);
Dustin Brownc4a5ba22016-11-10 17:21:18 -08003152
3153 /* skip past struct array tlv header */
3154 temp += WMI_TLV_HDR_SIZE;
3155
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303156 for (i = 0;
3157 i < rssi_event->num_per_chain_rssi_stats;
3158 i++) {
3159 rssi_stats = (wmi_rssi_stats *)temp;
3160 wma_update_rssi_stats(wma, rssi_stats);
3161 temp += sizeof(wmi_rssi_stats);
3162 }
3163 }
3164 }
3165 }
3166
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303167 congestion_stats = (wmi_congestion_stats *) param_buf->congestion_stats;
3168 if (congestion_stats) {
3169 if (((congestion_stats->tlv_header & 0xFFFF0000) >> 16 ==
3170 WMITLV_TAG_STRUC_wmi_congestion_stats) &&
3171 ((congestion_stats->tlv_header & 0x0000FFFF) ==
3172 WMITLV_GET_STRUCT_TLVLEN(wmi_congestion_stats))) {
3173 mac = cds_get_context(QDF_MODULE_ID_PE);
3174 if (!mac) {
3175 WMA_LOGE("%s: Invalid mac", __func__);
3176 return -EINVAL;
3177 }
3178 if (!mac->sme.congestion_cb) {
3179 WMA_LOGE("%s: Callback not registered",
3180 __func__);
3181 return -EINVAL;
3182 }
3183 WMA_LOGI("%s: congestion %d", __func__,
3184 congestion_stats->congestion);
3185 mac->sme.congestion_cb(mac->hHdd,
3186 congestion_stats->congestion,
3187 congestion_stats->vdev_id);
3188 }
3189 }
3190
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303191 for (i = 0; i < wma->max_bssid; i++) {
3192 node = &wma->interfaces[i];
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003193 if (node->fw_stats_set & FW_PEER_STATS_SET)
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303194 wma_post_stats(wma, node);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303195 }
3196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 return 0;
3198}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07003199#endif /* QCA_SUPPORT_CP_STATS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200
3201/**
Will Huanga9814592017-05-24 15:47:58 +08003202 * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct
3203 * @wma: wma interface
3204 * @stats_info: WMI peer info pointer
3205 * @peer_info: SIR peer info pointer
3206 *
3207 * This function will fill SIR peer info from WMI peer info struct
3208 *
3209 * Return: None
3210 */
3211static void wma_fill_peer_info(tp_wma_handle wma,
3212 wmi_peer_stats_info *stats_info,
3213 struct sir_peer_info_ext *peer_info)
3214{
3215 peer_info->tx_packets = stats_info->tx_packets.low_32;
3216 peer_info->tx_bytes = stats_info->tx_bytes.high_32;
3217 peer_info->tx_bytes <<= 32;
3218 peer_info->tx_bytes += stats_info->tx_bytes.low_32;
3219 peer_info->rx_packets = stats_info->rx_packets.low_32;
3220 peer_info->rx_bytes = stats_info->rx_bytes.high_32;
3221 peer_info->rx_bytes <<= 32;
3222 peer_info->rx_bytes += stats_info->rx_bytes.low_32;
3223 peer_info->tx_retries = stats_info->tx_retries;
3224 peer_info->tx_failed = stats_info->tx_failed;
3225 peer_info->rssi = stats_info->peer_rssi;
3226 peer_info->tx_rate = stats_info->last_tx_bitrate_kbps;
3227 peer_info->tx_rate_code = stats_info->last_tx_rate_code;
3228 peer_info->rx_rate = stats_info->last_rx_bitrate_kbps;
3229 peer_info->rx_rate_code = stats_info->last_rx_rate_code;
3230}
3231
3232/**
3233 * wma_peer_info_ext_rsp() - process peer ext info ext
3234 * @handle: wma interface
3235 * @buf: wmi event buf pointer
3236 *
3237 * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME
3238 *
3239 * Return: 0 on success, error code otherwise
3240 */
3241static QDF_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf)
3242{
3243 wmi_peer_stats_info_event_fixed_param *event;
3244 wmi_peer_stats_info *stats_info;
3245 struct sir_peer_info_ext_resp *resp;
3246 struct sir_peer_info_ext *peer_info;
3247 struct scheduler_msg sme_msg = {0};
3248 int i, j = 0;
3249 QDF_STATUS qdf_status;
3250
3251 event = (wmi_peer_stats_info_event_fixed_param *)buf;
3252 stats_info = (wmi_peer_stats_info *)(buf +
3253 sizeof(wmi_peer_stats_info_event_fixed_param));
3254
3255 if (wma->get_one_peer_info) {
3256 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3257 sizeof(resp->info[0]));
3258 if (!resp) {
3259 WMA_LOGE(FL("resp allocation failed."));
3260 return QDF_STATUS_E_NOMEM;
3261 }
3262 resp->count = 0;
3263 peer_info = &resp->info[0];
3264 for (i = 0; i < event->num_peers; i++) {
3265 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3266 peer_info->peer_macaddr.bytes);
3267
3268 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3269 wma->peer_macaddr.bytes,
3270 QDF_MAC_ADDR_SIZE)) {
3271 wma_fill_peer_info(wma, stats_info, peer_info);
3272 resp->count++;
3273 break;
3274 }
3275
3276 stats_info = stats_info + 1;
3277 }
3278 } else {
3279 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3280 event->num_peers * sizeof(resp->info[0]));
3281 if (!resp) {
3282 WMA_LOGE(FL("resp allocation failed."));
3283 return QDF_STATUS_E_NOMEM;
3284 }
3285 resp->count = event->num_peers;
3286 for (i = 0; i < event->num_peers; i++) {
3287 peer_info = &resp->info[j];
3288 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3289 peer_info->peer_macaddr.bytes);
3290
3291 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3292 wma->myaddr, QDF_MAC_ADDR_SIZE)) {
3293 resp->count = resp->count - 1;
3294 } else {
3295 wma_fill_peer_info(wma, stats_info, peer_info);
3296 j++;
3297 }
3298 stats_info = stats_info + 1;
3299 }
3300 }
3301
3302 sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND;
3303 sme_msg.bodyptr = resp;
3304 sme_msg.bodyval = 0;
3305
3306 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3307 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3308 WMA_LOGE("%s: Fail to post get peer info msg", __func__);
3309 qdf_mem_free(resp);
3310 }
3311
3312 return qdf_status;
3313}
3314
3315/**
3316 * dump_peer_stats_info() - dump wmi peer info struct
3317 * @event: wmi peer info fixed param pointer
3318 * @peer_stats: wmi peer stats info pointer
3319 *
3320 * This function will dump wmi peer info struct
3321 *
3322 * Return: None
3323 */
3324static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event,
3325 wmi_peer_stats_info *peer_stats)
3326{
3327 int i;
3328 wmi_peer_stats_info *stats = peer_stats;
3329 u_int8_t mac[6];
3330
3331 WMA_LOGI("%s vdev_id %d, num_peers %d more_data %d",
3332 __func__, event->vdev_id,
3333 event->num_peers, event->more_data);
3334
3335 for (i = 0; i < event->num_peers; i++) {
3336 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
3337 WMA_LOGI("%s mac %pM", __func__, mac);
3338 WMA_LOGI("%s tx_bytes %d %d tx_packets %d %d",
3339 __func__,
3340 stats->tx_bytes.low_32,
3341 stats->tx_bytes.high_32,
3342 stats->tx_packets.low_32,
3343 stats->tx_packets.high_32);
3344 WMA_LOGI("%s rx_bytes %d %d rx_packets %d %d",
3345 __func__,
3346 stats->rx_bytes.low_32,
3347 stats->rx_bytes.high_32,
3348 stats->rx_packets.low_32,
3349 stats->rx_packets.high_32);
3350 WMA_LOGI("%s tx_retries %d tx_failed %d",
3351 __func__, stats->tx_retries, stats->tx_failed);
3352 WMA_LOGI("%s tx_rate_code %x rx_rate_code %x",
3353 __func__,
3354 stats->last_tx_rate_code,
3355 stats->last_rx_rate_code);
3356 WMA_LOGI("%s tx_rate %x rx_rate %x",
3357 __func__,
3358 stats->last_tx_bitrate_kbps,
3359 stats->last_rx_bitrate_kbps);
3360 WMA_LOGI("%s peer_rssi %d", __func__, stats->peer_rssi);
3361 stats++;
3362 }
3363}
3364
3365int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
3366 u_int32_t len)
3367{
3368 tp_wma_handle wma = (tp_wma_handle) handle;
3369 WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
3370 wmi_peer_stats_info_event_fixed_param *event;
3371 u_int32_t buf_size;
3372 u_int8_t *buf;
3373
3374 param_buf =
3375 (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info;
3376 if (!param_buf) {
3377 WMA_LOGA("%s: Invalid stats event", __func__);
3378 return -EINVAL;
3379 }
3380
3381 WMA_LOGI("%s Recv WMI_PEER_STATS_INFO_EVENTID", __func__);
3382 event = param_buf->fixed_param;
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003383 if (event->num_peers >
Abhinav Kumara03659c2017-12-28 15:18:07 +05303384 ((WMI_SVC_MSG_MAX_SIZE -
3385 sizeof(wmi_peer_stats_info_event_fixed_param))/
3386 sizeof(wmi_peer_stats_info)) || event->num_peers >
3387 param_buf->num_peer_stats_info) {
3388 WMA_LOGE("Excess num of peers from fw: %d, num_peer_stats_info:%d",
3389 event->num_peers, param_buf->num_peer_stats_info);
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003390 return -EINVAL;
3391 }
Will Huanga9814592017-05-24 15:47:58 +08003392 buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) +
3393 sizeof(wmi_peer_stats_info) * event->num_peers;
3394 buf = qdf_mem_malloc(buf_size);
3395 if (!buf) {
3396 WMA_LOGE("%s: Failed alloc memory for buf", __func__);
3397 return -ENOMEM;
3398 }
3399
3400 qdf_mem_copy(buf, param_buf->fixed_param,
3401 sizeof(wmi_peer_stats_info_event_fixed_param));
3402 qdf_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)),
3403 param_buf->peer_stats_info,
3404 sizeof(wmi_peer_stats_info) * event->num_peers);
3405 WMA_LOGI("%s dump peer stats info", __func__);
3406 dump_peer_stats_info(event, param_buf->peer_stats_info);
3407
3408 wma_peer_info_ext_rsp(wma, buf);
3409 qdf_mem_free(buf);
3410
3411 return 0;
3412}
3413
3414/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 * wma_send_link_speed() - send link speed to SME
3416 * @link_speed: link speed
3417 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303418 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303420QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303422 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303423 tpAniSirGlobal mac_ctx;
3424 tSirLinkSpeedInfo *ls_ind;
3425
3426 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
3427 if (!mac_ctx) {
3428 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
3429 return QDF_STATUS_E_INVAL;
3430 }
3431
3432 ls_ind = (tSirLinkSpeedInfo *)qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003433 if (!ls_ind) {
3434 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303435 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 } else {
3437 ls_ind->estLinkSpeed = link_speed;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303438 if (mac_ctx->sme.pLinkSpeedIndCb)
3439 mac_ctx->sme.pLinkSpeedIndCb(ls_ind,
3440 mac_ctx->sme.pLinkSpeedCbContext);
3441 else
3442 WMA_LOGD("%s: pLinkSpeedIndCb is null", __func__);
3443 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003445 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303446 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447}
3448
3449/**
3450 * wma_link_speed_event_handler() - link speed event handler
3451 * @handle: wma handle
3452 * @cmd_param_info: event data
3453 * @len: length
3454 *
3455 * Return: 0 for success or error code
3456 */
3457int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
3458 uint32_t len)
3459{
3460 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
3461 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303462 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003464 param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)
3465 cmd_param_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003466 if (!param_buf) {
3467 WMA_LOGE("%s: Invalid linkspeed event", __func__);
3468 return -EINVAL;
3469 }
3470 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303471 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003472 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474 return 0;
3475}
3476
3477/**
3478 * wma_wni_cfg_dnld() - cfg download request
3479 * @handle: wma handle
3480 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303481 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303483QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303485 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303486 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003487
3488 WMA_LOGD("%s: Enter", __func__);
3489
3490 if (NULL == mac) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003491 WMA_LOGE("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303492 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303493 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003494 }
3495
3496 process_cfg_download_req(mac);
3497
3498 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303499 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500}
3501
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303502#define BIG_ENDIAN_MAX_DEBUG_BUF 500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503/**
3504 * wma_unified_debug_print_event_handler() - debug print event handler
3505 * @handle: wma handle
3506 * @datap: data pointer
3507 * @len: length
3508 *
3509 * Return: 0 for success or error code
3510 */
3511int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
3512 uint32_t len)
3513{
3514 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
3515 uint8_t *data;
3516 uint32_t datalen;
3517
3518 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303519 if (!param_buf || !param_buf->data) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 WMA_LOGE("Get NULL point message from FW");
3521 return -ENOMEM;
3522 }
3523 data = param_buf->data;
3524 datalen = param_buf->num_data;
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303525 if (datalen > WMI_SVC_MSG_MAX_SIZE) {
3526 WMA_LOGE("Received data len %d exceeds max value %d",
3527 datalen, WMI_SVC_MSG_MAX_SIZE);
3528 return QDF_STATUS_E_FAILURE;
3529 }
3530 data[datalen - 1] = '\0';
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531
3532#ifdef BIG_ENDIAN_HOST
3533 {
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303534 if (datalen >= BIG_ENDIAN_MAX_DEBUG_BUF) {
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303535 WMA_LOGE("%s Invalid data len %d, limiting to max",
3536 __func__, datalen);
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303537 datalen = BIG_ENDIAN_MAX_DEBUG_BUF - 1;
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303538 }
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003539 char dbgbuf[BIG_ENDIAN_MAX_DEBUG_BUF] = { 0 };
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003540
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003541 memcpy(dbgbuf, data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003542 SWAPME(dbgbuf, datalen);
3543 WMA_LOGD("FIRMWARE:%s", dbgbuf);
3544 return 0;
3545 }
3546#else
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003547 WMA_LOGD("FIRMWARE:%s", data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548 return 0;
3549#endif /* BIG_ENDIAN_HOST */
3550}
3551
3552/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003553 * wma_is_sap_active() - check sap is active or not
3554 * @handle: wma handle
3555 *
3556 * Return: true/false
3557 */
3558bool wma_is_sap_active(tp_wma_handle wma_handle)
3559{
3560 int i;
3561
3562 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303563 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003564 continue;
3565 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3566 wma_handle->interfaces[i].sub_type == 0)
3567 return true;
3568 }
3569 return false;
3570}
3571
3572/**
3573 * wma_is_p2p_go_active() - check p2p go is active or not
3574 * @handle: wma handle
3575 *
3576 * Return: true/false
3577 */
3578bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
3579{
3580 int i;
3581
3582 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303583 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 continue;
3585 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3586 wma_handle->interfaces[i].sub_type ==
3587 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
3588 return true;
3589 }
3590 return false;
3591}
3592
3593/**
3594 * wma_is_p2p_cli_active() - check p2p cli is active or not
3595 * @handle: wma handle
3596 *
3597 * Return: true/false
3598 */
3599bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
3600{
3601 int i;
3602
3603 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303604 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605 continue;
3606 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3607 wma_handle->interfaces[i].sub_type ==
3608 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
3609 return true;
3610 }
3611 return false;
3612}
3613
3614/**
3615 * wma_is_sta_active() - check sta is active or not
3616 * @handle: wma handle
3617 *
3618 * Return: true/false
3619 */
3620bool wma_is_sta_active(tp_wma_handle wma_handle)
3621{
3622 int i;
3623
3624 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303625 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 continue;
3627 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3628 wma_handle->interfaces[i].sub_type == 0)
3629 return true;
3630 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
3631 return true;
3632 }
3633 return false;
3634}
3635
3636/**
3637 * wma_peer_phymode() - get phymode
3638 * @nw_type: nw type
3639 * @sta_type: sta type
3640 * @is_ht: is ht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003641 * @ch_width: supported channel width
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 * @is_vht: is vht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003643 * @is_he: is HE supported
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 *
3645 * Return: WLAN_PHY_MODE
3646 */
3647WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
3648 uint8_t is_ht, uint8_t ch_width,
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003649 uint8_t is_vht, bool is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650{
3651 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
3652
3653 switch (nw_type) {
3654 case eSIR_11B_NW_TYPE:
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003655#ifdef FEATURE_WLAN_TDLS
3656 if (STA_ENTRY_TDLS_PEER == sta_type) {
3657 if (is_vht) {
3658 if (CH_WIDTH_80MHZ == ch_width)
3659 phymode = MODE_11AC_VHT80;
3660 else
3661 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3662 MODE_11AC_VHT40 :
3663 MODE_11AC_VHT20;
3664 } else if (is_ht) {
3665 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3666 MODE_11NG_HT40 : MODE_11NG_HT20;
3667 } else
3668 phymode = MODE_11B;
3669 } else
3670#endif /* FEATURE_WLAN_TDLS */
3671 {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 phymode = MODE_11B;
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003673 if (is_ht || is_vht || is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674 WMA_LOGE("HT/VHT is enabled with 11B NW type");
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003675 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003676 break;
3677 case eSIR_11G_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003678 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 phymode = MODE_11G;
3680 break;
3681 }
3682 if (CH_WIDTH_40MHZ < ch_width)
3683 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
3684 if (ch_width)
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003685 phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ?
3686 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687 else
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003688 phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ?
3689 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 break;
3691 case eSIR_11A_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003692 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003693 phymode = MODE_11A;
3694 break;
3695 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003696 if (is_he) {
3697 if (ch_width == CH_WIDTH_160MHZ)
3698 phymode = MODE_11AX_HE160;
3699 else if (ch_width == CH_WIDTH_80P80MHZ)
3700 phymode = MODE_11AX_HE80_80;
3701 else if (ch_width == CH_WIDTH_80MHZ)
3702 phymode = MODE_11AX_HE80;
3703 else
3704 phymode = (ch_width) ?
3705 MODE_11AX_HE40 : MODE_11AX_HE20;
3706 } else if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 if (ch_width == CH_WIDTH_160MHZ)
3708 phymode = MODE_11AC_VHT160;
3709 else if (ch_width == CH_WIDTH_80P80MHZ)
3710 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07003711 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003712 phymode = MODE_11AC_VHT80;
3713 else
3714 phymode = (ch_width) ?
3715 MODE_11AC_VHT40 : MODE_11AC_VHT20;
3716 } else
3717 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
3718 break;
3719 default:
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003720 WMA_LOGE("%s: Invalid nw type %d", __func__, nw_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003721 break;
3722 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003723 WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"),
3724 nw_type, is_ht, ch_width, is_vht, is_he, phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003725
3726 return phymode;
3727}
3728
3729/**
3730 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
3731 * @wma_handle: wma handle
3732 * @vdev_id: vdev id
3733 * @value: value
3734 *
3735 * Return: 0 for success or return error
3736 */
3737int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
3738 uint8_t vdev_id, uint32_t value)
3739{
3740 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003741 struct cdp_vdev *vdev;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303742 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3743
3744 if (!soc) {
3745 WMA_LOGE("%s:SOC context is NULL", __func__);
3746 return -EINVAL;
3747 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748
3749 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3750 if (!vdev) {
3751 WMA_LOGE("%s:Invalid vdev handle", __func__);
3752 return -EINVAL;
3753 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303754 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003755 req.stats_type_reset_mask = value;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003756 cdp_fw_stats_get(soc, vdev, &req, false, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757
3758 return 0;
3759}
3760
3761#ifdef HELIUMPLUS
Jeff Johnson560dc562017-03-17 15:19:31 -07003762#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003763 ((_mask) = 1 << (_rate_info ## _V2))
3764#else /* !HELIUMPLUS */
Jeff Johnson560dc562017-03-17 15:19:31 -07003765#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003766 ((_mask) = 1 << (_rate_info))
3767#endif
3768
Nirav Shah93e789e2016-04-14 19:47:43 +05303769#ifdef HELIUMPLUS
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003770static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303771{
3772 if (value > (HTT_DBG_NUM_STATS + 1) ||
3773 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
3774 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
3775 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3776 WMA_LOGE("%s: Not supported", __func__);
3777 return false;
3778 }
3779 return true;
3780}
3781#else
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003782static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303783{
3784 if (value > (HTT_DBG_NUM_STATS + 1) ||
3785 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
3786 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
3787 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3788 WMA_LOGE("%s: Not supported", __func__);
3789 return false;
3790 }
3791 return true;
3792}
3793#endif
3794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003795/**
3796 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
3797 * @wma_handle: wma handle
3798 * @vdev_id: vdev id
3799 * @value: value
3800 *
3801 * Return: 0 for success or return error
3802 */
3803int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
3804 uint8_t vdev_id, uint32_t value)
3805{
3806 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003807 struct cdp_vdev *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808 uint32_t l_up_mask;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303809 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3810
3811 if (!soc) {
3812 WMA_LOGE("%s:SOC context is NULL", __func__);
3813 return -EINVAL;
3814 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815
3816 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3817 if (!vdev) {
3818 WMA_LOGE("%s:Invalid vdev handle", __func__);
3819 return -EINVAL;
3820 }
Nirav Shah93e789e2016-04-14 19:47:43 +05303821
3822 if (wma_is_valid_fw_stats_cmd(value) == false)
3823 return -EINVAL;
3824
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303825 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 req.print.verbose = 1;
3827
Nirav Shah93e789e2016-04-14 19:47:43 +05303828 /* TODO: Need to check how to avoid mem leak*/
3829 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830 req.stats_type_upload_mask = l_up_mask;
3831
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003832 cdp_fw_stats_get(soc, vdev, &req, false, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003833
3834 return 0;
3835}
3836
Naveen Rawatfa2a1002018-05-17 16:06:37 -07003837#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 * wma_get_stats_rsp_buf() - fill get stats response buffer
3840 * @get_stats_param: get stats parameters
3841 *
3842 * Return: stats response buffer
3843 */
3844static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
3845 (tAniGetPEStatsReq *get_stats_param)
3846{
3847 tAniGetPEStatsRsp *stats_rsp_params;
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003848 uint32_t len, temp_mask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849
3850 len = sizeof(tAniGetPEStatsRsp);
3851 temp_mask = get_stats_param->statsMask;
3852
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003853 if (temp_mask & (1 << eCsrSummaryStats))
3854 len += sizeof(tCsrSummaryStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003856 if (temp_mask & (1 << eCsrGlobalClassAStats))
3857 len += sizeof(tCsrGlobalClassAStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003858
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003859 if (temp_mask & (1 << eCsrGlobalClassDStats))
3860 len += sizeof(tCsrGlobalClassDStatsInfo);
3861
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003862 if (temp_mask & (1 << csr_per_chain_rssi_stats))
3863 len += sizeof(struct csr_per_chain_rssi_stats_info);
3864
3865 stats_rsp_params = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 if (!stats_rsp_params) {
3867 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303868 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869 return NULL;
3870 }
3871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 stats_rsp_params->staId = get_stats_param->staId;
3873 stats_rsp_params->statsMask = get_stats_param->statsMask;
3874 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
3875 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303876 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 return stats_rsp_params;
3878}
3879
3880/**
3881 * wma_get_stats_req() - get stats request
3882 * @handle: wma handle
3883 * @get_stats_param: stats params
3884 *
3885 * Return: none
3886 */
3887void wma_get_stats_req(WMA_HANDLE handle,
3888 tAniGetPEStatsReq *get_stats_param)
3889{
3890 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3891 struct wma_txrx_node *node;
Dustin Brown35619492017-10-03 15:16:12 -07003892 struct stats_request_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05303894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895
3896 WMA_LOGD("%s: Enter", __func__);
3897 node = &wma_handle->interfaces[get_stats_param->sessionId];
3898 if (node->stats_rsp) {
3899 pGetPEStatsRspParams = node->stats_rsp;
3900 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
3901 pGetPEStatsRspParams->statsMask ==
3902 get_stats_param->statsMask) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003903 WMA_LOGD("Stats for staId %d with stats mask %d is pending.. ignore new request",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003904 get_stats_param->staId,
3905 get_stats_param->statsMask);
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303906 pGetPEStatsRspParams =
3907 wma_get_stats_rsp_buf(get_stats_param);
3908 if (!pGetPEStatsRspParams) {
3909 WMA_LOGE("failed to allocate memory for stats response");
3910 goto end;
3911 }
3912 goto req_pending;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003913 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303914 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 node->stats_rsp = NULL;
3916 node->fw_stats_set = 0;
3917 }
3918 }
3919
3920 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
3921 if (!pGetPEStatsRspParams)
3922 goto end;
3923
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924 node->fw_stats_set = 0;
Naveen Rawat3c49d192017-03-02 18:43:16 -08003925 if (node->stats_rsp) {
Jeff Johnsonadba3962017-09-18 08:12:35 -07003926 WMA_LOGD(FL("stats_rsp is not null, prev_value: %pK"),
Naveen Rawat3c49d192017-03-02 18:43:16 -08003927 node->stats_rsp);
3928 qdf_mem_free(node->stats_rsp);
3929 node->stats_rsp = NULL;
3930 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003931 node->stats_rsp = pGetPEStatsRspParams;
Will Huanga9814592017-05-24 15:47:58 +08003932 wma_handle->get_sta_peer_info = false;
Jeff Johnsonadba3962017-09-18 08:12:35 -07003933 WMA_LOGD("stats_rsp allocated: %pK, sta_id: %d, mask: %d, vdev_id: %d",
Naveen Rawat3c49d192017-03-02 18:43:16 -08003934 node->stats_rsp, node->stats_rsp->staId,
3935 node->stats_rsp->statsMask, get_stats_param->sessionId);
Govind Singh4863da42016-03-08 11:45:00 +05303936
Dustin Brown35619492017-10-03 15:16:12 -07003937 cmd.vdev_id = get_stats_param->sessionId;
3938 cmd.stats_id = get_stats_param->statsMask;
3939 if (wmi_unified_stats_request_send(wma_handle->wmi_handle,
3940 node->bssid,
3941 &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
3943 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944 goto failed;
3945 }
3946
3947 goto end;
3948failed:
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303949 node->stats_rsp = NULL;
3950req_pending:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303951 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003952 /* send response to UMAC */
3953 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
3954 0);
3955end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303956 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 WMA_LOGD("%s: Exit", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07003959#endif /* QCA_SUPPORT_CP_STATS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960
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}
Wen Gong99768902018-04-25 12:07:49 +08004260#ifdef FEATURE_FW_LOG_PARSING
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004261/**
Govind Singhd76a5b02016-03-08 15:12:14 +05304262 * wma_config_debug_module_cmd - set debug log config
4263 * @wmi_handle: wmi layer handle
4264 * @param: debug log parameter
4265 * @val: debug log value
4266 * @module_id_bitmap: debug module id bitmap
4267 * @bitmap_len: debug module bitmap length
4268 *
4269 * Return: QDF_STATUS_SUCCESS for success or error code
4270 */
4271QDF_STATUS
4272wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
4273 A_UINT32 val, A_UINT32 *module_id_bitmap,
4274 A_UINT32 bitmap_len)
4275{
4276 struct dbglog_params dbg_param;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004277
Govind Singhd76a5b02016-03-08 15:12:14 +05304278 dbg_param.param = param;
4279 dbg_param.val = val;
4280 dbg_param.module_id_bitmap = module_id_bitmap;
4281 dbg_param.bitmap_len = bitmap_len;
4282
4283 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
4284}
Wen Gong99768902018-04-25 12:07:49 +08004285#endif
Peng Xu8fdaa492016-06-22 10:20:47 -07004286
4287/**
4288 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
4289 *
4290 * This function checks if driver is capable of p2p listen offload
4291 * true: capable of p2p offload
4292 * false: not capable
4293 *
4294 * Return: true - capable, false - not capable
4295 */
4296bool wma_is_p2p_lo_capable(void)
4297{
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304298 return wma_is_service_enabled(wmi_service_p2p_listen_offload_support);
Peng Xu8fdaa492016-06-22 10:20:47 -07004299}
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004300
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004301bool wma_capability_enhanced_mcast_filter(void)
4302{
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304303 return wma_is_service_enabled(wmi_service_enhanced_mcast_filter);
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004304}
4305
4306
Mukul Sharmaf9047232017-03-02 16:58:56 +05304307bool wma_is_vdev_up(uint8_t vdev_id)
4308{
4309 struct wlan_objmgr_vdev *vdev;
4310 tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
4311 enum wlan_vdev_state state = WLAN_VDEV_S_INIT;
4312
4313 if (!wma) {
4314 WMA_LOGE("%s: WMA context is invald!", __func__);
4315 return false;
4316 }
4317
4318 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
4319 WLAN_LEGACY_WMA_ID);
4320 if (vdev) {
4321 wlan_vdev_obj_lock(vdev);
4322 state = wlan_vdev_mlme_get_state(vdev);
4323 wlan_vdev_obj_unlock(vdev);
4324 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4325 }
Mukul Sharmaf9047232017-03-02 16:58:56 +05304326 return (state == WLAN_VDEV_S_RUN) ? true : false;
4327}
4328
Dustin Brownec2c92e2017-07-26 11:13:49 -07004329void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004330{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004331 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4332
4333 cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4334 qdf_wake_lock_timeout_acquire(wl, msec);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004335 qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004336}
4337
Dustin Brownec2c92e2017-07-26 11:13:49 -07004338void wma_release_wakelock(qdf_wake_lock_t *wl)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004339{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004340 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4341
4342 qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004343 qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004344}
4345
Dustin Brownd5f12942017-03-10 11:06:25 -08004346QDF_STATUS
4347wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
4348{
4349 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004350 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
Dustin Brownd5f12942017-03-10 11:06:25 -08004351
Dustin Brownec2c92e2017-07-26 11:13:49 -07004352 wma_acquire_wakelock(&vdev->vdev_start_wakelock,
4353 WMA_VDEV_START_REQUEST_TIMEOUT);
Dustin Brownd5f12942017-03-10 11:06:25 -08004354 status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
4355 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004356 wma_release_wakelock(&vdev->vdev_start_wakelock);
Dustin Brownd5f12942017-03-10 11:06:25 -08004357
4358 return status;
4359}
4360
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004361QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4362{
4363 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004364 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004365
Dustin Brownec2c92e2017-07-26 11:13:49 -07004366 wma_acquire_wakelock(&vdev->vdev_stop_wakelock,
4367 WMA_VDEV_STOP_REQUEST_TIMEOUT);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004368 status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id);
4369 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004370 wma_release_wakelock(&vdev->vdev_stop_wakelock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004371
4372 return status;
4373}
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004374
Rajeev Kumar Sirasanagandla996e5292016-11-22 21:20:33 +05304375QDF_STATUS wma_get_rcpi_req(WMA_HANDLE handle,
4376 struct sme_rcpi_req *rcpi_request)
4377{
4378 tp_wma_handle wma_handle = (tp_wma_handle) handle;
4379 struct rcpi_req cmd = {0};
4380 struct wma_txrx_node *iface;
4381 struct sme_rcpi_req *node_rcpi_req;
4382
4383 WMA_LOGD("%s: Enter", __func__);
4384 iface = &wma_handle->interfaces[rcpi_request->session_id];
4385 /* command is in progress */
4386 if (iface->rcpi_req != NULL) {
4387 WMA_LOGE("%s : previous rcpi request is pending", __func__);
4388 return QDF_STATUS_SUCCESS;
4389 }
4390
4391 node_rcpi_req = qdf_mem_malloc(sizeof(*node_rcpi_req));
4392 if (!node_rcpi_req) {
4393 WMA_LOGE("Failed to allocate memory for rcpi_request");
4394 return QDF_STATUS_E_NOMEM;
4395 }
4396
4397 *node_rcpi_req = *rcpi_request;
4398 iface->rcpi_req = node_rcpi_req;
4399
4400 cmd.vdev_id = rcpi_request->session_id;
4401 qdf_mem_copy(cmd.mac_addr, &rcpi_request->mac_addr, QDF_MAC_ADDR_SIZE);
Tushnim Bhattacharyya0725f1a2018-03-28 13:01:45 -07004402 cmd.measurement_type = rcpi_request->measurement_type;
Rajeev Kumar Sirasanagandla996e5292016-11-22 21:20:33 +05304403
4404 if (wmi_unified_send_request_get_rcpi_cmd(wma_handle->wmi_handle,
4405 &cmd)) {
4406 WMA_LOGE("%s: Failed to send WMI_REQUEST_RCPI_CMDID",
4407 __func__);
4408 iface->rcpi_req = NULL;
4409 qdf_mem_free(node_rcpi_req);
4410 return QDF_STATUS_E_FAILURE;
4411 }
4412
4413 WMA_LOGD("%s: Exit", __func__);
4414
4415 return QDF_STATUS_SUCCESS;
4416}
4417
4418int wma_rcpi_event_handler(void *handle, uint8_t *cmd_param_info,
4419 uint32_t len)
4420{
4421 struct rcpi_res res = {0};
4422 struct sme_rcpi_req *rcpi_req;
4423 struct qdf_mac_addr qdf_mac;
4424 struct wma_txrx_node *iface;
4425 QDF_STATUS status = QDF_STATUS_SUCCESS;
4426 tp_wma_handle wma_handle = (tp_wma_handle)handle;
4427
4428 status = wmi_extract_rcpi_response_event(wma_handle->wmi_handle,
4429 cmd_param_info, &res);
4430 if (status == QDF_STATUS_E_INVAL)
4431 return -EINVAL;
4432
4433 iface = &wma_handle->interfaces[res.vdev_id];
4434 if (!iface->rcpi_req) {
4435 WMI_LOGE("rcpi_req buffer not available");
4436 return 0;
4437 }
4438
4439 rcpi_req = iface->rcpi_req;
4440 if (!rcpi_req->rcpi_callback) {
4441 iface->rcpi_req = NULL;
4442 qdf_mem_free(rcpi_req);
4443 return 0;
4444 }
4445
4446 if ((res.measurement_type == RCPI_MEASUREMENT_TYPE_INVALID) ||
4447 (res.vdev_id != rcpi_req->session_id) ||
4448 (res.measurement_type != rcpi_req->measurement_type) ||
4449 (qdf_mem_cmp(res.mac_addr, &rcpi_req->mac_addr,
4450 QDF_MAC_ADDR_SIZE))) {
4451 WMI_LOGE("invalid rcpi_response");
4452 iface->rcpi_req = NULL;
4453 qdf_mem_free(rcpi_req);
4454 return 0;
4455 }
4456
4457 qdf_mem_copy(&qdf_mac, res.mac_addr, QDF_MAC_ADDR_SIZE);
4458 (rcpi_req->rcpi_callback)(rcpi_req->rcpi_context, qdf_mac,
4459 res.rcpi_value, status);
4460 iface->rcpi_req = NULL;
4461 qdf_mem_free(rcpi_req);
4462
4463 return 0;
4464}
4465
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304466bool wma_is_service_enabled(uint32_t service_type)
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004467{
4468 tp_wma_handle wma;
Srinivas Girigowda4d65ebe2017-10-13 21:41:42 -07004469
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004470 wma = cds_get_context(QDF_MODULE_ID_WMA);
4471 if (!wma) {
4472 WMA_LOGE("%s: Invalid WMA handle", __func__);
4473 return false;
4474 }
4475
Yun Park01a45f72018-01-04 15:30:59 -08004476 if (service_type >= WMI_MAX_SERVICE) {
4477 WMA_LOGE("%s: Invalid service type %d", __func__, service_type);
4478 return false;
4479 }
4480
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304481 return wmi_service_enabled(wma->wmi_handle, service_type);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004482}
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004483
Dustin Brownec2c92e2017-07-26 11:13:49 -07004484QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
4485 struct vdev_up_params *params,
4486 uint8_t bssid[IEEE80211_ADDR_LEN])
4487{
4488 QDF_STATUS status;
4489 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
4490
Varun Reddy Yeturu5303e082017-10-24 14:20:00 -07004491 if (wma_is_vdev_up(params->vdev_id)) {
4492 WMA_LOGD("vdev %d is already up for bssid %pM. Do not send",
4493 params->vdev_id, bssid);
4494 return QDF_STATUS_SUCCESS;
4495 }
Dustin Brownec2c92e2017-07-26 11:13:49 -07004496 status = wmi_unified_vdev_up_send(wma->wmi_handle, bssid, params);
4497 wma_release_wakelock(&vdev->vdev_start_wakelock);
4498
4499 return status;
4500}
4501
4502QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4503{
4504 QDF_STATUS status;
4505 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
4506
Tushnim Bhattacharyyaeb622b02018-05-07 13:50:51 -07004507 wma->interfaces[vdev_id].roaming_in_progress = false;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004508 status = wmi_unified_vdev_down_send(wma->wmi_handle, vdev_id);
4509 wma_release_wakelock(&vdev->vdev_start_wakelock);
4510
4511 return status;
4512}
4513
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004514tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
4515{
4516 switch (type) {
4517 case WMI_PEER_TYPE_DEFAULT:
4518 return WIFI_PEER_STA;
4519 case WMI_PEER_TYPE_BSS:
4520 return WIFI_PEER_AP;
4521 case WMI_PEER_TYPE_TDLS:
4522 return WIFI_PEER_TDLS;
4523 case WMI_PEER_TYPE_NAN_DATA:
4524 return WIFI_PEER_NAN;
4525 default:
4526 WMA_LOGE("Cannot map wmi_peer_type %d to HAL peer type", type);
4527 return WIFI_PEER_INVALID;
4528 }
4529}
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304530
Nachiket Kukade8983cf62017-10-12 18:14:48 +05304531/**
4532 * wma_set_vc_mode_config() - set voltage corner mode config to FW.
4533 * @wma_handle: pointer to wma handle.
4534 * @vc_bitmap: value needs to set to firmware.
4535 *
4536 * At the time of driver startup, set operating voltage corner mode
4537 * for differenet phymode and bw configurations.
4538 *
4539 * Return: QDF_STATUS.
4540 */
4541QDF_STATUS wma_set_vc_mode_config(void *wma_handle,
4542 uint32_t vc_bitmap)
4543{
4544 int32_t ret;
4545 tp_wma_handle wma = (tp_wma_handle)wma_handle;
4546 struct pdev_params pdevparam;
4547
4548 pdevparam.param_id = WMI_PDEV_UPDATE_WDCVS_ALGO;
4549 pdevparam.param_value = vc_bitmap;
4550
4551 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
4552 &pdevparam,
4553 WMA_WILDCARD_PDEV_ID);
4554 if (ret) {
4555 WMA_LOGE("Fail to Set Voltage Corner config (0x%x)",
4556 vc_bitmap);
4557 return QDF_STATUS_E_FAILURE;
4558 }
4559
4560 WMA_LOGD("Successfully Set Voltage Corner config (0x%x)",
4561 vc_bitmap);
4562
4563 return QDF_STATUS_SUCCESS;
4564}
4565
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304566int wma_chip_power_save_failure_detected_handler(void *handle,
4567 uint8_t *cmd_param_info,
4568 uint32_t len)
4569{
4570 tp_wma_handle wma = (tp_wma_handle)handle;
4571 WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
4572 wmi_chip_power_save_failure_detected_fixed_param *event;
4573 struct chip_pwr_save_fail_detected_params pwr_save_fail_params;
4574 tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(
4575 QDF_MODULE_ID_PE);
4576 if (wma == NULL) {
4577 WMA_LOGE("%s: wma_handle is NULL", __func__);
4578 return -EINVAL;
4579 }
4580 if (!mac) {
4581 WMA_LOGE("%s: Invalid mac context", __func__);
4582 return -EINVAL;
4583 }
4584 if (!mac->sme.chip_power_save_fail_cb) {
4585 WMA_LOGE("%s: Callback not registered", __func__);
4586 return -EINVAL;
4587 }
4588
4589 param_buf =
4590 (WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
4591 cmd_param_info;
4592 if (!param_buf) {
4593 WMA_LOGE("%s: Invalid pwr_save_fail_params breached event",
4594 __func__);
4595 return -EINVAL;
4596 }
4597 event = param_buf->fixed_param;
4598 pwr_save_fail_params.failure_reason_code =
4599 event->power_save_failure_reason_code;
4600 pwr_save_fail_params.wake_lock_bitmap[0] =
4601 event->protocol_wake_lock_bitmap[0];
4602 pwr_save_fail_params.wake_lock_bitmap[1] =
4603 event->protocol_wake_lock_bitmap[1];
4604 pwr_save_fail_params.wake_lock_bitmap[2] =
4605 event->protocol_wake_lock_bitmap[2];
4606 pwr_save_fail_params.wake_lock_bitmap[3] =
4607 event->protocol_wake_lock_bitmap[3];
4608 mac->sme.chip_power_save_fail_cb(mac->hHdd,
4609 &pwr_save_fail_params);
4610
4611 WMA_LOGD("%s: Invoke HDD pwr_save_fail callback", __func__);
4612 return 0;
4613}