blob: c296d6e9ecbb7080ebb7b81456b30c55b6304d6b [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,
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530163 uint8_t *nss, uint16_t nss1_rate,
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800164 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) {
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530173 *nss = 1;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800174 return nss1_rate;
175 } else if (match_rate == nss1_srate) {
176 *is_sgi = true;
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530177 *nss = 1;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800178 return nss1_srate;
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530179 } else if (*nss == 2 && match_rate == nss2_rate)
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800180 return nss2_rate;
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530181 else if (*nss == 2 && match_rate == nss2_srate) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800182 *is_sgi = true;
183 return nss2_srate;
184 } else
185 return 0;
186}
187
Naveen Rawatfa2a1002018-05-17 16:06:37 -0700188uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530189 uint8_t *nss, uint8_t *mcsRateFlag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800190{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800191 uint8_t index = 0;
Arif Hussainb8fef842016-07-19 09:43:13 -0700192 uint16_t match_rate = 0;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800193 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800195 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530196 __func__, maxRate, rate_flags, *nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197
198 *mcsRateFlag = rate_flags;
Naveen Rawatea1564b2018-05-17 15:56:11 -0700199 *mcsRateFlag &= ~TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800200 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700201 if (rate_flags & TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800202 /* check for vht80 nss1/2 rate set */
203 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
204 vht_mcs_nss1[index].ht80_rate[0],
205 vht_mcs_nss1[index].ht80_rate[1],
206 vht_mcs_nss2[index].ht80_rate[0],
207 vht_mcs_nss2[index].ht80_rate[1]);
208 if (match_rate)
209 goto rate_found;
210 }
Naveen Rawatea1564b2018-05-17 15:56:11 -0700211 if ((rate_flags & TX_RATE_VHT40) |
212 (rate_flags & TX_RATE_VHT80)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800213 /* check for vht40 nss1/2 rate set */
214 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
215 vht_mcs_nss1[index].ht40_rate[0],
216 vht_mcs_nss1[index].ht40_rate[1],
217 vht_mcs_nss2[index].ht40_rate[0],
218 vht_mcs_nss2[index].ht40_rate[1]);
219 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700220 *mcsRateFlag &= ~TX_RATE_VHT80;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800221 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 }
223 }
Naveen Rawatea1564b2018-05-17 15:56:11 -0700224 if ((rate_flags & TX_RATE_VHT20) |
225 (rate_flags & TX_RATE_VHT40) |
226 (rate_flags & TX_RATE_VHT80)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800227 /* check for vht20 nss1/2 rate set */
228 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
229 vht_mcs_nss1[index].ht20_rate[0],
230 vht_mcs_nss1[index].ht20_rate[1],
231 vht_mcs_nss2[index].ht20_rate[0],
232 vht_mcs_nss2[index].ht20_rate[1]);
233 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700234 *mcsRateFlag &= ~(TX_RATE_VHT80 |
235 TX_RATE_VHT40);
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800236 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237 }
238 }
239 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800240 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700241 if (rate_flags & TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800242 /* check for ht40 nss1/2 rate set */
243 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
244 mcs_nss1[index].ht40_rate[0],
245 mcs_nss1[index].ht40_rate[1],
246 mcs_nss2[index].ht40_rate[0],
247 mcs_nss2[index].ht40_rate[1]);
248 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700249 *mcsRateFlag = TX_RATE_HT40;
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530250 if (*nss == 2)
Yeshwanth Sriram Guntukad18c7a22018-02-02 15:22:30 +0530251 index += MAX_HT_MCS_IDX;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800252 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 }
254 }
Naveen Rawatea1564b2018-05-17 15:56:11 -0700255 if ((rate_flags & TX_RATE_HT20) ||
256 (rate_flags & TX_RATE_HT40)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800257 /* check for ht20 nss1/2 rate set */
258 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
259 mcs_nss1[index].ht20_rate[0],
260 mcs_nss1[index].ht20_rate[1],
261 mcs_nss2[index].ht20_rate[0],
262 mcs_nss2[index].ht20_rate[1]);
263 if (match_rate) {
Naveen Rawatea1564b2018-05-17 15:56:11 -0700264 *mcsRateFlag = TX_RATE_HT20;
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +0530265 if (*nss == 2)
Yeshwanth Sriram Guntukad18c7a22018-02-02 15:22:30 +0530266 index += MAX_HT_MCS_IDX;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800267 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800268 }
269 }
270 }
271
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800272rate_found:
273 /* set SGI flag only if this is SGI rate */
274 if (match_rate && is_sgi == true)
Naveen Rawatea1564b2018-05-17 15:56:11 -0700275 *mcsRateFlag |= TX_RATE_SGI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800277 WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
278 __func__, match_rate, index, *mcsRateFlag, is_sgi);
279
280 return match_rate ? index : INVALID_MCS_IDX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281}
282
Naveen Rawatfa2a1002018-05-17 16:06:37 -0700283#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530285 * wma_peek_vdev_req() - peek what request message is queued for response.
286 * the function does not delete the node after found
287 * @wma: WMA handle
288 * @vdev_id: vdev ID
289 * @type: request message type
290 *
291 * Return: the request message found
292 */
293static struct wma_target_req *wma_peek_vdev_req(tp_wma_handle wma,
294 uint8_t vdev_id, uint8_t type)
295{
296 struct wma_target_req *req_msg = NULL;
297 bool found = false;
298 qdf_list_node_t *node1 = NULL, *node2 = NULL;
299
300 qdf_spin_lock_bh(&wma->vdev_respq_lock);
301 if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&wma->vdev_resp_queue,
302 &node2)) {
303 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530304 return NULL;
305 }
306
307 do {
308 node1 = node2;
309 req_msg = qdf_container_of(node1, struct wma_target_req, node);
310 if (req_msg->vdev_id != vdev_id)
311 continue;
312 if (req_msg->type != type)
313 continue;
314
315 found = true;
316 break;
317 } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&wma->vdev_resp_queue,
318 node1, &node2));
319 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
320 if (!found) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800321 WMA_LOGE(FL("target request not found for vdev_id %d type %d"),
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530322 vdev_id, type);
323 return NULL;
324 }
325 WMA_LOGD(FL("target request found for vdev id: %d type %d msg %d"),
326 vdev_id, type, req_msg->msg_type);
327 return req_msg;
328}
Naveen Rawatfa2a1002018-05-17 16:06:37 -0700329#endif /* QCA_SUPPORT_CP_STATS */
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530330
331void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id,
332 int32_t rssi)
333{
334 struct sir_lost_link_info *lost_link_info;
335 QDF_STATUS qdf_status;
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800336 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530337
338 /* report lost link information only for STA mode */
Mukul Sharmaf9047232017-03-02 16:58:56 +0530339 if (wma_is_vdev_up(vdev_id) &&
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530340 (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) &&
341 (0 == wma->interfaces[vdev_id].sub_type)) {
342 lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
343 if (NULL == lost_link_info) {
344 WMA_LOGE("%s: failed to allocate memory", __func__);
345 return;
346 }
347 lost_link_info->vdev_id = vdev_id;
348 lost_link_info->rssi = rssi;
349 sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
350 sme_msg.bodyptr = lost_link_info;
351 sme_msg.bodyval = 0;
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800352 WMA_LOGD("%s: post msg to SME, bss_idx %d, rssi %d", __func__,
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530353 lost_link_info->vdev_id, lost_link_info->rssi);
354
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800355 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530356 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
357 WMA_LOGE("%s: fail to post msg to SME", __func__);
358 qdf_mem_free(lost_link_info);
359 }
360 }
361}
362
363/**
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700364 * host_map_smps_mode() - map fw smps mode to enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 * @fw_smps_mode: fw smps mode
366 *
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700367 * Return: return enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700369enum eSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700371 enum eSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 switch (fw_smps_mode) {
374 case WMI_SMPS_FORCED_MODE_STATIC:
375 smps_mode = STATIC_SMPS_MODE;
376 break;
377 case WMI_SMPS_FORCED_MODE_DYNAMIC:
378 smps_mode = DYNAMIC_SMPS_MODE;
379 break;
380 default:
381 smps_mode = SMPS_MODE_DISABLED;
382 }
383
384 return smps_mode;
385}
386
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800387/**
388 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
389 * mode commmand param
390 * @smps_mode: SMPS mode according to the protocol
391 *
392 * Return: int > 0 for success else failure
393 */
394int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
395{
396 int param = -EINVAL;
397
398 switch (smps_mode) {
399 case STATIC_SMPS_MODE:
400 param = WMI_SMPS_FORCED_MODE_STATIC;
401 break;
402 case DYNAMIC_SMPS_MODE:
403 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
404 break;
405 case SMPS_MODE_DISABLED:
406 param = WMI_SMPS_FORCED_MODE_DISABLED;
407 break;
408 default:
409 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
410 smps_mode);
411 }
412 return param;
413}
414
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415#ifdef WLAN_FEATURE_STATS_EXT
416/**
417 * wma_stats_ext_event_handler() - extended stats event handler
418 * @handle: wma handle
419 * @event_buf: event buffer received from fw
420 * @len: length of data
421 *
422 * Return: 0 for success or error code
423 */
424int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
425 uint32_t len)
426{
427 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
428 tSirStatsExtEvent *stats_ext_event;
429 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530430 QDF_STATUS status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -0700431 struct scheduler_msg cds_msg = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432 uint8_t *buf_ptr;
433 uint32_t alloc_len;
434
435 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
436
437 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
438 if (!param_buf) {
439 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
440 return -EINVAL;
441 }
442
443 stats_ext_info = param_buf->fixed_param;
444 buf_ptr = (uint8_t *) stats_ext_info;
445
446 alloc_len = sizeof(tSirStatsExtEvent);
447 alloc_len += stats_ext_info->data_len;
448
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700449 if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE -
Yeshwanth Sriram Guntukaf71b48e2018-04-20 15:18:08 +0530450 WMI_TLV_HDR_SIZE - sizeof(*stats_ext_info)) ||
451 stats_ext_info->data_len > param_buf->num_data) {
Abhinav Kumara03659c2017-12-28 15:18:07 +0530452 WMA_LOGE("Excess data_len:%d, num_data:%d",
453 stats_ext_info->data_len, param_buf->num_data);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700454 return -EINVAL;
455 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530456 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800457 if (NULL == stats_ext_event) {
458 WMA_LOGE("%s: Memory allocation failure", __func__);
459 return -ENOMEM;
460 }
461
462 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
463
464 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
465 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530466 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467 buf_ptr, stats_ext_event->event_data_len);
468
469 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
470 cds_msg.bodyptr = (void *)stats_ext_event;
471 cds_msg.bodyval = 0;
472
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800473 status = scheduler_post_msg(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530474 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530476 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477 return -EFAULT;
478 }
479
480 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
481 return 0;
482}
483#endif /* WLAN_FEATURE_STATS_EXT */
484
Nirav Shah93e789e2016-04-14 19:47:43 +0530485
Govind Singha471e5e2015-10-12 17:11:14 +0530486/**
487 * wma_profile_data_report_event_handler() - fw profiling handler
488 * @handle: wma handle
489 * @event_buf: event buffer received from fw
490 * @len: length of data
491 *
492 * Return: 0 for success or error code
493 */
494int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
495 uint32_t len)
496{
497 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
498 wmi_wlan_profile_ctx_t *profile_ctx;
499 wmi_wlan_profile_t *profile_data;
500 uint32_t i = 0;
501 uint32_t entries;
502 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530503 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530504
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700505 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
Govind Singha471e5e2015-10-12 17:11:14 +0530506 if (!param_buf) {
507 WMA_LOGE("%s: Invalid profile data event buf", __func__);
508 return -EINVAL;
509 }
510 profile_ctx = param_buf->profile_ctx;
511 buf_ptr = (uint8_t *)profile_ctx;
512 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
513 profile_data = (wmi_wlan_profile_t *) buf_ptr;
514 entries = profile_ctx->bin_count;
Amar Singhal4bd22232017-10-04 13:24:00 -0700515
516 if (entries > param_buf->num_profile_data) {
517 WMA_LOGE("FW bin count %d more than data %d in TLV hdr",
518 entries,
519 param_buf->num_profile_data);
520 return -EINVAL;
521 }
522
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530523 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530524 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530525 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530526 "TOT: %d\n"
527 "tx_msdu_cnt: %d\n"
528 "tx_mpdu_cnt: %d\n"
529 "tx_ppdu_cnt: %d\n"
530 "rx_msdu_cnt: %d\n"
531 "rx_mpdu_cnt: %d\n"
532 "bin_count: %d\n",
533 profile_ctx->tot,
534 profile_ctx->tx_msdu_cnt,
535 profile_ctx->tx_mpdu_cnt,
536 profile_ctx->tx_ppdu_cnt,
537 profile_ctx->rx_msdu_cnt,
538 profile_ctx->rx_mpdu_cnt,
539 profile_ctx->bin_count);
540
Nirav Shah93e789e2016-04-14 19:47:43 +0530541 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
542 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
543
Govind Singha471e5e2015-10-12 17:11:14 +0530544 for (i = 0; i < entries; i++) {
545 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
546 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530547 snprintf(temp_str, sizeof(temp_str),
548 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530549 profile_data[i].id,
550 profile_data[i].cnt,
551 profile_data[i].tot,
552 profile_data[i].min,
553 profile_data[i].max,
554 profile_data[i].hist_intvl,
555 profile_data[i].hist[0],
556 profile_data[i].hist[1],
557 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530558 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
559 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530560 }
561
562 return 0;
563}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564
565#ifdef WLAN_FEATURE_LINK_LAYER_STATS
566
Zhang Qian73c348a2017-03-13 16:15:55 +0800567#define WMA_FILL_TX_STATS(eve, msg) do {\
568 (msg)->msdus = (eve)->tx_msdu_cnt;\
569 (msg)->mpdus = (eve)->tx_mpdu_cnt;\
570 (msg)->ppdus = (eve)->tx_ppdu_cnt;\
571 (msg)->bytes = (eve)->tx_bytes;\
572 (msg)->drops = (eve)->tx_msdu_drop_cnt;\
573 (msg)->drop_bytes = (eve)->tx_drop_bytes;\
574 (msg)->retries = (eve)->tx_mpdu_retry_cnt;\
575 (msg)->failed = (eve)->tx_mpdu_fail_cnt;\
576} while (0)
577
578#define WMA_FILL_RX_STATS(eve, msg) do {\
579 (msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
580 (msg)->bytes = (eve)->mac_rx_bytes;\
581 (msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
582 (msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
583 (msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
584 (msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
585 (msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
586} while (0)
587
588/**
589 * wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
590 * @len: buffer length output
591 * @peer_num: peer number
592 * @fixed_param: fixed parameters in WMI event
593 *
594 * Structure of the stats message
595 * LL_EXT_STATS
596 * |
597 * |--Channel stats[1~n]
598 * |--Peer[1~n]
599 * |
600 * +---Signal
601 * +---TX
602 * | +---BE
603 * | +---BK
604 * | +---VI
605 * | +---VO
606 * |
607 * +---RX
608 * +---BE
609 * +---BK
610 * +---VI
611 * +---VO
612 * For each Access Category, the arregation and mcs
613 * stats are as this:
614 * TX
615 * +-BE/BK/VI/VO
616 * +----tx_mpdu_aggr_array
617 * +----tx_succ_mcs_array
618 * +----tx_fail_mcs_array
619 * +----tx_delay_array
620 * RX
621 * +-BE/BK/VI/VO
622 * +----rx_mpdu_aggr_array
623 * +----rx_mcs_array
624 *
625 * return: Address for result buffer.
626 */
627static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
628 uint32_t peer_num,
629 wmi_report_stats_event_fixed_param *fixed_param)
630{
631 tSirLLStatsResults *buf;
632 uint32_t buf_len;
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530633 uint32_t total_array_len, total_peer_len;
634 bool excess_data = false;
Zhang Qian73c348a2017-03-13 16:15:55 +0800635
636 if (!len || !fixed_param) {
637 WMA_LOGE(FL("Invalid input parameters."));
638 return NULL;
639 }
640
641 /*
642 * Result buffer has a structure like this:
643 * ---------------------------------
644 * | trigger_cond_i |
645 * +-------------------------------+
646 * | cca_chgd_bitmap |
647 * +-------------------------------+
648 * | sig_chgd_bitmap |
649 * +-------------------------------+
650 * | tx_chgd_bitmap |
651 * +-------------------------------+
652 * | rx_chgd_bitmap |
653 * +-------------------------------+
654 * | peer_num |
655 * +-------------------------------+
656 * | channel_num |
657 * +-------------------------------+
658 * | tx_mpdu_aggr_array_len |
659 * +-------------------------------+
660 * | tx_succ_mcs_array_len |
661 * +-------------------------------+
662 * | tx_fail_mcs_array_len |
663 * +-------------------------------+
664 * | tx_delay_array_len |
665 * +-------------------------------+
666 * | rx_mpdu_aggr_array_len |
667 * +-------------------------------+
668 * | rx_mcs_array_len |
669 * +-------------------------------+
670 * | pointer to CCA stats |
671 * +-------------------------------+
672 * | CCA stats |
673 * +-------------------------------+
674 * | peer_stats |----+
675 * +-------------------------------+ |
676 * | TX aggr/mcs parameters array | |
677 * | Length of this buffer is | |
678 * | not fixed. |<-+ |
679 * +-------------------------------+ | |
680 * | per peer tx stats |--+ |
681 * | BE | <--+
682 * | BK | |
683 * | VI | |
684 * | VO | |
685 * +-------------------------------+ |
686 * | TX aggr/mcs parameters array | |
687 * | Length of this buffer is | |
688 * | not fixed. |<-+ |
689 * +-------------------------------+ | |
690 * | peer peer rx stats |--+ |
691 * | BE | <--+
692 * | BK |
693 * | VI |
694 * | VO |
695 * ---------------------------------
696 */
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530697
Zhang Qian73c348a2017-03-13 16:15:55 +0800698 buf_len = sizeof(tSirLLStatsResults) +
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530699 sizeof(struct sir_wifi_ll_ext_stats);
700 do {
701 if (fixed_param->num_chan_cca_stats > (WMI_SVC_MSG_MAX_SIZE /
702 sizeof(struct sir_wifi_chan_cca_stats))) {
703 excess_data = true;
704 break;
705 }
706 buf_len += (fixed_param->num_chan_cca_stats *
707 sizeof(struct sir_wifi_chan_cca_stats));
708 if (fixed_param->tx_mpdu_aggr_array_len >
709 WMI_SVC_MSG_MAX_SIZE) {
710 excess_data = true;
711 break;
712 } else {
713 total_array_len = fixed_param->tx_mpdu_aggr_array_len;
714 }
715 if (fixed_param->tx_succ_mcs_array_len >
716 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
717 excess_data = true;
718 break;
719 } else {
720 total_array_len += fixed_param->tx_succ_mcs_array_len;
721 }
722 if (fixed_param->tx_fail_mcs_array_len >
723 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
724 excess_data = true;
725 break;
726 } else {
727 total_array_len += fixed_param->tx_fail_mcs_array_len;
728 }
729 if (fixed_param->tx_ppdu_delay_array_len >
730 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
731 excess_data = true;
732 break;
733 } else {
734 total_array_len += fixed_param->tx_ppdu_delay_array_len;
735 }
736 if (fixed_param->rx_mpdu_aggr_array_len >
737 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
738 excess_data = true;
739 break;
740 } else {
741 total_array_len += fixed_param->rx_mpdu_aggr_array_len;
742 }
743 if (fixed_param->rx_mcs_array_len >
744 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
745 excess_data = true;
746 break;
747 } else {
748 total_array_len += fixed_param->rx_mcs_array_len;
749 }
750
751 if (total_array_len > (WMI_SVC_MSG_MAX_SIZE /
752 (sizeof(uint32_t) * WLAN_MAX_AC))) {
753 excess_data = true;
754 break;
755 } else {
756 total_peer_len = (sizeof(uint32_t) * WLAN_MAX_AC *
757 total_array_len) +
758 (WLAN_MAX_AC *
759 (sizeof(struct sir_wifi_tx) +
760 sizeof(struct sir_wifi_rx)));
761 }
Vignesh Viswanathanca67e362017-10-04 23:42:00 +0530762 if (total_peer_len > WMI_SVC_MSG_MAX_SIZE) {
763 excess_data = true;
764 break;
765 }
Vignesh Viswanathanbd1ad032017-11-15 15:13:56 +0530766 if (peer_num > WMI_SVC_MSG_MAX_SIZE / (total_peer_len +
767 sizeof(struct sir_wifi_ll_ext_peer_stats))) {
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530768 excess_data = true;
769 break;
770 } else {
771 buf_len += peer_num *
772 (sizeof(struct sir_wifi_ll_ext_peer_stats) +
773 total_peer_len);
774 }
775 } while (0);
776
777 if (excess_data || (buf_len > WMI_SVC_MSG_MAX_SIZE)) {
778 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",
779 __func__, peer_num, fixed_param->num_chan_cca_stats,
780 fixed_param->tx_mpdu_aggr_array_len,
781 fixed_param->tx_succ_mcs_array_len,
782 fixed_param->tx_fail_mcs_array_len,
783 fixed_param->tx_ppdu_delay_array_len,
784 fixed_param->rx_mpdu_aggr_array_len,
785 fixed_param->rx_mcs_array_len);
Vignesh Viswanathan9f090ad2017-09-27 20:33:55 +0530786 return NULL;
787 }
Zhang Qian73c348a2017-03-13 16:15:55 +0800788
789 buf = (tSirLLStatsResults *)qdf_mem_malloc(buf_len);
790 if (buf == NULL) {
791 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
792 buf_len = 0;
793 return NULL;
794 }
795
796 *len = buf_len;
797 return buf;
798}
799
800/**
801 * wma_fill_tx_stats() - Fix TX stats into result buffer
802 * @ll_stats: LL stats buffer
803 * @fix_param: parameters with fixed length in WMI event
804 * @param_buf: parameters without fixed length in WMI event
805 * @buf: buffer for TLV parameters
806 *
807 * Return: None
808 */
809static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
810 wmi_report_stats_event_fixed_param *fix_param,
811 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
812 uint8_t **buf, uint32_t *buf_length)
813{
814 uint8_t *result;
815 uint32_t i, j, k;
816 wmi_peer_ac_tx_stats *wmi_peer_tx;
817 wmi_tx_stats *wmi_tx;
818 struct sir_wifi_tx *tx_stats;
819 struct sir_wifi_ll_ext_peer_stats *peer_stats;
820 uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
821 uint32_t len, dst_len, tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
822 tx_fail_mcs_array_len, tx_delay_array_len;
823
824 result = *buf;
825 dst_len = *buf_length;
826 tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
827 ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
828 tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
829 ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
830 tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
831 ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
832 tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
833 ll_stats->tx_delay_array_len = tx_delay_array_len;
834 wmi_peer_tx = param_buf->peer_ac_tx_stats;
835 wmi_tx = param_buf->tx_stats;
836
837 len = fix_param->num_peer_ac_tx_stats *
838 WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
839 if (len <= dst_len) {
840 tx_mpdu_aggr = (uint32_t *)result;
841 qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
842 result += len;
843 dst_len -= len;
844 } else {
845 WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong."));
846 tx_mpdu_aggr = NULL;
847 }
848
849 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
850 tx_succ_mcs_array_len * sizeof(uint32_t);
851 if (len <= dst_len) {
852 tx_succ_mcs = (uint32_t *)result;
853 qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
854 result += len;
855 dst_len -= len;
856 } else {
857 WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong."));
858 tx_succ_mcs = NULL;
859 }
860
861 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
862 tx_fail_mcs_array_len * sizeof(uint32_t);
863 if (len <= dst_len) {
864 tx_fail_mcs = (uint32_t *)result;
865 qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
866 result += len;
867 dst_len -= len;
868 } else {
869 WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong."));
870 tx_fail_mcs = NULL;
871 }
872
873 len = fix_param->num_peer_ac_tx_stats *
874 WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
875 if (len <= dst_len) {
876 tx_delay = (uint32_t *)result;
877 qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
878 result += len;
879 dst_len -= len;
880 } else {
881 WMA_LOGE(FL("TX_DELAY buffer length is wrong."));
882 tx_delay = NULL;
883 }
884
885 /* per peer tx stats */
886 peer_stats = ll_stats->peer_stats;
887
888 for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
889 uint32_t peer_id = wmi_peer_tx[i].peer_id;
890 struct sir_wifi_tx *ac;
891 wmi_tx_stats *wmi_tx_stats;
892
893 for (j = 0; j < ll_stats->peer_num; j++) {
894 peer_stats += j;
895 if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
896 peer_stats->peer_id == peer_id)
897 break;
898 }
899
900 if (j < ll_stats->peer_num) {
901 peer_stats->peer_id = wmi_peer_tx[i].peer_id;
902 peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
903 tx_stats = (struct sir_wifi_tx *)result;
904 for (k = 0; k < WLAN_MAX_AC; k++) {
905 wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
906 ac = &tx_stats[k];
907 WMA_FILL_TX_STATS(wmi_tx_stats, ac);
908 ac->mpdu_aggr_size = tx_mpdu_aggr;
909 ac->aggr_len = tx_mpdu_aggr_array_len *
910 sizeof(uint32_t);
911 ac->success_mcs_len = tx_succ_mcs_array_len *
912 sizeof(uint32_t);
913 ac->success_mcs = tx_succ_mcs;
914 ac->fail_mcs = tx_fail_mcs;
915 ac->fail_mcs_len = tx_fail_mcs_array_len *
916 sizeof(uint32_t);
917 ac->delay = tx_delay;
918 ac->delay_len = tx_delay_array_len *
919 sizeof(uint32_t);
920 peer_stats->ac_stats[k].tx_stats = ac;
921 peer_stats->ac_stats[k].type = k;
922 tx_mpdu_aggr += tx_mpdu_aggr_array_len;
923 tx_succ_mcs += tx_succ_mcs_array_len;
924 tx_fail_mcs += tx_fail_mcs_array_len;
925 tx_delay += tx_delay_array_len;
926 }
927 result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
928 } else {
929 /*
930 * Buffer for Peer TX counter overflow.
931 * There is peer ID mismatch between TX, RX,
932 * signal counters.
933 */
934 WMA_LOGE(FL("One peer TX info is dropped."));
935
936 tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
937 tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
938 tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
939 tx_delay += tx_delay_array_len * WLAN_MAX_AC;
940 }
941 }
942 *buf = result;
943 *buf_length = dst_len;
944}
945
946/**
947 * wma_fill_rx_stats() - Fix RX stats into result buffer
948 * @ll_stats: LL stats buffer
949 * @fix_param: parameters with fixed length in WMI event
950 * @param_buf: parameters without fixed length in WMI event
951 * @buf: buffer for TLV parameters
952 *
953 * Return: None
954 */
955static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
956 wmi_report_stats_event_fixed_param *fix_param,
957 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
958 uint8_t **buf, uint32_t *buf_length)
959{
960 uint8_t *result;
961 uint32_t i, j, k;
962 uint32_t *rx_mpdu_aggr, *rx_mcs;
963 wmi_rx_stats *wmi_rx;
964 wmi_peer_ac_rx_stats *wmi_peer_rx;
965 struct sir_wifi_rx *rx_stats;
966 struct sir_wifi_ll_ext_peer_stats *peer_stats;
967 uint32_t len, dst_len, rx_mpdu_aggr_array_len, rx_mcs_array_len;
968
969 rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
970 ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
971 rx_mcs_array_len = fix_param->rx_mcs_array_len;
972 ll_stats->rx_mcs_array_len = rx_mcs_array_len;
973 wmi_peer_rx = param_buf->peer_ac_rx_stats;
974 wmi_rx = param_buf->rx_stats;
975
976 result = *buf;
977 dst_len = *buf_length;
978 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
979 WLAN_MAX_AC * rx_mpdu_aggr_array_len);
980 if (len <= dst_len) {
981 rx_mpdu_aggr = (uint32_t *)result;
982 qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
983 result += len;
984 dst_len -= len;
985 } else {
986 WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong."));
987 rx_mpdu_aggr = NULL;
988 }
989
990 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
991 WLAN_MAX_AC * rx_mcs_array_len);
992 if (len <= dst_len) {
993 rx_mcs = (uint32_t *)result;
994 qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len);
995 result += len;
996 dst_len -= len;
997 } else {
998 WMA_LOGE(FL("RX_MCS array length is wrong."));
999 rx_mcs = NULL;
1000 }
1001
1002 /* per peer rx stats */
1003 peer_stats = ll_stats->peer_stats;
1004 for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) {
1005 uint32_t peer_id = wmi_peer_rx[i].peer_id;
1006 struct sir_wifi_rx *ac;
1007 wmi_rx_stats *wmi_rx_stats;
1008
1009 for (j = 0; j < ll_stats->peer_num; j++) {
1010 peer_stats += j;
1011 if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
1012 (peer_stats->peer_id == peer_id))
1013 break;
1014 }
1015
1016 if (j < ll_stats->peer_num) {
1017 peer_stats->peer_id = wmi_peer_rx[i].peer_id;
1018 peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
1019 peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
1020 peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
1021 peer_stats->rx_probe_reqs =
1022 wmi_peer_rx[i].rx_probe_reqs;
1023 peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
1024 rx_stats = (struct sir_wifi_rx *)result;
1025
1026 for (k = 0; k < WLAN_MAX_AC; k++) {
1027 wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
1028 ac = &rx_stats[k];
1029 WMA_FILL_RX_STATS(wmi_rx_stats, ac);
1030 ac->mpdu_aggr = rx_mpdu_aggr;
1031 ac->aggr_len = rx_mpdu_aggr_array_len *
1032 sizeof(uint32_t);
1033 ac->mcs = rx_mcs;
1034 ac->mcs_len = rx_mcs_array_len *
1035 sizeof(uint32_t);
1036 peer_stats->ac_stats[k].rx_stats = ac;
1037 peer_stats->ac_stats[k].type = k;
1038 rx_mpdu_aggr += rx_mpdu_aggr_array_len;
1039 rx_mcs += rx_mcs_array_len;
1040 }
1041 result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
1042 } else {
1043 /*
1044 * Buffer for Peer RX counter overflow.
1045 * There is peer ID mismatch between TX, RX,
1046 * signal counters.
1047 */
1048 WMA_LOGE(FL("One peer RX info is dropped."));
1049 rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
1050 rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
1051 }
1052 }
1053 *buf = result;
1054 *buf_length = dst_len;
1055}
1056
1057/**
1058 * wma_ll_stats_evt_handler() - handler for MAC layer counters.
1059 * @handle - wma handle
1060 * @event - FW event
1061 * @len - length of FW event
1062 *
1063 * return: 0 success.
1064 */
1065static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
1066 u_int32_t len)
1067{
1068 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
1069 wmi_report_stats_event_fixed_param *fixed_param;
1070 tSirLLStatsResults *link_stats_results;
1071 wmi_chan_cca_stats *wmi_cca_stats;
1072 wmi_peer_signal_stats *wmi_peer_signal;
1073 wmi_peer_ac_rx_stats *wmi_peer_rx;
1074 struct sir_wifi_ll_ext_stats *ll_stats;
1075 struct sir_wifi_ll_ext_peer_stats *peer_stats;
1076 struct sir_wifi_chan_cca_stats *cca_stats;
1077 struct sir_wifi_peer_signal_stats *peer_signal;
1078 uint8_t *result;
1079 uint32_t i, peer_num, result_size, dst_len;
1080 tpAniSirGlobal mac;
1081 struct scheduler_msg sme_msg = { 0 };
1082 QDF_STATUS qdf_status;
1083
1084 mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
1085 if (!mac) {
1086 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1087 return -EINVAL;
1088 }
1089
1090 if (!mac->sme.link_layer_stats_ext_cb) {
1091 WMA_LOGD("%s: HDD callback is null", __func__);
1092 return -EINVAL;
1093 }
1094
1095 WMA_LOGD("%s: Posting MAC counters event to HDD", __func__);
1096
1097 param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
1098 fixed_param = param_buf->fixed_param;
1099 wmi_cca_stats = param_buf->chan_cca_stats;
1100 wmi_peer_signal = param_buf->peer_signal_stats;
1101 wmi_peer_rx = param_buf->peer_ac_rx_stats;
Abhinav Kumara03659c2017-12-28 15:18:07 +05301102 if (fixed_param->num_peer_signal_stats >
1103 param_buf->num_peer_signal_stats ||
1104 fixed_param->num_peer_ac_tx_stats >
1105 param_buf->num_peer_ac_tx_stats ||
1106 fixed_param->num_peer_ac_rx_stats >
1107 param_buf->num_peer_ac_rx_stats) {
1108 WMA_LOGE("%s: excess num_peer_signal_stats:%d, num_peer_ac_tx_stats:%d, num_peer_ac_rx_stats:%d",
1109 __func__, fixed_param->num_peer_signal_stats,
1110 fixed_param->num_peer_ac_tx_stats,
1111 fixed_param->num_peer_ac_rx_stats);
1112 return -EINVAL;
1113 }
Zhang Qian73c348a2017-03-13 16:15:55 +08001114
1115 /* Get the MAX of three peer numbers */
1116 peer_num = fixed_param->num_peer_signal_stats >
1117 fixed_param->num_peer_ac_tx_stats ?
1118 fixed_param->num_peer_signal_stats :
1119 fixed_param->num_peer_ac_tx_stats;
1120 peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
1121 peer_num : fixed_param->num_peer_ac_rx_stats;
1122
1123 if (peer_num == 0)
1124 return -EINVAL;
1125
1126 link_stats_results = wma_get_ll_stats_ext_buf(&result_size,
1127 peer_num,
1128 fixed_param);
1129 if (!link_stats_results) {
1130 WMA_LOGE("%s: Fail to allocate stats buffer", __func__);
1131 return -EINVAL;
1132 }
1133 link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
1134 link_stats_results->num_peers = peer_num;
1135 link_stats_results->peer_event_number = 1;
1136 link_stats_results->moreResultToFollow = 0;
1137
1138 ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
1139 ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
1140 ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
1141 ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
1142 ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
1143 ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
1144 ll_stats->channel_num = fixed_param->num_chan_cca_stats;
1145 ll_stats->peer_num = peer_num;
1146
1147 result = (uint8_t *)ll_stats->stats;
1148 peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
1149 ll_stats->peer_stats = peer_stats;
1150
1151 for (i = 0; i < peer_num; i++) {
1152 peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
1153 peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
1154 }
1155
1156 /* Per peer signal */
1157 result_size -= sizeof(struct sir_wifi_ll_ext_stats);
1158 dst_len = sizeof(struct sir_wifi_peer_signal_stats);
1159 for (i = 0; i < fixed_param->num_peer_signal_stats; i++) {
1160 peer_stats[i].peer_id = wmi_peer_signal->peer_id;
1161 peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
1162 peer_signal = &peer_stats[i].peer_signal_stats;
1163
Zhang Qian303ebe92017-05-18 13:59:07 +08001164 WMA_LOGD("%d antennas for peer %d",
1165 wmi_peer_signal->num_chains_valid,
1166 wmi_peer_signal->peer_id);
Zhang Qian73c348a2017-03-13 16:15:55 +08001167 if (dst_len <= result_size) {
Zhang Qian303ebe92017-05-18 13:59:07 +08001168 peer_signal->vdev_id = wmi_peer_signal->vdev_id;
1169 peer_signal->peer_id = wmi_peer_signal->peer_id;
1170 peer_signal->num_chain =
1171 wmi_peer_signal->num_chains_valid;
1172 qdf_mem_copy(peer_signal->per_ant_snr,
1173 wmi_peer_signal->per_chain_snr,
1174 sizeof(peer_signal->per_ant_snr));
1175 qdf_mem_copy(peer_signal->nf,
1176 wmi_peer_signal->per_chain_nf,
1177 sizeof(peer_signal->nf));
1178 qdf_mem_copy(peer_signal->per_ant_rx_mpdus,
1179 wmi_peer_signal->per_antenna_rx_mpdus,
1180 sizeof(peer_signal->per_ant_rx_mpdus));
1181 qdf_mem_copy(peer_signal->per_ant_tx_mpdus,
1182 wmi_peer_signal->per_antenna_tx_mpdus,
1183 sizeof(peer_signal->per_ant_tx_mpdus));
Zhang Qian73c348a2017-03-13 16:15:55 +08001184 result_size -= dst_len;
1185 } else {
1186 WMA_LOGE(FL("Invalid length of PEER signal."));
1187 }
1188 wmi_peer_signal++;
1189 }
1190
1191 result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
1192 cca_stats = (struct sir_wifi_chan_cca_stats *)result;
1193 ll_stats->cca = cca_stats;
1194 dst_len = sizeof(struct sir_wifi_chan_cca_stats);
1195 for (i = 0; i < ll_stats->channel_num; i++) {
1196 if (dst_len <= result_size) {
1197 qdf_mem_copy(&cca_stats[i], &wmi_cca_stats->vdev_id,
1198 dst_len);
1199 result_size -= dst_len;
1200 } else {
1201 WMA_LOGE(FL("Invalid length of CCA."));
1202 }
1203 }
1204
1205 result += i * sizeof(struct sir_wifi_chan_cca_stats);
1206 wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
1207 &result, &result_size);
1208 wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
1209 &result, &result_size);
1210 sme_msg.type = eWMI_SME_LL_STATS_IND;
1211 sme_msg.bodyptr = (void *)link_stats_results;
1212 sme_msg.bodyval = 0;
1213 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1214 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1215 WMA_LOGP(FL("Failed to post peer stat change msg!"));
1216 qdf_mem_free(link_stats_results);
1217 return -EINVAL;
1218 }
1219
1220 return 0;
1221}
1222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223/**
1224 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
1225 * @handle: wma handle
1226 * @cmd_param_info: data received with event from fw
1227 * @len: length of data
1228 *
1229 * Return: 0 for success or error code
1230 */
1231static int wma_unified_link_peer_stats_event_handler(void *handle,
1232 uint8_t *cmd_param_info,
1233 uint32_t len)
1234{
1235 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1236 wmi_peer_stats_event_fixed_param *fixed_param;
1237 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
1238 wmi_rate_stats *rate_stats;
1239 tSirLLStatsResults *link_stats_results;
1240 uint8_t *results, *t_peer_stats, *t_rate_stats;
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301241 uint32_t count, rate_cnt;
1242 uint32_t total_num_rates = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
1244 size_t peer_info_size, peer_stats_size, rate_stats_size;
1245 size_t link_stats_results_size;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001246 bool excess_data = false;
jitiphil06b539a2018-06-07 16:31:48 +05301247 uint32_t buf_len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301249 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301251 if (!mac) {
1252 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 return -EINVAL;
1254 }
1255
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301256 if (!mac->sme.link_layer_stats_cb) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 WMA_LOGD("%s: HDD callback is null", __func__);
1258 return -EINVAL;
1259 }
1260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1262 if (!param_tlvs) {
1263 WMA_LOGA("%s: Invalid stats event", __func__);
1264 return -EINVAL;
1265 }
1266 /*
1267 * cmd_param_info contains
1268 * wmi_peer_stats_event_fixed_param fixed_param;
1269 * num_peers * size of(struct wmi_peer_link_stats)
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301270 * total_num_rates * size of(struct wmi_rate_stats)
1271 * total_num_rates is the sum of the rates of all the peers.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272 */
1273 fixed_param = param_tlvs->fixed_param;
1274 peer_stats = param_tlvs->peer_stats;
1275 rate_stats = param_tlvs->peer_rate_stats;
1276
1277 if (!fixed_param || !peer_stats ||
1278 (peer_stats->num_rates && !rate_stats)) {
1279 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
1280 return -EINVAL;
1281 }
1282
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001283 do {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001284 if (fixed_param->num_peers >
Abhinav Kumara03659c2017-12-28 15:18:07 +05301285 WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats) ||
1286 fixed_param->num_peers > param_tlvs->num_peer_stats) {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001287 excess_data = true;
1288 break;
1289 } else {
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301290 buf_len = fixed_param->num_peers *
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001291 sizeof(wmi_peer_link_stats);
1292 }
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301293 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
1294 for (count = 0; count < fixed_param->num_peers; count++) {
1295 if (temp_peer_stats->num_rates >
1296 WMI_SVC_MSG_MAX_SIZE / sizeof(wmi_rate_stats)) {
1297 excess_data = true;
1298 break;
1299 } else {
1300 total_num_rates += temp_peer_stats->num_rates;
1301 if (total_num_rates >
1302 WMI_SVC_MSG_MAX_SIZE /
Abhinav Kumara03659c2017-12-28 15:18:07 +05301303 sizeof(wmi_rate_stats) || total_num_rates >
1304 param_tlvs->num_peer_rate_stats) {
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301305 excess_data = true;
1306 break;
1307 }
1308 buf_len += temp_peer_stats->num_rates *
1309 sizeof(wmi_rate_stats);
1310 }
1311 temp_peer_stats++;
1312 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001313 } while (0);
1314
1315 if (excess_data ||
jitiphil9fa0e8e2018-05-25 17:40:41 +05301316 (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_param))) {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001317 WMA_LOGE("excess wmi buffer: rates:%d, peers:%d",
1318 peer_stats->num_rates, fixed_param->num_peers);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001319 return -EINVAL;
1320 }
1321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322 peer_stats_size = sizeof(tSirWifiPeerStat);
1323 peer_info_size = sizeof(tSirWifiPeerInfo);
1324 rate_stats_size = sizeof(tSirWifiRateStat);
1325 link_stats_results_size =
1326 sizeof(*link_stats_results) + peer_stats_size +
1327 (fixed_param->num_peers * peer_info_size) +
Vignesh Viswanathan53d69c92017-09-26 15:27:16 +05301328 (total_num_rates * rate_stats_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301330 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001331 if (NULL == link_stats_results) {
1332 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1333 __func__, link_stats_results_size);
1334 return -ENOMEM;
1335 }
1336
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301337 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001338
1339 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
1340 link_stats_results->rspId = fixed_param->request_id;
1341 link_stats_results->ifaceId = 0;
1342 link_stats_results->num_peers = fixed_param->num_peers;
1343 link_stats_results->peer_event_number = fixed_param->peer_event_number;
1344 link_stats_results->moreResultToFollow = fixed_param->more_data;
1345
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301346 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347 &fixed_param->num_peers, peer_stats_size);
1348
1349 results = (uint8_t *) link_stats_results->results;
1350 t_peer_stats = (uint8_t *) peer_stats;
1351 t_rate_stats = (uint8_t *) rate_stats;
1352 next_res_offset = peer_stats_size;
1353 next_peer_offset = WMI_TLV_HDR_SIZE;
1354 next_rate_offset = WMI_TLV_HDR_SIZE;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301355 for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301356 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001357 t_peer_stats + next_peer_offset, peer_info_size);
1358 next_res_offset += peer_info_size;
1359
1360 /* Copy rate stats associated with this peer */
1361 for (count = 0; count < peer_stats->num_rates; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 rate_stats++;
1363
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301364 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 t_rate_stats + next_rate_offset,
1366 rate_stats_size);
1367 next_res_offset += rate_stats_size;
1368 next_rate_offset += sizeof(*rate_stats);
1369 }
1370 next_peer_offset += sizeof(*peer_stats);
1371 peer_stats++;
1372 }
1373
1374 /* call hdd callback with Link Layer Statistics
1375 * vdev_id/ifacId in link_stats_results will be
1376 * used to retrieve the correct HDD context
1377 */
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301378 mac->sme.link_layer_stats_cb(mac->hdd_handle,
1379 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1380 link_stats_results,
1381 mac->sme.ll_stats_context);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301382 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383
1384 return 0;
1385}
1386
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001387/**
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001388 * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
1389 * @handle: WMI handle
1390 *
1391 * Return: 0 on success, error number otherwise.
1392 */
yeshwanth sriram guntuka584c2332017-07-29 12:50:25 +05301393int wma_unified_radio_tx_mem_free(void *handle)
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001394{
1395 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1396 tSirWifiRadioStat *rs_results;
1397 uint32_t i = 0;
1398
1399 if (!wma_handle->link_stats_results)
1400 return 0;
1401
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001402 rs_results = (tSirWifiRadioStat *)
1403 &wma_handle->link_stats_results->results[0];
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001404 for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
1405 rs_results += i;
1406 if (rs_results->tx_time_per_power_level) {
1407 qdf_mem_free(rs_results->tx_time_per_power_level);
1408 rs_results->tx_time_per_power_level = NULL;
1409 }
1410
1411 if (rs_results->channels) {
1412 qdf_mem_free(rs_results->channels);
1413 rs_results->channels = NULL;
1414 }
1415 }
1416
1417 qdf_mem_free(wma_handle->link_stats_results);
1418 wma_handle->link_stats_results = NULL;
1419
1420 return 0;
1421}
1422
1423/**
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001424 * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
1425 * @handle: WMI handle
1426 * @cmd_param_info: command param info
1427 * @len: Length of @cmd_param_info
1428 *
1429 * This is the WMI event handler function to receive radio stats tx
1430 * power level stats.
1431 *
1432 * Return: 0 on success, error number otherwise.
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001433 */
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001434static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
1435 u_int8_t *cmd_param_info, u_int32_t len)
1436{
1437 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1438 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
1439 wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
1440 uint8_t *tx_power_level_values;
1441 tSirLLStatsResults *link_stats_results;
1442 tSirWifiRadioStat *rs_results;
Vignesh Viswanathan59f0fad2018-01-25 17:04:46 +05301443 uint32_t max_total_num_tx_power_levels = MAX_TPC_LEVELS * NUM_OF_BANDS *
1444 MAX_SPATIAL_STREAM_ANY_V3;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001445
1446 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1447
1448 if (!mac) {
1449 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1450 return -EINVAL;
1451 }
1452
Jeff Johnson959f3692018-07-03 17:30:40 -07001453 if (!mac->sme.link_layer_stats_cb) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001454 WMA_LOGD("%s: HDD callback is null", __func__);
1455 return -EINVAL;
1456 }
1457
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001458 param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)
1459 cmd_param_info;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001460 if (!param_tlvs) {
1461 WMA_LOGA("%s: Invalid tx power level stats event", __func__);
1462 return -EINVAL;
1463 }
1464
1465 fixed_param = param_tlvs->fixed_param;
1466 if (!fixed_param) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001467 WMA_LOGA("%s:Invalid param_tlvs for Radio tx_power level Stats",
1468 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001469 return -EINVAL;
1470 }
1471
1472 link_stats_results = wma_handle->link_stats_results;
Srinivas Girigowda52cbce42016-10-25 14:11:58 -07001473 if (!link_stats_results) {
1474 WMA_LOGA("%s: link_stats_results is NULL", __func__);
1475 return -EINVAL;
1476 }
1477
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001478 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 -07001479 __func__, fixed_param->total_num_tx_power_levels,
1480 fixed_param->num_tx_power_levels,
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001481 fixed_param->power_level_offset,
1482 fixed_param->radio_id);
1483
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001484 if (fixed_param->num_tx_power_levels > ((WMI_SVC_MSG_MAX_SIZE -
Abhinav Kumara03659c2017-12-28 15:18:07 +05301485 sizeof(*fixed_param)) / sizeof(uint32_t)) ||
1486 fixed_param->num_tx_power_levels >
1487 param_tlvs->num_tx_time_per_power_level) {
1488 WMA_LOGE("%s: excess tx_power buffers:%d, num_tx_time_per_power_level:%d",
1489 __func__, fixed_param->num_tx_power_levels,
1490 param_tlvs->num_tx_time_per_power_level);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001491 return -EINVAL;
1492 }
Vignesh Viswanathanad7eded2017-11-28 16:58:24 +05301493
Vignesh Viswanathan01e1adb2018-03-23 20:22:38 +05301494 if (fixed_param->radio_id >= link_stats_results->num_radio) {
1495 WMA_LOGE("%s: Invalid radio_id %d num_radio %d",
Vignesh Viswanathan59f0fad2018-01-25 17:04:46 +05301496 __func__, fixed_param->radio_id,
1497 link_stats_results->num_radio);
1498 return -EINVAL;
1499 }
1500
1501 if (fixed_param->total_num_tx_power_levels >
1502 max_total_num_tx_power_levels) {
1503 WMA_LOGD("Invalid total_num_tx_power_levels %d",
1504 fixed_param->total_num_tx_power_levels);
1505 return -EINVAL;
1506 }
1507
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001508 rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] +
1509 fixed_param->radio_id;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001510 tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001511
1512 rs_results->total_num_tx_power_levels =
1513 fixed_param->total_num_tx_power_levels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001514 if (!rs_results->total_num_tx_power_levels) {
1515 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001516 goto post_stats;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001517 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001518
Vignesh Viswanathanad7eded2017-11-28 16:58:24 +05301519 if ((fixed_param->power_level_offset >
1520 rs_results->total_num_tx_power_levels) ||
1521 (fixed_param->num_tx_power_levels >
1522 rs_results->total_num_tx_power_levels -
1523 fixed_param->power_level_offset)) {
1524 WMA_LOGE("%s: Invalid offset %d total_num %d num %d",
1525 __func__, fixed_param->power_level_offset,
1526 rs_results->total_num_tx_power_levels,
1527 fixed_param->num_tx_power_levels);
1528 return -EINVAL;
1529 }
1530
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001531 if (!rs_results->tx_time_per_power_level) {
1532 rs_results->tx_time_per_power_level = qdf_mem_malloc(
1533 sizeof(uint32_t) *
1534 rs_results->total_num_tx_power_levels);
1535 if (!rs_results->tx_time_per_power_level) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001536 WMA_LOGA("%s: Mem alloc fail for tx power level stats",
1537 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001538 /* In error case, atleast send the radio stats without
1539 * tx_power_level stats */
1540 rs_results->total_num_tx_power_levels = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001541 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001542 goto post_stats;
1543 }
1544 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001545 qdf_mem_copy(&rs_results->tx_time_per_power_level[
1546 fixed_param->power_level_offset],
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001547 tx_power_level_values,
1548 sizeof(uint32_t) * fixed_param->num_tx_power_levels);
1549 if (rs_results->total_num_tx_power_levels ==
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001550 (fixed_param->num_tx_power_levels +
1551 fixed_param->power_level_offset)) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001552 link_stats_results->moreResultToFollow = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001553 link_stats_results->nr_received++;
1554 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001555
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001556 WMA_LOGD("%s: moreResultToFollow: %u nr: %u nr_received: %u",
1557 __func__, link_stats_results->moreResultToFollow,
1558 link_stats_results->num_radio,
1559 link_stats_results->nr_received);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001560
1561 /* If still data to receive, return from here */
1562 if (link_stats_results->moreResultToFollow)
1563 return 0;
1564
1565post_stats:
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001566 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1567 /* Not received all radio stats yet, don't post yet */
1568 return 0;
1569 }
1570
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001571 /* call hdd callback with Link Layer Statistics
1572 * vdev_id/ifacId in link_stats_results will be
1573 * used to retrieve the correct HDD context
1574 */
Jeff Johnson959f3692018-07-03 17:30:40 -07001575 mac->sme.link_layer_stats_cb(mac->hdd_handle,
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001576 WMA_LINK_LAYER_STATS_RESULTS_RSP,
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301577 link_stats_results,
1578 mac->sme.ll_stats_context);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001579 wma_unified_radio_tx_mem_free(handle);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001580
1581 return 0;
1582}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583
1584/**
1585 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
1586 * @handle: wma handle
1587 * @cmd_param_info: data received with event from fw
1588 * @len: length of data
1589 *
1590 * Return: 0 for success or error code
1591 */
1592static int wma_unified_link_radio_stats_event_handler(void *handle,
1593 uint8_t *cmd_param_info,
1594 uint32_t len)
1595{
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001596 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001597 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1598 wmi_radio_link_stats_event_fixed_param *fixed_param;
1599 wmi_radio_link_stats *radio_stats;
1600 wmi_channel_stats *channel_stats;
1601 tSirLLStatsResults *link_stats_results;
1602 uint8_t *results, *t_radio_stats, *t_channel_stats;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001603 uint32_t next_chan_offset, count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604 size_t radio_stats_size, chan_stats_size;
1605 size_t link_stats_results_size;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001606 tSirWifiRadioStat *rs_results;
1607 tSirWifiChannelStats *chn_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001608
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301609 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001610
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301611 if (!mac) {
1612 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613 return -EINVAL;
1614 }
1615
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301616 if (!mac->sme.link_layer_stats_cb) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001617 WMA_LOGD("%s: HDD callback is null", __func__);
1618 return -EINVAL;
1619 }
1620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001621 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1622 if (!param_tlvs) {
1623 WMA_LOGA("%s: Invalid stats event", __func__);
1624 return -EINVAL;
1625 }
1626
1627 /*
1628 * cmd_param_info contains
1629 * wmi_radio_link_stats_event_fixed_param fixed_param;
1630 * size of(struct wmi_radio_link_stats);
1631 * num_channels * size of(struct wmi_channel_stats)
1632 */
1633 fixed_param = param_tlvs->fixed_param;
1634 radio_stats = param_tlvs->radio_stats;
1635 channel_stats = param_tlvs->channel_stats;
1636
1637 if (!fixed_param || !radio_stats ||
1638 (radio_stats->num_channels && !channel_stats)) {
1639 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
1640 return -EINVAL;
1641 }
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001642 if (radio_stats->num_channels >
Abhinav Kumara03659c2017-12-28 15:18:07 +05301643 (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS) ||
1644 radio_stats->num_channels > param_tlvs->num_channel_stats) {
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001645 WMA_LOGE("%s: Too many channels %d",
1646 __func__, radio_stats->num_channels);
1647 return -EINVAL;
1648 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001649
1650 radio_stats_size = sizeof(tSirWifiRadioStat);
1651 chan_stats_size = sizeof(tSirWifiChannelStats);
Varun Reddy Yeturuc3139102017-09-27 20:38:39 -07001652 if (fixed_param->num_radio >
1653 (UINT_MAX - sizeof(*link_stats_results))/radio_stats_size) {
1654 WMA_LOGE("excess num_radio %d is leading to int overflow",
1655 fixed_param->num_radio);
1656 return -EINVAL;
1657 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 link_stats_results_size = sizeof(*link_stats_results) +
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001659 fixed_param->num_radio * radio_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001660
Vignesh Viswanathan01e1adb2018-03-23 20:22:38 +05301661 if (radio_stats->radio_id >= fixed_param->num_radio) {
1662 WMA_LOGE("%s, invalid radio id:%d, num radio:%d",
1663 __func__, radio_stats->radio_id,
1664 fixed_param->num_radio);
1665 return -EINVAL;
1666 }
1667
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001668 if (!wma_handle->link_stats_results) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001669 wma_handle->link_stats_results = qdf_mem_malloc(
1670 link_stats_results_size);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001671 if (NULL == wma_handle->link_stats_results) {
1672 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1673 __func__, link_stats_results_size);
1674 return -ENOMEM;
1675 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001676 }
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001677 link_stats_results = wma_handle->link_stats_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001678
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001679 WMA_LOGD("Radio stats Fixed Param:");
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001680 WMA_LOGD("req_id: %u num_radio: %u more_radio_events: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681 fixed_param->request_id, fixed_param->num_radio,
1682 fixed_param->more_radio_events);
1683
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001684 WMA_LOGD("Radio Info: radio_id: %u on_time: %u tx_time: %u rx_time: %u on_time_scan: %u",
1685 radio_stats->radio_id, radio_stats->on_time,
1686 radio_stats->tx_time, radio_stats->rx_time,
1687 radio_stats->on_time_scan);
1688 WMA_LOGD("on_time_nbd: %u on_time_gscan: %u on_time_roam_scan: %u",
1689 radio_stats->on_time_nbd,
1690 radio_stats->on_time_gscan, radio_stats->on_time_roam_scan);
1691 WMA_LOGD("on_time_pno_scan: %u on_time_hs20: %u num_channels: %u",
1692 radio_stats->on_time_pno_scan, radio_stats->on_time_hs20,
1693 radio_stats->num_channels);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001694 WMA_LOGD("on_time_host_scan: %u, on_time_lpi_scan: %u",
1695 radio_stats->on_time_host_scan, radio_stats->on_time_lpi_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001696
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001697 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
1698 link_stats_results->rspId = fixed_param->request_id;
1699 link_stats_results->ifaceId = 0;
1700 link_stats_results->num_radio = fixed_param->num_radio;
1701 link_stats_results->peer_event_number = 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001702
1703 /*
1704 * Backward compatibility:
1705 * There are firmware(s) which will send Radio stats only with
1706 * more_radio_events set to 0 and firmware which sends Radio stats
1707 * followed by tx_power level stats with more_radio_events set to 1.
1708 * if more_radio_events is set to 1, buffer the radio stats and
1709 * wait for tx_power_level stats.
1710 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001711 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
1712
1713 results = (uint8_t *) link_stats_results->results;
1714 t_radio_stats = (uint8_t *) radio_stats;
1715 t_channel_stats = (uint8_t *) channel_stats;
1716
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001717 rs_results = (tSirWifiRadioStat *) &results[0] + radio_stats->radio_id;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001718 rs_results->radio = radio_stats->radio_id;
1719 rs_results->onTime = radio_stats->on_time;
1720 rs_results->txTime = radio_stats->tx_time;
1721 rs_results->rxTime = radio_stats->rx_time;
1722 rs_results->onTimeScan = radio_stats->on_time_scan;
1723 rs_results->onTimeNbd = radio_stats->on_time_nbd;
1724 rs_results->onTimeGscan = radio_stats->on_time_gscan;
1725 rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
1726 rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
1727 rs_results->onTimeHs20 = radio_stats->on_time_hs20;
1728 rs_results->total_num_tx_power_levels = 0;
gaurank kathpalia247554c2017-11-30 19:12:01 +05301729 if (rs_results->tx_time_per_power_level) {
1730 qdf_mem_free(rs_results->tx_time_per_power_level);
1731 rs_results->tx_time_per_power_level = NULL;
1732 }
1733 if (rs_results->channels) {
1734 qdf_mem_free(rs_results->channels);
1735 rs_results->channels = NULL;
1736 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001737 rs_results->numChannels = radio_stats->num_channels;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001738 rs_results->on_time_host_scan = radio_stats->on_time_host_scan;
1739 rs_results->on_time_lpi_scan = radio_stats->on_time_lpi_scan;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001740 if (rs_results->numChannels) {
1741 rs_results->channels = (tSirWifiChannelStats *) qdf_mem_malloc(
1742 radio_stats->num_channels *
1743 chan_stats_size);
1744 if (rs_results->channels == NULL) {
1745 WMA_LOGD("%s: could not allocate mem for channel stats (size=%zu)",
1746 __func__, radio_stats->num_channels * chan_stats_size);
1747 wma_unified_radio_tx_mem_free(handle);
1748 return -ENOMEM;
1749 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001750
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001751 chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
1752 next_chan_offset = WMI_TLV_HDR_SIZE;
1753 WMA_LOGD("Channel Stats Info");
1754 for (count = 0; count < radio_stats->num_channels; count++) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001755 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001756 channel_stats->channel_width,
1757 channel_stats->center_freq,
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001758 channel_stats->center_freq0);
1759 WMA_LOGD("center_freq1 %u radio_awake_time %u cca_busy_time %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001760 channel_stats->center_freq1,
1761 channel_stats->radio_awake_time,
1762 channel_stats->cca_busy_time);
1763 channel_stats++;
1764
1765 qdf_mem_copy(chn_results,
1766 t_channel_stats + next_chan_offset,
1767 chan_stats_size);
1768 chn_results++;
1769 next_chan_offset += sizeof(*channel_stats);
1770 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771 }
1772
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001773 if (link_stats_results->moreResultToFollow) {
1774 /* More results coming, don't post yet */
1775 return 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001776 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001777 link_stats_results->nr_received++;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001778
1779 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1780 /* Not received all radio stats yet, don't post yet */
1781 return 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001782 }
1783
Dundi Ravitejae232cf12018-05-16 18:34:34 +05301784 mac->sme.link_layer_stats_cb(mac->hdd_handle,
1785 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1786 link_stats_results,
1787 mac->sme.ll_stats_context);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001788 wma_unified_radio_tx_mem_free(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001789
1790 return 0;
1791}
1792
Zhang Qiana6e9c102016-12-22 16:47:24 +08001793#ifdef WLAN_PEER_PS_NOTIFICATION
1794/**
1795 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1796 * @handle: wma handle
1797 * @event: FW event
1798 * @len: length of FW event
1799 *
1800 * Once peer STA power state changes, an event will be indicated by
1801 * FW. This function send a link layer state change msg to HDD. HDD
1802 * link layer callback will converts the event to NL msg.
1803 *
1804 * Return: 0 Success. Others fail.
1805 */
1806static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1807 u_int32_t len)
1808{
1809 WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *param_buf;
1810 wmi_peer_sta_ps_statechange_event_fixed_param *fixed_param;
1811 tSirWifiPeerStat *peer_stat;
1812 tSirWifiPeerInfo *peer_info;
1813 tSirLLStatsResults *link_stats_results;
1814 tSirMacAddr mac_address;
1815 uint32_t result_len;
1816 cds_msg_t sme_msg = { 0 };
1817 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1818
1819 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1820
1821 if (!mac) {
1822 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1823 return -EINVAL;
1824 }
1825
1826 if (!mac->sme.link_layer_stats_ext_cb) {
1827 WMA_LOGD("%s: HDD callback is null", __func__);
1828 return -EINVAL;
1829 }
1830
1831 WMA_LOGD("%s: Posting Peer Stats PS event to HDD", __func__);
1832
1833 param_buf = (WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *)event;
1834 fixed_param = param_buf->fixed_param;
1835
1836 result_len = sizeof(tSirLLStatsResults) +
1837 sizeof(tSirWifiPeerStat) +
1838 sizeof(tSirWifiPeerInfo);
1839 link_stats_results = qdf_mem_malloc(result_len);
1840 if (link_stats_results == NULL) {
1841 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1842 return -EINVAL;
1843 }
1844
1845 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->peer_macaddr, &mac_address[0]);
1846 WMA_LOGD("Peer power state change event from FW");
1847 WMA_LOGD("Fixed Param:");
1848 WMA_LOGD("MAC address: %2x:%2x:%2x:%2x:%2x:%2x, Power state: %d",
1849 mac_address[0], mac_address[1], mac_address[2],
1850 mac_address[3], mac_address[4], mac_address[5],
1851 fixed_param->peer_ps_state);
1852
1853 link_stats_results->paramId = WMI_LL_STATS_EXT_PS_CHG;
1854 link_stats_results->num_peers = 1;
1855 link_stats_results->peer_event_number = 1;
1856 link_stats_results->moreResultToFollow = 0;
1857
1858 peer_stat = (tSirWifiPeerStat *)link_stats_results->results;
1859 peer_stat->numPeers = 1;
1860 peer_info = (tSirWifiPeerInfo *)peer_stat->peerInfo;
1861 qdf_mem_copy(&peer_info->peerMacAddress,
1862 &mac_address,
1863 sizeof(tSirMacAddr));
1864 peer_info->power_saving = fixed_param->peer_ps_state;
1865
1866 sme_msg.type = eWMI_SME_LL_STATS_IND;
1867 sme_msg.bodyptr = link_stats_results;
1868 sme_msg.bodyval = 0;
1869
Zhang Qian73c348a2017-03-13 16:15:55 +08001870 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001871 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1872 WMA_LOGE("%s: Fail to post ps change ind msg", __func__);
1873 qdf_mem_free(link_stats_results);
1874 }
1875
1876 return 0;
1877}
1878#else
1879/**
1880 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1881 * @handle: wma handle
1882 * @event: FW event
1883 * @len: length of FW event
1884 *
1885 * Once peer STA power state changes, an event will be indicated by
1886 * FW. This function send a link layer state change msg to HDD. HDD
1887 * link layer callback will converts the event to NL msg.
1888 *
1889 * Return: 0 Success. Others fail.
1890 */
1891static inline int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1892 u_int32_t len)
1893{
1894 return 0;
1895}
1896#endif
1897
1898/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 * wma_register_ll_stats_event_handler() - register link layer stats related
1900 * event handler
1901 * @wma_handle: wma handle
1902 *
1903 * Return: none
1904 */
1905void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
1906{
1907 if (NULL == wma_handle) {
1908 WMA_LOGE("%s: wma_handle is NULL", __func__);
1909 return;
1910 }
1911
1912 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301913 wmi_iface_link_stats_event_id,
Govind Singhd76a5b02016-03-08 15:12:14 +05301914 wma_unified_link_iface_stats_event_handler,
1915 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301917 wmi_peer_link_stats_event_id,
Govind Singhd76a5b02016-03-08 15:12:14 +05301918 wma_unified_link_peer_stats_event_handler,
1919 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301921 wmi_radio_link_stats_link,
Govind Singhd76a5b02016-03-08 15:12:14 +05301922 wma_unified_link_radio_stats_event_handler,
1923 WMA_RX_SERIALIZER_CTX);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001924 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301925 wmi_radio_tx_power_level_stats_event_id,
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001926 wma_unified_radio_tx_power_level_stats_event_handler,
1927 WMA_RX_SERIALIZER_CTX);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001928 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301929 wmi_peer_sta_ps_statechg_event_id,
Zhang Qiana6e9c102016-12-22 16:47:24 +08001930 wma_peer_ps_evt_handler,
1931 WMA_RX_SERIALIZER_CTX);
Zhang Qian73c348a2017-03-13 16:15:55 +08001932 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Mukul Sharma228223a2017-11-03 19:25:39 +05301933 wmi_report_stats_event_id,
Zhang Qian73c348a2017-03-13 16:15:55 +08001934 wma_ll_stats_evt_handler,
1935 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937}
1938
1939
1940/**
1941 * wma_process_ll_stats_clear_req() - clear link layer stats
1942 * @wma: wma handle
1943 * @clearReq: ll stats clear request command params
1944 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301945 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001947QDF_STATUS wma_process_ll_stats_clear_req(tp_wma_handle wma,
1948 const tpSirLLStatsClearReq clearReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949{
Govind Singh4863da42016-03-08 11:45:00 +05301950 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 int ret;
1952
1953 if (!clearReq || !wma) {
1954 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301955 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956 }
1957
Deepak Dhamdhere6adc08e2017-07-27 09:33:22 -07001958 if (!wma->interfaces[clearReq->staId].handle) {
1959 WMA_LOGE("%s: vdev_id %d handle is NULL",
1960 __func__, clearReq->staId);
1961 return QDF_STATUS_E_FAILURE;
1962 }
1963
Govind Singh4863da42016-03-08 11:45:00 +05301964 cmd.stop_req = clearReq->stopReq;
1965 cmd.sta_id = clearReq->staId;
1966 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001967
Govind Singh4863da42016-03-08 11:45:00 +05301968 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
1969 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970 if (ret) {
1971 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301972 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 }
1974
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301975 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976}
1977
1978/**
1979 * wma_process_ll_stats_set_req() - link layer stats set request
1980 * @wma: wma handle
1981 * @setReq: ll stats set request command params
1982 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301983 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001985QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma,
1986 const tpSirLLStatsSetReq setReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987{
Govind Singh4863da42016-03-08 11:45:00 +05301988 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 int ret;
1990
1991 if (!setReq || !wma) {
1992 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301993 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994 }
1995
Govind Singh4863da42016-03-08 11:45:00 +05301996 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
1997 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998 setReq->aggressiveStatisticsGathering;
1999
Govind Singh4863da42016-03-08 11:45:00 +05302000 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
2001 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 if (ret) {
2003 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302004 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 }
2006
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302007 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008}
2009
2010/**
2011 * wma_process_ll_stats_get_req() - link layer stats get request
2012 * @wma:wma handle
2013 * @getReq:ll stats get request command params
2014 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302015 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002017QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
2018 const tpSirLLStatsGetReq getReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002019{
Govind Singh4863da42016-03-08 11:45:00 +05302020 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 int ret;
2022
2023 if (!getReq || !wma) {
2024 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302025 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026 }
2027
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +05302028 if (!wma->interfaces[getReq->staId].vdev_active) {
2029 WMA_LOGE("%s: vdev not created yet", __func__);
2030 return QDF_STATUS_E_FAILURE;
2031 }
2032
Govind Singh4863da42016-03-08 11:45:00 +05302033 cmd.req_id = getReq->reqId;
2034 cmd.param_id_mask = getReq->paramIdMask;
2035 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002036
Govind Singh4863da42016-03-08 11:45:00 +05302037 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
2038 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039 if (ret) {
2040 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302041 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 }
2043
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302044 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045}
2046
2047/**
2048 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
2049 * @wma:wma handle
2050 * @cmd_param_info: data from event
2051 * @len: length
2052 *
2053 * Return: 0 for success or error code
2054 */
2055int wma_unified_link_iface_stats_event_handler(void *handle,
2056 uint8_t *cmd_param_info,
2057 uint32_t len)
2058{
2059 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
2060 wmi_iface_link_stats_event_fixed_param *fixed_param;
Min Liuffb250d2018-07-11 17:35:32 +08002061 wmi_iface_link_stats *link_stats, *iface_link_stats;
2062 wmi_wmm_ac_stats *ac_stats, *iface_ac_stats;
2063 wmi_iface_offload_stats *offload_stats, *iface_offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 tSirLLStatsResults *link_stats_results;
Min Liuffb250d2018-07-11 17:35:32 +08002065 tSirWifiIfaceStat *iface_stat;
2066 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002067 size_t link_stats_size, ac_stats_size, iface_info_size;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002068 size_t link_stats_results_size, offload_stats_size;
2069 size_t total_ac_size, total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070
Dundi Ravitejae232cf12018-05-16 18:34:34 +05302071 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072
Dundi Ravitejae232cf12018-05-16 18:34:34 +05302073 if (!mac) {
2074 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 return -EINVAL;
2076 }
2077
Dundi Ravitejae232cf12018-05-16 18:34:34 +05302078 if (!mac->sme.link_layer_stats_cb) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 WMA_LOGD("%s: HDD callback is null", __func__);
2080 return -EINVAL;
2081 }
2082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
2084 if (!param_tlvs) {
2085 WMA_LOGA("%s: Invalid stats event", __func__);
2086 return -EINVAL;
2087 }
2088
2089 /*
2090 * cmd_param_info contains
2091 * wmi_iface_link_stats_event_fixed_param fixed_param;
2092 * wmi_iface_link_stats iface_link_stats;
2093 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002094 * fixed_param->num_offload_stats * size of(wmi_iface_offload_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 */
2096 fixed_param = param_tlvs->fixed_param;
2097 link_stats = param_tlvs->iface_link_stats;
2098 ac_stats = param_tlvs->ac;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002099 offload_stats = param_tlvs->iface_offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002101 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats) ||
2102 (fixed_param->num_offload_stats && !offload_stats)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
2104 return -EINVAL;
2105 }
Abhinav Kumara03659c2017-12-28 15:18:07 +05302106 if (link_stats->num_ac > WIFI_AC_MAX || link_stats->num_ac >
2107 param_tlvs->num_ac) {
2108 WMA_LOGE("%s: Excess data received from firmware num_ac %d, param_tlvs->num_ac %d",
2109 __func__, link_stats->num_ac, param_tlvs->num_ac);
Vignesh Viswanathan37794ae2017-09-28 15:26:56 +05302110 return -EINVAL;
2111 }
Abhinav Kumara03659c2017-12-28 15:18:07 +05302112 if (fixed_param->num_offload_stats > WMI_OFFLOAD_STATS_TYPE_MAX ||
2113 fixed_param->num_offload_stats >
2114 param_tlvs->num_iface_offload_stats) {
2115 WMA_LOGE("%s: Excess num offload stats recvd from fw: %d, um_iface_offload_stats: %d",
2116 __func__, fixed_param->num_offload_stats,
2117 param_tlvs->num_iface_offload_stats);
Vignesh Viswanathan37794ae2017-09-28 15:26:56 +05302118 return -EINVAL;
2119 }
2120
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002121 link_stats_size = sizeof(tSirWifiIfaceStat);
2122 iface_info_size = sizeof(tSirWifiInterfaceInfo);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002123
Min Liuffb250d2018-07-11 17:35:32 +08002124 ac_stats_size = sizeof(wmi_wmm_ac_stats);
2125 offload_stats_size = sizeof(wmi_iface_offload_stats);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002126
2127 total_ac_size = ac_stats_size * WIFI_AC_MAX;
2128 total_offload_size = offload_stats_size * WMI_OFFLOAD_STATS_TYPE_MAX +
2129 member_size(tSirWifiIfaceStat, num_offload_stats);
2130
2131 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002132
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302133 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002134 if (!link_stats_results) {
2135 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
2136 __func__, link_stats_results_size);
2137 return -ENOMEM;
2138 }
2139
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302140 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141
2142 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
2143 link_stats_results->rspId = fixed_param->request_id;
2144 link_stats_results->ifaceId = fixed_param->vdev_id;
2145 link_stats_results->num_peers = link_stats->num_peers;
2146 link_stats_results->peer_event_number = 0;
2147 link_stats_results->moreResultToFollow = 0;
2148
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002149 /* results is copied to tSirWifiIfaceStat in upper layer
2150 * tSirWifiIfaceStat
2151 * - tSirWifiInterfaceInfo (all fields except roaming is
2152 * filled by host in the upper layer)
2153 * - various members of tSirWifiIfaceStat (from wmi_iface_link_stats)
2154 * - ACs information (from wmi_wmm_ac_stats)
2155 * - num_offload_stats (from fixed param)
2156 * - offload stats (from wmi_iface_offload_stats)
2157 */
2158
Min Liuffb250d2018-07-11 17:35:32 +08002159 iface_stat = (tSirWifiIfaceStat *)link_stats_results->results;
2160
2161 iface_link_stats = &iface_stat->link_stats;
2162 *iface_link_stats = *link_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002163
2164 /* Copy roaming state */
Min Liuffb250d2018-07-11 17:35:32 +08002165 iface_stat->info.roaming = link_stats->roam_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166
Min Liuffb250d2018-07-11 17:35:32 +08002167 iface_ac_stats = &iface_stat->ac_stats[0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 for (count = 0; count < link_stats->num_ac; count++) {
Min Liuffb250d2018-07-11 17:35:32 +08002169 *iface_ac_stats = *ac_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 ac_stats++;
Min Liuffb250d2018-07-11 17:35:32 +08002171 iface_ac_stats++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 }
2173
Min Liuffb250d2018-07-11 17:35:32 +08002174 /* Copy wmi_iface_offload_stats to wifi_iface_offload_stat */
2175 iface_stat->num_offload_stats = fixed_param->num_offload_stats;
2176 iface_offload_stats = &iface_stat->offload_stats[0];
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002177 for (count = 0; count < fixed_param->num_offload_stats; count++) {
Min Liuffb250d2018-07-11 17:35:32 +08002178 *iface_offload_stats = *offload_stats;
2179 offload_stats++;
2180 iface_offload_stats++;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002181 }
2182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 /* call hdd callback with Link Layer Statistics
2184 * vdev_id/ifacId in link_stats_results will be
2185 * used to retrieve the correct HDD context
2186 */
Dundi Ravitejae232cf12018-05-16 18:34:34 +05302187 mac->sme.link_layer_stats_cb(mac->hdd_handle,
2188 WMA_LINK_LAYER_STATS_RESULTS_RSP,
2189 link_stats_results,
2190 mac->sme.ll_stats_context);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302191 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192
2193 return 0;
2194}
2195
Zhang Qian73c348a2017-03-13 16:15:55 +08002196/**
2197 * wma_config_stats_ext_threshold - set threthold for MAC counters
2198 * @wma: wma handler
2199 * @threshold: threhold for MAC counters
2200 *
2201 * For each MAC layer counter, FW holds two copies. One is the current value.
2202 * The other is the last report. Once a current counter's increment is larger
2203 * than the threshold, FW will indicate that counter to host even if the
2204 * monitoring timer does not expire.
2205 *
2206 * Return: None
2207 */
2208void wma_config_stats_ext_threshold(tp_wma_handle wma,
2209 struct sir_ll_ext_stats_threshold *thresh)
2210{
2211 uint32_t len, tag, hdr_len;
2212 uint8_t *buf_ptr;
2213 wmi_buf_t buf;
2214 wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
2215 wmi_chan_cca_stats_thresh *cca;
2216 wmi_peer_signal_stats_thresh *signal;
2217 wmi_tx_stats_thresh *tx;
2218 wmi_rx_stats_thresh *rx;
2219
2220 if (!thresh) {
2221 WMA_LOGE(FL("Invalid threshold input."));
2222 return;
2223 }
2224
2225 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
2226 sizeof(wmi_chan_cca_stats_thresh) +
2227 sizeof(wmi_peer_signal_stats_thresh) +
2228 sizeof(wmi_tx_stats_thresh) +
2229 sizeof(wmi_rx_stats_thresh) +
2230 5 * WMI_TLV_HDR_SIZE;
2231 buf = wmi_buf_alloc(wma->wmi_handle, len);
2232 if (!buf) {
2233 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
2234 return;
2235 }
2236
2237 buf_ptr = (u_int8_t *)wmi_buf_data(buf);
2238 tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
2239 hdr_len = WMITLV_GET_STRUCT_TLVLEN(
2240 wmi_pdev_set_stats_threshold_cmd_fixed_param);
2241 WMA_LOGD(FL("Setting fixed parameters. tag=%d, len=%d"), tag, hdr_len);
2242 cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
2243 WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
2244 cmd->enable_thresh = thresh->enable;
2245 cmd->use_thresh_bitmap = thresh->enable_bitmap;
2246 cmd->gbl_thresh = thresh->global_threshold;
2247 cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
2248 cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
2249 cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
2250 cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
2251 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
2252
2253 tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
2254 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
2255 cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
2256 WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
2257 WMA_LOGD(FL("Setting cca parameters. tag=%d, len=%d"), tag, hdr_len);
2258 cca->idle_time = thresh->cca.idle_time;
2259 cca->tx_time = thresh->cca.tx_time;
2260 cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
2261 cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
2262 cca->rx_busy_time = thresh->cca.rx_busy_time;
2263 cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
2264 cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
2265 cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
2266 WMA_LOGD(FL("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d"),
2267 cca->idle_time, cca->tx_time,
2268 cca->rx_in_bss_time, cca->rx_out_bss_time);
2269 WMA_LOGD(FL("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d"),
2270 cca->rx_busy_time, cca->rx_in_bad_cond_time,
2271 cca->tx_in_bad_cond_time, cca->wlan_not_avail_time);
2272 len += sizeof(wmi_chan_cca_stats_thresh);
2273
2274 signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
2275 tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
2276 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
2277 WMA_LOGD(FL("Setting signal parameters. tag=%d, len=%d"), tag, hdr_len);
2278 WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
2279 signal->per_chain_snr = thresh->signal.snr;
2280 signal->per_chain_nf = thresh->signal.nf;
2281 WMA_LOGD(FL("snr=%d, nf=%d"), signal->per_chain_snr,
2282 signal->per_chain_nf);
2283 len += sizeof(wmi_peer_signal_stats_thresh);
2284
2285 tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
2286 tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
2287 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
2288 WMA_LOGD(FL("Setting TX parameters. tag=%d, len=%d"), tag, len);
2289 WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
2290 tx->tx_msdu_cnt = thresh->tx.msdu;
2291 tx->tx_mpdu_cnt = thresh->tx.mpdu;
2292 tx->tx_ppdu_cnt = thresh->tx.ppdu;
2293 tx->tx_bytes = thresh->tx.bytes;
2294 tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
2295 tx->tx_drop_bytes = thresh->tx.byte_drop;
2296 tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
2297 tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
2298 tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
2299 tx->tx_mpdu_aggr = thresh->tx.aggregation;
2300 tx->tx_succ_mcs = thresh->tx.succ_mcs;
2301 tx->tx_fail_mcs = thresh->tx.fail_mcs;
2302 tx->tx_ppdu_delay = thresh->tx.delay;
2303 WMA_LOGD(FL("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d"),
2304 tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
2305 tx->tx_bytes, tx->tx_msdu_drop_cnt);
2306 WMA_LOGD(FL("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d"),
2307 tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
2308 tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
2309 WMA_LOGD(FL("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d"),
2310 tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
2311 tx->tx_ppdu_delay);
2312 len += sizeof(wmi_tx_stats_thresh);
2313
2314 rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
2315 tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
2316 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
2317 WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
2318 WMA_LOGD(FL("Setting RX parameters. tag=%d, len=%d"), tag, hdr_len);
2319 rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
2320 rx->mac_rx_bytes = thresh->rx.bytes;
2321 rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
2322 rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
2323 rx->rx_disorder_cnt = thresh->rx.disorder;
2324 rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
2325 rx->rx_mpdu_dup_cnt = thresh->rx.mpdu_dup;
2326 rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
2327 rx->rx_mpdu_aggr = thresh->rx.aggregation;
2328 rx->rx_mcs = thresh->rx.mcs;
2329 rx->sta_ps_inds = thresh->rx.ps_inds;
2330 rx->sta_ps_durs = thresh->rx.ps_durs;
2331 rx->rx_probe_reqs = thresh->rx.probe_reqs;
2332 rx->rx_oth_mgmts = thresh->rx.other_mgmt;
2333 WMA_LOGD(FL("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d"),
2334 rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
2335 rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
2336 WMA_LOGD(FL("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d"),
2337 rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
2338 rx->rx_mpdu_aggr, rx->rx_mcs);
2339 WMA_LOGD(FL("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d"),
2340 rx->sta_ps_inds, rx->sta_ps_durs,
2341 rx->rx_probe_reqs, rx->rx_oth_mgmts);
2342 len += sizeof(wmi_rx_stats_thresh);
2343
2344 WMA_LOGA("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
2345 WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
2346 if (EOK != wmi_unified_cmd_send(wma->wmi_handle,
2347 buf, len,
2348 WMI_PDEV_SET_STATS_THRESHOLD_CMDID)) {
2349 WMA_LOGE("Failed to send WMI_PDEV_SET_STATS_THRESHOLD_CMDID");
2350 wmi_buf_free(buf);
2351 }
2352}
2353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2355
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002356#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357/**
2358 * wma_update_pdev_stats() - update pdev stats
2359 * @wma: wma handle
2360 * @pdev_stats: pdev stats
2361 *
2362 * Return: none
2363 */
2364static void wma_update_pdev_stats(tp_wma_handle wma,
2365 wmi_pdev_stats *pdev_stats)
2366{
2367 tAniGetPEStatsRsp *stats_rsp_params;
2368 uint32_t temp_mask;
2369 uint8_t *stats_buf;
2370 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2371 struct wma_txrx_node *node;
2372 uint8_t i;
2373
2374 for (i = 0; i < wma->max_bssid; i++) {
2375 node = &wma->interfaces[i];
2376 stats_rsp_params = node->stats_rsp;
2377 if (stats_rsp_params) {
2378 node->fw_stats_set |= FW_PDEV_STATS_SET;
2379 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
2380 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2381 temp_mask = stats_rsp_params->statsMask;
2382 if (temp_mask & (1 << eCsrSummaryStats))
2383 stats_buf += sizeof(tCsrSummaryStatsInfo);
2384
2385 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2386 classa_stats =
2387 (tCsrGlobalClassAStatsInfo *) stats_buf;
2388 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
2389 }
2390 }
2391 }
2392}
2393
2394/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302395 * wma_vdev_stats_lost_link_helper() - helper function to extract
2396 * lost link information from vdev statistics event while deleting BSS.
2397 * @wma: WMA handle
2398 * @vdev_stats: statistics information from firmware
2399 *
2400 * This is for informing HDD to collect lost link information while
2401 * disconnection. Following conditions to check
2402 * 1. vdev is up
2403 * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to
2404 * zero, hence add the check here to indicate the event comes during deleting
2405 * BSS
2406 * 3. DELETE_BSS is the request message queued. Put this condition check on the
2407 * last one as it consumes more resource searching entries in the list
2408 *
2409 * Return: none
2410 */
2411static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma,
2412 wmi_vdev_stats *vdev_stats)
2413{
2414 struct wma_txrx_node *node;
2415 int32_t rssi;
2416 struct wma_target_req *req_msg;
2417 static const uint8_t zero_mac[QDF_MAC_ADDR_SIZE] = {0};
Naveen Rawatf440a132017-05-05 12:27:39 -07002418 int32_t bcn_snr, dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302419
Rajeev Kumar0b071172018-02-08 18:21:57 -08002420 if (vdev_stats->vdev_id >= wma->max_bssid) {
2421 WMA_LOGE("%s: Invalid vdev_id %hu",
2422 __func__, vdev_stats->vdev_id);
2423 return;
2424 }
2425
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302426 node = &wma->interfaces[vdev_stats->vdev_id];
Mukul Sharmaf9047232017-03-02 16:58:56 +05302427 if (wma_is_vdev_up(vdev_stats->vdev_id) &&
Hanumanth Reddy Pothulaaef3c7f2017-05-18 12:19:23 +05302428 !qdf_mem_cmp(node->bssid, zero_mac, QDF_MAC_ADDR_SIZE)) {
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302429 req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id,
2430 WMA_TARGET_REQ_TYPE_VDEV_STOP);
2431 if ((NULL == req_msg) ||
2432 (WMA_DELETE_BSS_REQ != req_msg->msg_type)) {
2433 WMA_LOGD(FL("cannot find DELETE_BSS request message"));
2434 return;
2435 }
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002436 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2437 dat_snr = vdev_stats->vdev_snr.dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302438 WMA_LOGD(FL("get vdev id %d, beancon snr %d, data snr %d"),
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002439 vdev_stats->vdev_id, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302440
2441 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002442 rssi = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302443 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002444 rssi = dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302445 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302446 rssi = WMA_TGT_INVALID_SNR;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302447
2448 /* Get the absolute rssi value from the current rssi value */
2449 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2450 wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi);
2451 }
2452}
2453
2454/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 * wma_update_vdev_stats() - update vdev stats
2456 * @wma: wma handle
2457 * @vdev_stats: vdev stats
2458 *
2459 * Return: none
2460 */
2461static void wma_update_vdev_stats(tp_wma_handle wma,
2462 wmi_vdev_stats *vdev_stats)
2463{
2464 tAniGetPEStatsRsp *stats_rsp_params;
2465 tCsrSummaryStatsInfo *summary_stats = NULL;
2466 uint8_t *stats_buf;
2467 struct wma_txrx_node *node;
2468 uint8_t i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002469 int32_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302470 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002472 struct scheduler_msg sme_msg = { 0 };
Naveen Rawatf440a132017-05-05 12:27:39 -07002473 int32_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474
Rajeev Kumar0b071172018-02-08 18:21:57 -08002475 if (vdev_stats->vdev_id >= wma->max_bssid) {
2476 WMA_LOGE("%s: Invalid vdev_id %hu",
2477 __func__, vdev_stats->vdev_id);
2478 return;
2479 }
2480
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002481 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2482 dat_snr = vdev_stats->vdev_snr.dat_snr;
2483 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
2484 vdev_stats->vdev_id, bcn_snr, dat_snr);
2485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 node = &wma->interfaces[vdev_stats->vdev_id];
2487 stats_rsp_params = node->stats_rsp;
2488 if (stats_rsp_params) {
2489 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2490 node->fw_stats_set |= FW_VDEV_STATS_SET;
2491 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
2492 vdev_stats->vdev_id);
2493 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
2494 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
2495 for (i = 0; i < 4; i++) {
2496 summary_stats->tx_frm_cnt[i] =
2497 vdev_stats->tx_frm_cnt[i];
2498 summary_stats->fail_cnt[i] =
2499 vdev_stats->fail_cnt[i];
2500 summary_stats->multiple_retry_cnt[i] =
2501 vdev_stats->multiple_retry_cnt[i];
2502 }
2503
2504 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
2505 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
2506 summary_stats->rx_discard_cnt =
2507 vdev_stats->rx_discard_cnt;
2508 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
2509 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
2510 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002511 /* Update SNR and RSSI in SummaryStats */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302512 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002513 summary_stats->snr = bcn_snr;
2514 summary_stats->rssi =
2515 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302516 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002517 summary_stats->snr = dat_snr;
2518 summary_stats->rssi =
Naveen Rawatf440a132017-05-05 12:27:39 -07002519 dat_snr + WMA_TGT_NOISE_FLOOR_DBM;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002520 } else {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302521 summary_stats->snr = WMA_TGT_INVALID_SNR;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002522 summary_stats->rssi = 0;
2523 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 }
2525 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526
2527 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302528 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
2529 rssi = bcn_snr;
2530 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2531 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
2532 rssi = dat_snr;
2533 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2534 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 /*
2536 * Firmware sends invalid snr till it sees
2537 * Beacon/Data after connection since after
2538 * vdev up fw resets the snr to invalid.
2539 * In this duartion Host will return the last know
2540 * rssi during connection.
2541 */
2542 WMA_LOGE("Invalid SNR from firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 }
2544
2545 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
2546 pGetRssiReq->sessionId);
2547
2548 /* update the average rssi value to UMAC layer */
2549 if (NULL != pGetRssiReq->rssiCallback) {
2550 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
2551 pGetRssiReq->staId,
2552 pGetRssiReq->pDevContext);
2553 }
2554
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302555 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 wma->pGetRssiReq = NULL;
2557 }
2558
2559 if (node->psnr_req) {
2560 tAniGetSnrReq *p_snr_req = node->psnr_req;
2561
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302562 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07002563 p_snr_req->snr = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302564 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002565 p_snr_req->snr = dat_snr;
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002566 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302567 p_snr_req->snr = WMA_TGT_INVALID_SNR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568
2569 sme_msg.type = eWNI_SME_SNR_IND;
2570 sme_msg.bodyptr = p_snr_req;
2571 sme_msg.bodyval = 0;
2572
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002573 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302574 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302576 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 }
2578
2579 node->psnr_req = NULL;
2580 }
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302581 wma_vdev_stats_lost_link_helper(wma, vdev_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582}
2583
2584/**
2585 * wma_post_stats() - update stats to PE
2586 * @wma: wma handle
2587 * @node: txrx node
2588 *
2589 * Return: none
2590 */
2591static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
2592{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 /* send response to UMAC */
Naveen Rawat3c49d192017-03-02 18:43:16 -08002594 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, node->stats_rsp, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 node->stats_rsp = NULL;
2596 node->fw_stats_set = 0;
2597}
2598
2599/**
2600 * wma_update_peer_stats() - update peer stats
2601 * @wma: wma handle
2602 * @peer_stats: peer stats
2603 *
2604 * Return: none
2605 */
2606static void wma_update_peer_stats(tp_wma_handle wma,
2607 wmi_peer_stats *peer_stats)
2608{
2609 tAniGetPEStatsRsp *stats_rsp_params;
2610 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2611 struct wma_txrx_node *node;
2612 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
2613 uint32_t temp_mask;
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +05302614 uint8_t nss;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615
2616 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
2617 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
2618 return;
2619
2620 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002621 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2622 if (stats_rsp_params) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623 node->fw_stats_set |= FW_PEER_STATS_SET;
2624 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2626 temp_mask = stats_rsp_params->statsMask;
2627 if (temp_mask & (1 << eCsrSummaryStats))
2628 stats_buf += sizeof(tCsrSummaryStatsInfo);
2629
2630 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2631 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
2632 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002633 /* The linkspeed returned by fw is in kbps so convert
2634 * it in to units of 500kbps which is expected by UMAC
2635 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636 if (peer_stats->peer_tx_rate) {
2637 classa_stats->tx_rate =
2638 peer_stats->peer_tx_rate / 500;
2639 }
2640
2641 classa_stats->tx_rate_flags = node->rate_flags;
Naveen Rawatea1564b2018-05-17 15:56:11 -07002642 if (!(node->rate_flags & TX_RATE_LEGACY)) {
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +05302643 nss = node->nss;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644 classa_stats->mcs_index =
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002645 wma_get_mcs_idx(
2646 (peer_stats->peer_tx_rate /
2647 100), node->rate_flags,
Hanumanth Reddy Pothula834f9432018-05-30 14:20:32 +05302648 &nss, &mcsRateFlags);
2649 classa_stats->nss = nss;
Jeff Johnsonad0b2c62017-03-16 14:37:38 -07002650 classa_stats->mcs_rate_flags = mcsRateFlags;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651 }
2652 /* FW returns tx power in intervals of 0.5 dBm
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002653 * Convert it back to intervals of 1 dBm
2654 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655 classa_stats->max_pwr =
2656 roundup(classa_stats->max_pwr, 2) >> 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658 }
2659}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002660#endif /* WMA_GET_STATISTICS_RSP */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002661
2662/**
2663 * wma_post_link_status() - post link status to SME
2664 * @pGetLinkStatus: SME Link status
2665 * @link_status: Link status
2666 *
2667 * Return: none
2668 */
2669void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
2670 uint8_t link_status)
2671{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302672 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002673 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674
2675 pGetLinkStatus->linkStatus = link_status;
2676 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
2677 sme_msg.bodyptr = pGetLinkStatus;
2678 sme_msg.bodyval = 0;
2679
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002680 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302681 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302683 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 }
2685}
2686
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002687#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302689 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
2690 * @wma: wma handle
2691 * @rssi_stats: rssi stats
2692 * @rssi_per_chain_stats: buffer where rssi stats to be stored
2693 *
2694 * This function stores per chain rssi stats received from fw for all vdevs for
2695 * which the stats were requested into a csr stats structure.
2696 *
2697 * Return: void
2698 */
2699static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
2700 wmi_rssi_stats *rssi_stats,
2701 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
2702{
2703 int i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002704 int32_t bcn_snr, dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302705
2706 for (i = 0; i < NUM_CHAINS_MAX; i++) {
2707 bcn_snr = rssi_stats->rssi_avg_beacon[i];
2708 dat_snr = rssi_stats->rssi_avg_data[i];
2709 WMA_LOGD("chain %d beacon snr %d data snr %d",
2710 i, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302711 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302712 rssi_per_chain_stats->rssi[i] = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302713 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
2714 rssi_per_chain_stats->rssi[i] = dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302715 else
2716 /*
2717 * Firmware sends invalid snr till it sees
2718 * Beacon/Data after connection since after
2719 * vdev up fw resets the snr to invalid.
2720 * In this duartion Host will return an invalid rssi
2721 * value.
2722 */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302723 rssi_per_chain_stats->rssi[i] = WMA_TGT_INVALID_SNR;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302724
2725 /*
2726 * Get the absolute rssi value from the current rssi value the
2727 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
2728 */
2729 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
2730 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
2731 rssi_per_chain_stats->peer_mac_addr);
2732 }
2733}
2734
2735/**
2736 * wma_update_rssi_stats() - to update rssi stats for all vdevs
2737 * for which the stats were requested.
2738 * @wma: wma handle
2739 * @rssi_stats: rssi stats
2740 *
2741 * This function updates the rssi stats for all vdevs for which
2742 * the stats were requested.
2743 *
2744 * Return: void
2745 */
2746static void wma_update_rssi_stats(tp_wma_handle wma,
2747 wmi_rssi_stats *rssi_stats)
2748{
2749 tAniGetPEStatsRsp *stats_rsp_params;
2750 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
2751 struct wma_txrx_node *node;
2752 uint8_t *stats_buf;
2753 uint32_t temp_mask;
2754 uint8_t vdev_id;
2755
Rajeev Kumar0b071172018-02-08 18:21:57 -08002756 if (rssi_stats->vdev_id >= wma->max_bssid) {
2757 WMA_LOGE("%s: Invalid vdev_id %hu",
2758 __func__, rssi_stats->vdev_id);
2759 return;
2760 }
2761
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302762 vdev_id = rssi_stats->vdev_id;
2763 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002764 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2765 if (stats_rsp_params) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302766 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
2767 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
2768 vdev_id);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302769 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2770 temp_mask = stats_rsp_params->statsMask;
2771
2772 if (temp_mask & (1 << eCsrSummaryStats))
2773 stats_buf += sizeof(tCsrSummaryStatsInfo);
2774 if (temp_mask & (1 << eCsrGlobalClassAStats))
2775 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302776 if (temp_mask & (1 << eCsrGlobalClassDStats))
2777 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302778
2779 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
2780 rssi_per_chain_stats =
2781 (struct csr_per_chain_rssi_stats_info *)stats_buf;
2782 wma_update_per_chain_rssi_stats(wma, rssi_stats,
2783 rssi_per_chain_stats);
2784 }
2785 }
2786}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002787#endif /* QCA_SUPPORT_CP_STATS */
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302788
2789/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002790 * wma_link_status_event_handler() - link status event handler
2791 * @handle: wma handle
2792 * @cmd_param_info: data from event
2793 * @len: length
2794 *
2795 * Return: 0 for success or error code
2796 */
2797int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
2798 uint32_t len)
2799{
2800 tp_wma_handle wma = (tp_wma_handle) handle;
2801 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
2802 wmi_vdev_rate_stats_event_fixed_param *event;
2803 wmi_vdev_rate_ht_info *ht_info;
2804 struct wma_txrx_node *intr = wma->interfaces;
2805 uint8_t link_status = LINK_STATUS_LEGACY;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002806 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807
2808 param_buf =
2809 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2810 if (!param_buf) {
2811 WMA_LOGA("%s: Invalid stats event", __func__);
2812 return -EINVAL;
2813 }
2814
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002815 event = (wmi_vdev_rate_stats_event_fixed_param *)
2816 param_buf->fixed_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
2818
2819 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002820
2821 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
Abhinav Kumara03659c2017-12-28 15:18:07 +05302822 sizeof(*event)) / sizeof(*ht_info)) ||
2823 event->num_vdev_stats > param_buf->num_ht_info) {
2824 WMA_LOGE("%s: excess vdev_stats buffers:%d, num_ht_info:%d",
2825 __func__, event->num_vdev_stats,
2826 param_buf->num_ht_info);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002827 return -EINVAL;
2828 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
2830 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
2831 __func__, ht_info->vdevid, ht_info->tx_nss,
2832 ht_info->rx_nss, ht_info->tx_preamble,
2833 ht_info->rx_preamble);
2834 if (ht_info->vdevid < wma->max_bssid
2835 && intr[ht_info->vdevid].plink_status_req) {
2836 if (ht_info->tx_nss || ht_info->rx_nss)
2837 link_status = LINK_STATUS_MIMO;
2838
2839 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
2840 (ht_info->rx_preamble == LINK_RATE_VHT))
2841 link_status |= LINK_STATUS_VHT;
2842
2843 if (intr[ht_info->vdevid].nss == 2)
2844 link_status |= LINK_SUPPORT_MIMO;
2845
2846 if (intr[ht_info->vdevid].rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -07002847 (TX_RATE_VHT20 | TX_RATE_VHT40 |
2848 TX_RATE_VHT80))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002849 link_status |= LINK_SUPPORT_VHT;
2850
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002851 wma_post_link_status(
2852 intr[ht_info->vdevid].plink_status_req,
2853 link_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002854 intr[ht_info->vdevid].plink_status_req = NULL;
2855 link_status = LINK_STATUS_LEGACY;
2856 }
2857
2858 ht_info++;
2859 }
2860
2861 return 0;
2862}
2863
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302864int wma_rso_cmd_status_event_handler(wmi_roam_event_fixed_param *wmi_event)
2865{
2866 struct rso_cmd_status *rso_status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -07002867 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302868 QDF_STATUS qdf_status;
2869
2870 rso_status = qdf_mem_malloc(sizeof(*rso_status));
2871 if (!rso_status) {
2872 WMA_LOGE("%s: malloc fails for rso cmd status", __func__);
2873 return -ENOMEM;
2874 }
2875
2876 rso_status->vdev_id = wmi_event->vdev_id;
2877 if (WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS == wmi_event->notif)
2878 rso_status->status = true;
2879 else if (WMI_ROAM_NOTIF_SCAN_MODE_FAIL == wmi_event->notif)
2880 rso_status->status = false;
2881 sme_msg.type = eWNI_SME_RSO_CMD_STATUS_IND;
2882 sme_msg.bodyptr = rso_status;
2883 sme_msg.bodyval = 0;
Sandeep Puligilla1f1e4002018-08-18 12:15:01 -07002884 WMA_LOGD("%s: Post RSO cmd status to SME", __func__);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302885
2886 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2887 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2888 WMA_LOGE("%s: fail to post RSO cmd status to SME", __func__);
2889 qdf_mem_free(rso_status);
2890 }
2891 return 0;
2892}
2893
Naveen Rawatfa2a1002018-05-17 16:06:37 -07002894#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895/**
Will Huanga9814592017-05-24 15:47:58 +08002896 * wma_handle_sta_peer_info() - handle peer information in
2897 * peer stats
2898 * @num_peer_stats: peer number
2899 * @peer_stats: peer stats received from firmware
2900 * @peer_macaddr: the specified mac address
2901 * @sapaddr: sap mac address
2902 *
2903 * This function will send eWNI_SME_GET_PEER_INFO_IND
2904 * to sme with stations' information
2905 *
2906 */
2907static void wma_handle_sta_peer_info(uint32_t num_peer_stats,
2908 wmi_peer_stats *peer_stats,
2909 struct qdf_mac_addr peer_macaddr,
2910 uint8_t *sapaddr)
2911{
2912 QDF_STATUS qdf_status;
2913 wmi_mac_addr temp_addr;
2914 struct sir_peer_info_resp *peer_info;
2915 struct scheduler_msg sme_msg = {0};
2916 uint32_t i;
2917 uint32_t j = 0;
2918
2919 if (!qdf_is_macaddr_broadcast(&peer_macaddr)) {
2920 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_macaddr.bytes, &temp_addr);
2921 for (i = 0; i < num_peer_stats; i++) {
2922 if ((((temp_addr.mac_addr47to32) & 0x0000ffff) ==
2923 ((peer_stats->peer_macaddr.mac_addr47to32) &
2924 0x0000ffff))
2925 && (temp_addr.mac_addr31to0 ==
2926 peer_stats->peer_macaddr.mac_addr31to0)) {
2927
2928 break;
2929 }
2930 peer_stats = peer_stats + 1;
2931 }
2932 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2933 sizeof(peer_info->info[0]));
2934 if (NULL == peer_info) {
2935 WMA_LOGE("%s: Memory allocation failed.", __func__);
2936 return;
2937 }
2938 if (i < num_peer_stats) {
2939 peer_info->count = 1;
2940 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2941 peer_info->info[0].peer_macaddr.bytes);
2942 peer_info->info[0].rssi = peer_stats->peer_rssi;
2943 peer_info->info[0].tx_rate = peer_stats->peer_tx_rate;
2944 peer_info->info[0].rx_rate = peer_stats->peer_rx_rate;
2945 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2946 __func__,
2947 peer_info->info[0].peer_macaddr.bytes,
2948 peer_stats->peer_rssi,
2949 peer_stats->peer_tx_rate,
2950 peer_stats->peer_rx_rate);
2951 } else {
2952 WMA_LOGE("%s: no match mac address", __func__);
2953 peer_info->count = 0;
2954 }
2955 } else {
2956 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2957 num_peer_stats * sizeof(peer_info->info[0]));
2958 if (NULL == peer_info) {
2959 WMA_LOGE("%s: Memory allocation failed.", __func__);
2960 return;
2961 }
2962 peer_info->count = num_peer_stats;
2963
2964 for (i = 0; i < num_peer_stats; i++) {
2965 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2966 peer_info->info[j].peer_macaddr.bytes);
2967 peer_info->info[j].rssi = peer_stats->peer_rssi;
2968 peer_info->info[j].tx_rate = peer_stats->peer_tx_rate;
2969 peer_info->info[j].rx_rate = peer_stats->peer_rx_rate;
2970 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2971 __func__,
2972 peer_info->info[j].peer_macaddr.bytes,
2973 peer_stats->peer_rssi,
2974 peer_stats->peer_tx_rate,
2975 peer_stats->peer_rx_rate);
2976 if (!qdf_mem_cmp(peer_info->info[j].peer_macaddr.bytes,
2977 sapaddr, QDF_MAC_ADDR_SIZE)) {
2978 peer_info->count = peer_info->count - 1;
2979 } else {
2980 j++;
2981 }
2982 peer_stats = peer_stats + 1;
2983 }
2984 WMA_LOGD("WDA send peer num %d", peer_info->count);
2985 }
2986
2987 sme_msg.type = eWNI_SME_GET_PEER_INFO_IND;
2988 sme_msg.bodyptr = peer_info;
2989 sme_msg.bodyval = 0;
2990
2991 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2992 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2993 WMA_LOGE("%s: Fail to post get rssi msg", __func__);
2994 qdf_mem_free(peer_info);
2995 }
2996
2997 return;
2998}
2999
3000/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 * wma_stats_event_handler() - stats event handler
3002 * @handle: wma handle
3003 * @cmd_param_info: data from event
3004 * @len: length
3005 *
3006 * Return: 0 for success or error code
3007 */
3008int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
3009 uint32_t len)
3010{
3011 tp_wma_handle wma = (tp_wma_handle) handle;
3012 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
3013 wmi_stats_event_fixed_param *event;
3014 wmi_pdev_stats *pdev_stats;
3015 wmi_vdev_stats *vdev_stats;
3016 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303017 wmi_rssi_stats *rssi_stats;
3018 wmi_per_chain_rssi_stats *rssi_event;
3019 struct wma_txrx_node *node;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003020 uint8_t *temp;
3021 uint32_t i;
3022 uint32_t buf_len = 0;
3023 bool excess_data = false;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303024 wmi_congestion_stats *congestion_stats;
3025 tpAniSirGlobal mac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
3028 if (!param_buf) {
3029 WMA_LOGA("%s: Invalid stats event", __func__);
3030 return -EINVAL;
3031 }
3032 event = param_buf->fixed_param;
3033 temp = (uint8_t *) param_buf->data;
Abhinav Kumara03659c2017-12-28 15:18:07 +05303034 if ((event->num_pdev_stats + event->num_vdev_stats +
3035 event->num_peer_stats) > param_buf->num_data) {
3036 WMA_LOGE("%s: Invalid num_pdev_stats:%d or num_vdev_stats:%d or num_peer_stats:%d",
3037 __func__, event->num_pdev_stats, event->num_vdev_stats,
3038 event->num_peer_stats);
3039 return -EINVAL;
3040 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003042 do {
3043 if (event->num_pdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
3044 sizeof(*event)) / sizeof(*pdev_stats))) {
3045 excess_data = true;
3046 break;
3047 } else {
3048 buf_len += event->num_pdev_stats * sizeof(*pdev_stats);
3049 }
3050
3051 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
3052 sizeof(*event)) / sizeof(*vdev_stats))) {
3053 excess_data = true;
3054 break;
3055 } else {
3056 buf_len += event->num_vdev_stats * sizeof(*vdev_stats);
3057 }
3058
3059 if (event->num_peer_stats > ((WMI_SVC_MSG_MAX_SIZE -
3060 sizeof(*event)) / sizeof(*peer_stats))) {
3061 excess_data = true;
3062 break;
3063 } else {
3064 buf_len += event->num_peer_stats * sizeof(*peer_stats);
3065 }
3066
3067 rssi_event =
3068 (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
bingsf9047652017-08-31 08:05:54 +08003069 if (rssi_event) {
3070 if (rssi_event->num_per_chain_rssi_stats >
3071 ((WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) /
3072 sizeof(*rssi_event))) {
3073 excess_data = true;
3074 break;
3075 } else {
3076 buf_len += sizeof(*rssi_event) *
3077 rssi_event->num_per_chain_rssi_stats;
3078 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003079 }
3080 } while (0);
3081
3082 if (excess_data ||
Rakshith Suresh Patkar90517362018-05-25 14:09:10 +05303083 (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*event))) {
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07003084 WMA_LOGE("excess wmi buffer: stats pdev %d vdev %d peer %d",
3085 event->num_pdev_stats, event->num_vdev_stats,
3086 event->num_peer_stats);
3087 QDF_ASSERT(0);
3088 return -EINVAL;
3089 }
3090
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003091 if (event->num_pdev_stats > 0) {
3092 for (i = 0; i < event->num_pdev_stats; i++) {
3093 pdev_stats = (wmi_pdev_stats *) temp;
3094 wma_update_pdev_stats(wma, pdev_stats);
3095 temp += sizeof(wmi_pdev_stats);
3096 }
3097 }
3098
3099 if (event->num_vdev_stats > 0) {
3100 for (i = 0; i < event->num_vdev_stats; i++) {
3101 vdev_stats = (wmi_vdev_stats *) temp;
3102 wma_update_vdev_stats(wma, vdev_stats);
3103 temp += sizeof(wmi_vdev_stats);
3104 }
3105 }
3106
3107 if (event->num_peer_stats > 0) {
Will Huanga9814592017-05-24 15:47:58 +08003108 if (wma->get_sta_peer_info == true) {
3109 wma_handle_sta_peer_info(event->num_peer_stats,
3110 (wmi_peer_stats *)temp,
3111 wma->peer_macaddr,
3112 wma->myaddr);
3113 } else {
3114 for (i = 0; i < event->num_peer_stats; i++) {
3115 peer_stats = (wmi_peer_stats *) temp;
3116 wma_update_peer_stats(wma, peer_stats);
3117 temp += sizeof(wmi_peer_stats);
3118 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003119 }
3120 }
3121
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303122 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
3123 if (rssi_event) {
Abhinav Kumara03659c2017-12-28 15:18:07 +05303124 if (rssi_event->num_per_chain_rssi_stats >
3125 param_buf->num_rssi_stats) {
3126 WMA_LOGE("%s: Invalid num_per_chain_rssi_stats:%d",
3127 __func__, rssi_event->num_per_chain_rssi_stats);
3128 return -EINVAL;
3129 }
Himanshu Agarwalcd8a84a2016-07-21 14:59:50 +05303130 if (((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
3131 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) &&
3132 ((rssi_event->tlv_header & 0x0000FFFF) ==
3133 WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats))) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303134 if (rssi_event->num_per_chain_rssi_stats > 0) {
3135 temp = (uint8_t *) rssi_event;
3136 temp += sizeof(*rssi_event);
Dustin Brownc4a5ba22016-11-10 17:21:18 -08003137
3138 /* skip past struct array tlv header */
3139 temp += WMI_TLV_HDR_SIZE;
3140
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303141 for (i = 0;
3142 i < rssi_event->num_per_chain_rssi_stats;
3143 i++) {
3144 rssi_stats = (wmi_rssi_stats *)temp;
3145 wma_update_rssi_stats(wma, rssi_stats);
3146 temp += sizeof(wmi_rssi_stats);
3147 }
3148 }
3149 }
3150 }
3151
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303152 congestion_stats = (wmi_congestion_stats *) param_buf->congestion_stats;
3153 if (congestion_stats) {
3154 if (((congestion_stats->tlv_header & 0xFFFF0000) >> 16 ==
3155 WMITLV_TAG_STRUC_wmi_congestion_stats) &&
3156 ((congestion_stats->tlv_header & 0x0000FFFF) ==
3157 WMITLV_GET_STRUCT_TLVLEN(wmi_congestion_stats))) {
3158 mac = cds_get_context(QDF_MODULE_ID_PE);
3159 if (!mac) {
3160 WMA_LOGE("%s: Invalid mac", __func__);
3161 return -EINVAL;
3162 }
3163 if (!mac->sme.congestion_cb) {
3164 WMA_LOGE("%s: Callback not registered",
3165 __func__);
3166 return -EINVAL;
3167 }
3168 WMA_LOGI("%s: congestion %d", __func__,
3169 congestion_stats->congestion);
Jeff Johnson6aaaa992018-06-30 10:43:04 -07003170 mac->sme.congestion_cb(mac->hdd_handle,
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303171 congestion_stats->congestion,
3172 congestion_stats->vdev_id);
3173 }
3174 }
3175
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303176 for (i = 0; i < wma->max_bssid; i++) {
3177 node = &wma->interfaces[i];
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003178 if (node->fw_stats_set & FW_PEER_STATS_SET)
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303179 wma_post_stats(wma, node);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303180 }
3181
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 return 0;
3183}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07003184#endif /* QCA_SUPPORT_CP_STATS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185
3186/**
Will Huanga9814592017-05-24 15:47:58 +08003187 * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct
3188 * @wma: wma interface
3189 * @stats_info: WMI peer info pointer
3190 * @peer_info: SIR peer info pointer
3191 *
3192 * This function will fill SIR peer info from WMI peer info struct
3193 *
3194 * Return: None
3195 */
3196static void wma_fill_peer_info(tp_wma_handle wma,
3197 wmi_peer_stats_info *stats_info,
3198 struct sir_peer_info_ext *peer_info)
3199{
3200 peer_info->tx_packets = stats_info->tx_packets.low_32;
3201 peer_info->tx_bytes = stats_info->tx_bytes.high_32;
3202 peer_info->tx_bytes <<= 32;
3203 peer_info->tx_bytes += stats_info->tx_bytes.low_32;
3204 peer_info->rx_packets = stats_info->rx_packets.low_32;
3205 peer_info->rx_bytes = stats_info->rx_bytes.high_32;
3206 peer_info->rx_bytes <<= 32;
3207 peer_info->rx_bytes += stats_info->rx_bytes.low_32;
3208 peer_info->tx_retries = stats_info->tx_retries;
3209 peer_info->tx_failed = stats_info->tx_failed;
3210 peer_info->rssi = stats_info->peer_rssi;
3211 peer_info->tx_rate = stats_info->last_tx_bitrate_kbps;
3212 peer_info->tx_rate_code = stats_info->last_tx_rate_code;
3213 peer_info->rx_rate = stats_info->last_rx_bitrate_kbps;
3214 peer_info->rx_rate_code = stats_info->last_rx_rate_code;
3215}
3216
3217/**
3218 * wma_peer_info_ext_rsp() - process peer ext info ext
3219 * @handle: wma interface
3220 * @buf: wmi event buf pointer
3221 *
3222 * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME
3223 *
3224 * Return: 0 on success, error code otherwise
3225 */
3226static QDF_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf)
3227{
3228 wmi_peer_stats_info_event_fixed_param *event;
3229 wmi_peer_stats_info *stats_info;
3230 struct sir_peer_info_ext_resp *resp;
3231 struct sir_peer_info_ext *peer_info;
3232 struct scheduler_msg sme_msg = {0};
3233 int i, j = 0;
3234 QDF_STATUS qdf_status;
3235
3236 event = (wmi_peer_stats_info_event_fixed_param *)buf;
3237 stats_info = (wmi_peer_stats_info *)(buf +
3238 sizeof(wmi_peer_stats_info_event_fixed_param));
3239
3240 if (wma->get_one_peer_info) {
3241 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3242 sizeof(resp->info[0]));
3243 if (!resp) {
3244 WMA_LOGE(FL("resp allocation failed."));
3245 return QDF_STATUS_E_NOMEM;
3246 }
3247 resp->count = 0;
3248 peer_info = &resp->info[0];
3249 for (i = 0; i < event->num_peers; i++) {
3250 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3251 peer_info->peer_macaddr.bytes);
3252
3253 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3254 wma->peer_macaddr.bytes,
3255 QDF_MAC_ADDR_SIZE)) {
3256 wma_fill_peer_info(wma, stats_info, peer_info);
3257 resp->count++;
3258 break;
3259 }
3260
3261 stats_info = stats_info + 1;
3262 }
3263 } else {
3264 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3265 event->num_peers * sizeof(resp->info[0]));
3266 if (!resp) {
3267 WMA_LOGE(FL("resp allocation failed."));
3268 return QDF_STATUS_E_NOMEM;
3269 }
3270 resp->count = event->num_peers;
3271 for (i = 0; i < event->num_peers; i++) {
3272 peer_info = &resp->info[j];
3273 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3274 peer_info->peer_macaddr.bytes);
3275
3276 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3277 wma->myaddr, QDF_MAC_ADDR_SIZE)) {
3278 resp->count = resp->count - 1;
3279 } else {
3280 wma_fill_peer_info(wma, stats_info, peer_info);
3281 j++;
3282 }
3283 stats_info = stats_info + 1;
3284 }
3285 }
3286
3287 sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND;
3288 sme_msg.bodyptr = resp;
3289 sme_msg.bodyval = 0;
3290
3291 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3292 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3293 WMA_LOGE("%s: Fail to post get peer info msg", __func__);
3294 qdf_mem_free(resp);
3295 }
3296
3297 return qdf_status;
3298}
3299
3300/**
3301 * dump_peer_stats_info() - dump wmi peer info struct
3302 * @event: wmi peer info fixed param pointer
3303 * @peer_stats: wmi peer stats info pointer
3304 *
3305 * This function will dump wmi peer info struct
3306 *
3307 * Return: None
3308 */
3309static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event,
3310 wmi_peer_stats_info *peer_stats)
3311{
3312 int i;
3313 wmi_peer_stats_info *stats = peer_stats;
3314 u_int8_t mac[6];
3315
3316 WMA_LOGI("%s vdev_id %d, num_peers %d more_data %d",
3317 __func__, event->vdev_id,
3318 event->num_peers, event->more_data);
3319
3320 for (i = 0; i < event->num_peers; i++) {
3321 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
3322 WMA_LOGI("%s mac %pM", __func__, mac);
3323 WMA_LOGI("%s tx_bytes %d %d tx_packets %d %d",
3324 __func__,
3325 stats->tx_bytes.low_32,
3326 stats->tx_bytes.high_32,
3327 stats->tx_packets.low_32,
3328 stats->tx_packets.high_32);
3329 WMA_LOGI("%s rx_bytes %d %d rx_packets %d %d",
3330 __func__,
3331 stats->rx_bytes.low_32,
3332 stats->rx_bytes.high_32,
3333 stats->rx_packets.low_32,
3334 stats->rx_packets.high_32);
3335 WMA_LOGI("%s tx_retries %d tx_failed %d",
3336 __func__, stats->tx_retries, stats->tx_failed);
3337 WMA_LOGI("%s tx_rate_code %x rx_rate_code %x",
3338 __func__,
3339 stats->last_tx_rate_code,
3340 stats->last_rx_rate_code);
3341 WMA_LOGI("%s tx_rate %x rx_rate %x",
3342 __func__,
3343 stats->last_tx_bitrate_kbps,
3344 stats->last_rx_bitrate_kbps);
3345 WMA_LOGI("%s peer_rssi %d", __func__, stats->peer_rssi);
3346 stats++;
3347 }
3348}
3349
3350int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
3351 u_int32_t len)
3352{
3353 tp_wma_handle wma = (tp_wma_handle) handle;
3354 WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
3355 wmi_peer_stats_info_event_fixed_param *event;
3356 u_int32_t buf_size;
3357 u_int8_t *buf;
3358
3359 param_buf =
3360 (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info;
3361 if (!param_buf) {
3362 WMA_LOGA("%s: Invalid stats event", __func__);
3363 return -EINVAL;
3364 }
3365
3366 WMA_LOGI("%s Recv WMI_PEER_STATS_INFO_EVENTID", __func__);
3367 event = param_buf->fixed_param;
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003368 if (event->num_peers >
Abhinav Kumara03659c2017-12-28 15:18:07 +05303369 ((WMI_SVC_MSG_MAX_SIZE -
3370 sizeof(wmi_peer_stats_info_event_fixed_param))/
3371 sizeof(wmi_peer_stats_info)) || event->num_peers >
3372 param_buf->num_peer_stats_info) {
3373 WMA_LOGE("Excess num of peers from fw: %d, num_peer_stats_info:%d",
3374 event->num_peers, param_buf->num_peer_stats_info);
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003375 return -EINVAL;
3376 }
Will Huanga9814592017-05-24 15:47:58 +08003377 buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) +
3378 sizeof(wmi_peer_stats_info) * event->num_peers;
3379 buf = qdf_mem_malloc(buf_size);
3380 if (!buf) {
3381 WMA_LOGE("%s: Failed alloc memory for buf", __func__);
3382 return -ENOMEM;
3383 }
3384
3385 qdf_mem_copy(buf, param_buf->fixed_param,
3386 sizeof(wmi_peer_stats_info_event_fixed_param));
3387 qdf_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)),
3388 param_buf->peer_stats_info,
3389 sizeof(wmi_peer_stats_info) * event->num_peers);
3390 WMA_LOGI("%s dump peer stats info", __func__);
3391 dump_peer_stats_info(event, param_buf->peer_stats_info);
3392
3393 wma_peer_info_ext_rsp(wma, buf);
3394 qdf_mem_free(buf);
3395
3396 return 0;
3397}
3398
3399/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 * wma_send_link_speed() - send link speed to SME
3401 * @link_speed: link speed
3402 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303403 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303405QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003406{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303407 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303408 tpAniSirGlobal mac_ctx;
3409 tSirLinkSpeedInfo *ls_ind;
3410
3411 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
3412 if (!mac_ctx) {
3413 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
3414 return QDF_STATUS_E_INVAL;
3415 }
3416
3417 ls_ind = (tSirLinkSpeedInfo *)qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 if (!ls_ind) {
3419 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303420 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 } else {
3422 ls_ind->estLinkSpeed = link_speed;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303423 if (mac_ctx->sme.pLinkSpeedIndCb)
3424 mac_ctx->sme.pLinkSpeedIndCb(ls_ind,
3425 mac_ctx->sme.pLinkSpeedCbContext);
3426 else
3427 WMA_LOGD("%s: pLinkSpeedIndCb is null", __func__);
3428 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303431 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003432}
3433
3434/**
3435 * wma_link_speed_event_handler() - link speed event handler
3436 * @handle: wma handle
3437 * @cmd_param_info: event data
3438 * @len: length
3439 *
3440 * Return: 0 for success or error code
3441 */
3442int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
3443 uint32_t len)
3444{
3445 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
3446 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303447 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003448
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003449 param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)
3450 cmd_param_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451 if (!param_buf) {
3452 WMA_LOGE("%s: Invalid linkspeed event", __func__);
3453 return -EINVAL;
3454 }
3455 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303456 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003457 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 return 0;
3460}
3461
3462/**
3463 * wma_wni_cfg_dnld() - cfg download request
3464 * @handle: wma handle
3465 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303466 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003467 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303468QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003469{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303470 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303471 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472
3473 WMA_LOGD("%s: Enter", __func__);
3474
3475 if (NULL == mac) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003476 WMA_LOGE("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303477 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303478 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003479 }
3480
3481 process_cfg_download_req(mac);
3482
3483 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303484 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485}
3486
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303487#define BIG_ENDIAN_MAX_DEBUG_BUF 500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488/**
3489 * wma_unified_debug_print_event_handler() - debug print event handler
3490 * @handle: wma handle
3491 * @datap: data pointer
3492 * @len: length
3493 *
3494 * Return: 0 for success or error code
3495 */
3496int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
3497 uint32_t len)
3498{
3499 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
3500 uint8_t *data;
3501 uint32_t datalen;
3502
3503 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303504 if (!param_buf || !param_buf->data) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 WMA_LOGE("Get NULL point message from FW");
3506 return -ENOMEM;
3507 }
3508 data = param_buf->data;
3509 datalen = param_buf->num_data;
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303510 if (datalen > WMI_SVC_MSG_MAX_SIZE) {
3511 WMA_LOGE("Received data len %d exceeds max value %d",
3512 datalen, WMI_SVC_MSG_MAX_SIZE);
3513 return QDF_STATUS_E_FAILURE;
3514 }
3515 data[datalen - 1] = '\0';
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516
3517#ifdef BIG_ENDIAN_HOST
3518 {
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303519 if (datalen >= BIG_ENDIAN_MAX_DEBUG_BUF) {
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303520 WMA_LOGE("%s Invalid data len %d, limiting to max",
3521 __func__, datalen);
Pragaspathi Thilagarajd9888ce2018-04-16 16:23:06 +05303522 datalen = BIG_ENDIAN_MAX_DEBUG_BUF - 1;
Vignesh Viswanathan5b86f132017-10-30 18:09:15 +05303523 }
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003524 char dbgbuf[BIG_ENDIAN_MAX_DEBUG_BUF] = { 0 };
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003525
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003526 memcpy(dbgbuf, data, datalen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003527 SWAPME(dbgbuf, datalen);
3528 WMA_LOGD("FIRMWARE:%s", dbgbuf);
3529 return 0;
3530 }
3531#else
Pragaspathi Thilagaraj71596f72018-04-11 03:48:42 -07003532 WMA_LOGD("FIRMWARE:%s", data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533 return 0;
3534#endif /* BIG_ENDIAN_HOST */
3535}
3536
3537/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538 * wma_is_sap_active() - check sap is active or not
3539 * @handle: wma handle
3540 *
3541 * Return: true/false
3542 */
3543bool wma_is_sap_active(tp_wma_handle wma_handle)
3544{
3545 int i;
3546
3547 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303548 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549 continue;
3550 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3551 wma_handle->interfaces[i].sub_type == 0)
3552 return true;
3553 }
3554 return false;
3555}
3556
3557/**
3558 * wma_is_p2p_go_active() - check p2p go is active or not
3559 * @handle: wma handle
3560 *
3561 * Return: true/false
3562 */
3563bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
3564{
3565 int i;
3566
3567 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303568 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003569 continue;
3570 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3571 wma_handle->interfaces[i].sub_type ==
3572 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
3573 return true;
3574 }
3575 return false;
3576}
3577
3578/**
3579 * wma_is_p2p_cli_active() - check p2p cli is active or not
3580 * @handle: wma handle
3581 *
3582 * Return: true/false
3583 */
3584bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
3585{
3586 int i;
3587
3588 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303589 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 continue;
3591 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3592 wma_handle->interfaces[i].sub_type ==
3593 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
3594 return true;
3595 }
3596 return false;
3597}
3598
3599/**
3600 * wma_is_sta_active() - check sta is active or not
3601 * @handle: wma handle
3602 *
3603 * Return: true/false
3604 */
3605bool wma_is_sta_active(tp_wma_handle wma_handle)
3606{
3607 int i;
3608
3609 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303610 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 continue;
3612 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3613 wma_handle->interfaces[i].sub_type == 0)
3614 return true;
3615 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
3616 return true;
3617 }
3618 return false;
3619}
3620
3621/**
3622 * wma_peer_phymode() - get phymode
3623 * @nw_type: nw type
3624 * @sta_type: sta type
3625 * @is_ht: is ht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003626 * @ch_width: supported channel width
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 * @is_vht: is vht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003628 * @is_he: is HE supported
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629 *
3630 * Return: WLAN_PHY_MODE
3631 */
3632WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
3633 uint8_t is_ht, uint8_t ch_width,
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003634 uint8_t is_vht, bool is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635{
3636 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
3637
3638 switch (nw_type) {
3639 case eSIR_11B_NW_TYPE:
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003640#ifdef FEATURE_WLAN_TDLS
3641 if (STA_ENTRY_TDLS_PEER == sta_type) {
3642 if (is_vht) {
3643 if (CH_WIDTH_80MHZ == ch_width)
3644 phymode = MODE_11AC_VHT80;
3645 else
3646 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3647 MODE_11AC_VHT40 :
3648 MODE_11AC_VHT20;
3649 } else if (is_ht) {
3650 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3651 MODE_11NG_HT40 : MODE_11NG_HT20;
3652 } else
3653 phymode = MODE_11B;
3654 } else
3655#endif /* FEATURE_WLAN_TDLS */
3656 {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003657 phymode = MODE_11B;
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003658 if (is_ht || is_vht || is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 WMA_LOGE("HT/VHT is enabled with 11B NW type");
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003660 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661 break;
3662 case eSIR_11G_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003663 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 phymode = MODE_11G;
3665 break;
3666 }
3667 if (CH_WIDTH_40MHZ < ch_width)
3668 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
3669 if (ch_width)
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003670 phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ?
3671 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 else
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003673 phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ?
3674 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003675 break;
3676 case eSIR_11A_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003677 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678 phymode = MODE_11A;
3679 break;
3680 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003681 if (is_he) {
3682 if (ch_width == CH_WIDTH_160MHZ)
3683 phymode = MODE_11AX_HE160;
3684 else if (ch_width == CH_WIDTH_80P80MHZ)
3685 phymode = MODE_11AX_HE80_80;
3686 else if (ch_width == CH_WIDTH_80MHZ)
3687 phymode = MODE_11AX_HE80;
3688 else
3689 phymode = (ch_width) ?
3690 MODE_11AX_HE40 : MODE_11AX_HE20;
3691 } else if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 if (ch_width == CH_WIDTH_160MHZ)
3693 phymode = MODE_11AC_VHT160;
3694 else if (ch_width == CH_WIDTH_80P80MHZ)
3695 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07003696 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697 phymode = MODE_11AC_VHT80;
3698 else
3699 phymode = (ch_width) ?
3700 MODE_11AC_VHT40 : MODE_11AC_VHT20;
3701 } else
3702 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
3703 break;
3704 default:
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003705 WMA_LOGE("%s: Invalid nw type %d", __func__, nw_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706 break;
3707 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003708 WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"),
3709 nw_type, is_ht, ch_width, is_vht, is_he, phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003710
3711 return phymode;
3712}
3713
3714/**
3715 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
3716 * @wma_handle: wma handle
3717 * @vdev_id: vdev id
3718 * @value: value
3719 *
3720 * Return: 0 for success or return error
3721 */
3722int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
3723 uint8_t vdev_id, uint32_t value)
3724{
3725 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003726 struct cdp_vdev *vdev;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303727 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3728
3729 if (!soc) {
3730 WMA_LOGE("%s:SOC context is NULL", __func__);
3731 return -EINVAL;
3732 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733
3734 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3735 if (!vdev) {
3736 WMA_LOGE("%s:Invalid vdev handle", __func__);
3737 return -EINVAL;
3738 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303739 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003740 req.stats_type_reset_mask = value;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003741 cdp_fw_stats_get(soc, vdev, &req, false, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742
3743 return 0;
3744}
3745
3746#ifdef HELIUMPLUS
Jeff Johnson560dc562017-03-17 15:19:31 -07003747#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748 ((_mask) = 1 << (_rate_info ## _V2))
3749#else /* !HELIUMPLUS */
Jeff Johnson560dc562017-03-17 15:19:31 -07003750#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003751 ((_mask) = 1 << (_rate_info))
3752#endif
3753
Nirav Shah93e789e2016-04-14 19:47:43 +05303754#ifdef HELIUMPLUS
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003755static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303756{
3757 if (value > (HTT_DBG_NUM_STATS + 1) ||
3758 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
3759 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
3760 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3761 WMA_LOGE("%s: Not supported", __func__);
3762 return false;
3763 }
3764 return true;
3765}
3766#else
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003767static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303768{
3769 if (value > (HTT_DBG_NUM_STATS + 1) ||
3770 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
3771 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
3772 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3773 WMA_LOGE("%s: Not supported", __func__);
3774 return false;
3775 }
3776 return true;
3777}
3778#endif
3779
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780/**
3781 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
3782 * @wma_handle: wma handle
3783 * @vdev_id: vdev id
3784 * @value: value
3785 *
3786 * Return: 0 for success or return error
3787 */
3788int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
3789 uint8_t vdev_id, uint32_t value)
3790{
3791 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003792 struct cdp_vdev *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793 uint32_t l_up_mask;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303794 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3795
3796 if (!soc) {
3797 WMA_LOGE("%s:SOC context is NULL", __func__);
3798 return -EINVAL;
3799 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800
3801 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3802 if (!vdev) {
3803 WMA_LOGE("%s:Invalid vdev handle", __func__);
3804 return -EINVAL;
3805 }
Nirav Shah93e789e2016-04-14 19:47:43 +05303806
3807 if (wma_is_valid_fw_stats_cmd(value) == false)
3808 return -EINVAL;
3809
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303810 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 req.print.verbose = 1;
3812
Nirav Shah93e789e2016-04-14 19:47:43 +05303813 /* TODO: Need to check how to avoid mem leak*/
3814 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815 req.stats_type_upload_mask = l_up_mask;
3816
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003817 cdp_fw_stats_get(soc, vdev, &req, false, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818
3819 return 0;
3820}
3821
Naveen Rawatfa2a1002018-05-17 16:06:37 -07003822#ifndef QCA_SUPPORT_CP_STATS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003823/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003824 * wma_get_stats_rsp_buf() - fill get stats response buffer
3825 * @get_stats_param: get stats parameters
3826 *
3827 * Return: stats response buffer
3828 */
3829static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
3830 (tAniGetPEStatsReq *get_stats_param)
3831{
3832 tAniGetPEStatsRsp *stats_rsp_params;
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003833 uint32_t len, temp_mask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834
3835 len = sizeof(tAniGetPEStatsRsp);
3836 temp_mask = get_stats_param->statsMask;
3837
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003838 if (temp_mask & (1 << eCsrSummaryStats))
3839 len += sizeof(tCsrSummaryStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003841 if (temp_mask & (1 << eCsrGlobalClassAStats))
3842 len += sizeof(tCsrGlobalClassAStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003844 if (temp_mask & (1 << eCsrGlobalClassDStats))
3845 len += sizeof(tCsrGlobalClassDStatsInfo);
3846
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003847 if (temp_mask & (1 << csr_per_chain_rssi_stats))
3848 len += sizeof(struct csr_per_chain_rssi_stats_info);
3849
3850 stats_rsp_params = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003851 if (!stats_rsp_params) {
3852 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303853 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003854 return NULL;
3855 }
3856
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003857 stats_rsp_params->staId = get_stats_param->staId;
3858 stats_rsp_params->statsMask = get_stats_param->statsMask;
3859 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
3860 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303861 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003862 return stats_rsp_params;
3863}
3864
3865/**
3866 * wma_get_stats_req() - get stats request
3867 * @handle: wma handle
3868 * @get_stats_param: stats params
3869 *
3870 * Return: none
3871 */
3872void wma_get_stats_req(WMA_HANDLE handle,
3873 tAniGetPEStatsReq *get_stats_param)
3874{
3875 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3876 struct wma_txrx_node *node;
Dustin Brown35619492017-10-03 15:16:12 -07003877 struct stats_request_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05303879
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880
3881 WMA_LOGD("%s: Enter", __func__);
3882 node = &wma_handle->interfaces[get_stats_param->sessionId];
3883 if (node->stats_rsp) {
3884 pGetPEStatsRspParams = node->stats_rsp;
3885 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
3886 pGetPEStatsRspParams->statsMask ==
3887 get_stats_param->statsMask) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003888 WMA_LOGD("Stats for staId %d with stats mask %d is pending.. ignore new request",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889 get_stats_param->staId,
3890 get_stats_param->statsMask);
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303891 pGetPEStatsRspParams =
3892 wma_get_stats_rsp_buf(get_stats_param);
3893 if (!pGetPEStatsRspParams) {
3894 WMA_LOGE("failed to allocate memory for stats response");
3895 goto end;
3896 }
3897 goto req_pending;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303899 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003900 node->stats_rsp = NULL;
3901 node->fw_stats_set = 0;
3902 }
3903 }
3904
3905 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
3906 if (!pGetPEStatsRspParams)
3907 goto end;
3908
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 node->fw_stats_set = 0;
Naveen Rawat3c49d192017-03-02 18:43:16 -08003910 if (node->stats_rsp) {
Jeff Johnsonadba3962017-09-18 08:12:35 -07003911 WMA_LOGD(FL("stats_rsp is not null, prev_value: %pK"),
Naveen Rawat3c49d192017-03-02 18:43:16 -08003912 node->stats_rsp);
3913 qdf_mem_free(node->stats_rsp);
3914 node->stats_rsp = NULL;
3915 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916 node->stats_rsp = pGetPEStatsRspParams;
Will Huanga9814592017-05-24 15:47:58 +08003917 wma_handle->get_sta_peer_info = false;
Jeff Johnsonadba3962017-09-18 08:12:35 -07003918 WMA_LOGD("stats_rsp allocated: %pK, sta_id: %d, mask: %d, vdev_id: %d",
Naveen Rawat3c49d192017-03-02 18:43:16 -08003919 node->stats_rsp, node->stats_rsp->staId,
3920 node->stats_rsp->statsMask, get_stats_param->sessionId);
Govind Singh4863da42016-03-08 11:45:00 +05303921
Dustin Brown35619492017-10-03 15:16:12 -07003922 cmd.vdev_id = get_stats_param->sessionId;
3923 cmd.stats_id = get_stats_param->statsMask;
3924 if (wmi_unified_stats_request_send(wma_handle->wmi_handle,
3925 node->bssid,
3926 &cmd)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
3928 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 goto failed;
3930 }
3931
3932 goto end;
3933failed:
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303934 node->stats_rsp = NULL;
3935req_pending:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303936 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003937 /* send response to UMAC */
3938 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
3939 0);
3940end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303941 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942 WMA_LOGD("%s: Exit", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943}
Naveen Rawatfa2a1002018-05-17 16:06:37 -07003944#endif /* QCA_SUPPORT_CP_STATS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945
3946/**
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303947 * wma_get_cca_stats() - send request to fw to get CCA
3948 * @wma_handle: wma handle
3949 * @vdev_id: vdev id
3950 *
3951 * Return: QDF status
3952 */
3953QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
3954 uint8_t vdev_id)
3955{
3956 if (wmi_unified_congestion_request_cmd(wma_handle->wmi_handle,
3957 vdev_id)) {
3958 WMA_LOGE("Failed to congestion request to fw");
3959 return QDF_STATUS_E_FAILURE;
3960 }
3961 return QDF_STATUS_SUCCESS;
3962}
3963
3964/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003965 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
3966 * @vdev_id: vdev id
3967 * @buffer_size: size of buffer
3968 *
3969 * Return: none
3970 */
3971void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
3972{
3973 tp_wma_handle wma;
3974 struct beacon_info *beacon;
3975 uint8_t *buf;
3976 uint32_t buf_size;
3977
Anurag Chouhan6d760662016-02-20 16:05:43 +05303978 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 if (!wma) {
3980 WMA_LOGE("%s: Invalid WMA handle", __func__);
3981 return NULL;
3982 }
3983
3984 if (vdev_id >= wma->max_bssid) {
3985 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3986 return NULL;
3987 }
3988
3989 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
3990 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
3991 return NULL;
3992 }
3993
3994 beacon = wma->interfaces[vdev_id].beacon;
3995
3996 if (!beacon) {
3997 WMA_LOGE("%s: beacon invalid", __func__);
3998 return NULL;
3999 }
4000
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304001 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002
Nirav Shahcbc6d722016-03-01 16:24:53 +05304003 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304004 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005
4006 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304007 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
4009 return NULL;
4010 }
4011
Nirav Shahcbc6d722016-03-01 16:24:53 +05304012 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304014 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015
4016 if (buffer_size)
4017 *buffer_size = buf_size;
4018
4019 return buf;
4020}
4021
4022/**
4023 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
4024 * @vdev_id: vdev id
4025 *
4026 * Return: mac address
4027 */
4028uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
4029{
4030 tp_wma_handle wma;
4031
Anurag Chouhan6d760662016-02-20 16:05:43 +05304032 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 if (!wma) {
4034 WMA_LOGE("%s: Invalid WMA handle", __func__);
4035 return NULL;
4036 }
4037
4038 if (vdev_id >= wma->max_bssid) {
4039 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
4040 return NULL;
4041 }
4042
4043 return wma->interfaces[vdev_id].addr;
4044}
4045
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004046QDF_STATUS wma_get_connection_info(uint8_t vdev_id,
4047 struct policy_mgr_vdev_entry_info *conn_table_entry)
4048{
4049 struct wma_txrx_node *wma_conn_table_entry;
4050
4051 wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id);
4052 if (NULL == wma_conn_table_entry) {
4053 WMA_LOGE("%s: can't find vdev_id %d in WMA table", __func__, vdev_id);
4054 return QDF_STATUS_E_FAILURE;
4055 }
4056 conn_table_entry->chan_width = wma_conn_table_entry->chan_width;
4057 conn_table_entry->mac_id = wma_conn_table_entry->mac_id;
4058 conn_table_entry->mhz = wma_conn_table_entry->mhz;
4059 conn_table_entry->sub_type = wma_conn_table_entry->sub_type;
4060 conn_table_entry->type = wma_conn_table_entry->type;
4061
4062 return QDF_STATUS_SUCCESS;
4063}
4064
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065/**
4066 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
4067 * @vdev_id: vdev id
4068 *
4069 * Return: entry from vdev table
4070 */
4071struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
4072{
4073 tp_wma_handle wma;
4074
Anurag Chouhan6d760662016-02-20 16:05:43 +05304075 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004076 if (!wma) {
4077 WMA_LOGE("%s: Invalid WMA handle", __func__);
4078 return NULL;
4079 }
4080
4081 if (vdev_id >= wma->max_bssid) {
4082 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
4083 return NULL;
4084 }
4085
4086 return &wma->interfaces[vdev_id];
4087}
4088
Jeff Johnsonabb74042017-08-31 11:44:55 -07004089QDF_STATUS wma_get_wcnss_software_version(uint8_t *version,
4090 uint32_t version_buffer_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004092 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304093 struct target_psoc_info *tgt_hdl;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094
4095 if (NULL == wma_handle) {
4096 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304097 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098 }
4099
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304100 tgt_hdl = wlan_psoc_get_tgt_if_handle(wma_handle->psoc);
4101 if (!tgt_hdl) {
4102 WMA_LOGE("%s: Failed to get wma", __func__);
4103 return QDF_STATUS_E_FAULT;
4104 }
4105
Jeff Johnsonabb74042017-08-31 11:44:55 -07004106 snprintf(version, version_buffer_size, "%x",
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304107 target_if_get_fw_version(tgt_hdl));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304108 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109}
4110
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004111/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004112 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
4113 * @vdev_id: VDEV whose MAC ID is required
4114 *
4115 * Get MAC id corresponding to a vdev id from the WMA structure
4116 *
4117 * Return: Negative value on failure and MAC id on success
4118 */
4119int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
4120{
4121 tp_wma_handle wma;
4122
Anurag Chouhan6d760662016-02-20 16:05:43 +05304123 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 if (!wma) {
4125 WMA_LOGE("%s: Invalid WMA handle", __func__);
4126 return -EINVAL;
4127 }
4128
4129 if (wma->interfaces)
4130 return wma->interfaces[vdev_id].mac_id;
4131
4132 return -EINVAL;
4133}
4134
4135/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004136 * wma_update_intf_hw_mode_params() - Update WMA params
4137 * @vdev_id: VDEV id whose params needs to be updated
4138 * @mac_id: MAC id to be updated
4139 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
4140 *
4141 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
4142 *
4143 * Return: None
4144 */
4145void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
4146 uint32_t cfgd_hw_mode_index)
4147{
4148 tp_wma_handle wma;
Liangwei Dong0f9c75d2018-05-22 22:14:37 -04004149 struct policy_mgr_hw_mode_params hw_mode;
4150 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151
Anurag Chouhan6d760662016-02-20 16:05:43 +05304152 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153 if (!wma) {
4154 WMA_LOGE("%s: Invalid WMA handle", __func__);
4155 return;
4156 }
4157
4158 if (!wma->interfaces) {
4159 WMA_LOGE("%s: Interface is NULL", __func__);
4160 return;
4161 }
4162
Liangwei Dong0f9c75d2018-05-22 22:14:37 -04004163 status = policy_mgr_get_hw_mode_from_idx(wma->psoc, cfgd_hw_mode_index,
4164 &hw_mode);
4165 if (!QDF_IS_STATUS_SUCCESS(status)) {
4166 WMA_LOGE("%s: cfgd_hw_mode_index %d not found", __func__,
4167 cfgd_hw_mode_index);
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004168 return;
4169 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 wma->interfaces[vdev_id].mac_id = mac_id;
4171 if (mac_id == 0) {
4172 wma->interfaces[vdev_id].tx_streams =
Liangwei Dong0f9c75d2018-05-22 22:14:37 -04004173 hw_mode.mac0_tx_ss;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174 wma->interfaces[vdev_id].rx_streams =
Liangwei Dong0f9c75d2018-05-22 22:14:37 -04004175 hw_mode.mac0_rx_ss;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176 } else {
4177 wma->interfaces[vdev_id].tx_streams =
Liangwei Dong0f9c75d2018-05-22 22:14:37 -04004178 hw_mode.mac1_tx_ss;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004179 wma->interfaces[vdev_id].rx_streams =
Liangwei Dong0f9c75d2018-05-22 22:14:37 -04004180 hw_mode.mac1_tx_ss;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004181 }
Liangwei Dong0f9c75d2018-05-22 22:14:37 -04004182 WMA_LOGD("%s: vdev %d, update tx ss:%d rx ss:%d mac %d hw_mode_id %d",
4183 __func__,
4184 vdev_id,
4185 wma->interfaces[vdev_id].tx_streams,
4186 wma->interfaces[vdev_id].rx_streams,
4187 mac_id,
4188 cfgd_hw_mode_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189}
4190
4191/**
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004192 * wma_get_vht_ch_width - return vht channel width
4193 *
4194 * Return: return vht channel width
4195 */
4196uint32_t wma_get_vht_ch_width(void)
4197{
4198 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304199 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304200 struct target_psoc_info *tgt_hdl;
4201 int vht_cap_info;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004202
4203 if (NULL == wm_hdl)
4204 return fw_ch_wd;
4205
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304206 tgt_hdl = wlan_psoc_get_tgt_if_handle(wm_hdl->psoc);
4207 if (!tgt_hdl)
4208 return fw_ch_wd;
4209
4210 vht_cap_info = target_if_get_vht_cap_info(tgt_hdl);
4211 if (vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004212 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Arunk Khandavalli2462f462018-01-25 14:41:02 +05304213 else if (vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004214 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004215
4216 return fw_ch_wd;
4217}
Govind Singhd76a5b02016-03-08 15:12:14 +05304218
4219/**
Krunal Soniaa664da2016-06-15 23:46:40 -07004220 * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
4221 * @mask: given bitmask
4222 *
4223 * This helper function should return number of setbits from bitmask
4224 *
4225 * Return: number of setbits from bitmask
4226 */
4227uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
4228{
4229 uint32_t num_of_setbits = 0;
4230
4231 while (mask) {
4232 mask &= (mask - 1);
4233 num_of_setbits++;
4234 }
4235 return num_of_setbits;
4236}
4237
4238/**
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004239 * wma_is_csa_offload_enabled - checks fw CSA offload capability
4240 *
4241 * Return: true or false
4242 */
4243
4244bool wma_is_csa_offload_enabled(void)
4245{
4246 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4247
4248 if (!wma)
4249 return false;
4250
Sourav Mohapatra89c85d12017-12-01 09:17:54 +05304251 return wmi_service_enabled(wma->wmi_handle,
4252 wmi_service_csa_offload);
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004253}
Wen Gong99768902018-04-25 12:07:49 +08004254#ifdef FEATURE_FW_LOG_PARSING
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004255/**
Govind Singhd76a5b02016-03-08 15:12:14 +05304256 * wma_config_debug_module_cmd - set debug log config
4257 * @wmi_handle: wmi layer handle
4258 * @param: debug log parameter
4259 * @val: debug log value
4260 * @module_id_bitmap: debug module id bitmap
4261 * @bitmap_len: debug module bitmap length
4262 *
4263 * Return: QDF_STATUS_SUCCESS for success or error code
4264 */
4265QDF_STATUS
4266wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
4267 A_UINT32 val, A_UINT32 *module_id_bitmap,
4268 A_UINT32 bitmap_len)
4269{
4270 struct dbglog_params dbg_param;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004271
Govind Singhd76a5b02016-03-08 15:12:14 +05304272 dbg_param.param = param;
4273 dbg_param.val = val;
4274 dbg_param.module_id_bitmap = module_id_bitmap;
4275 dbg_param.bitmap_len = bitmap_len;
4276
4277 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
4278}
Wen Gong99768902018-04-25 12:07:49 +08004279#endif
Rachit Kankane026e77a2018-07-31 16:21:09 +05304280#ifdef FEATURE_P2P_LISTEN_OFFLOAD
Peng Xu8fdaa492016-06-22 10:20:47 -07004281/**
4282 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
4283 *
4284 * This function checks if driver is capable of p2p listen offload
4285 * true: capable of p2p offload
4286 * false: not capable
4287 *
4288 * Return: true - capable, false - not capable
4289 */
4290bool wma_is_p2p_lo_capable(void)
4291{
Sourav Mohapatra5daec822018-07-10 14:40:06 +05304292 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4293
4294 if (wma) {
4295 return wmi_service_enabled
4296 (wma->wmi_handle,
4297 wmi_service_p2p_listen_offload_support);
4298 }
4299
4300 return 0;
Peng Xu8fdaa492016-06-22 10:20:47 -07004301}
Rachit Kankane026e77a2018-07-31 16:21:09 +05304302#endif
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004303
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004304bool wma_capability_enhanced_mcast_filter(void)
4305{
Sourav Mohapatra5daec822018-07-10 14:40:06 +05304306 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4307
4308 if (wma) {
4309 return wmi_service_enabled(wma->wmi_handle,
4310 wmi_service_enhanced_mcast_filter);
4311 }
4312
4313 return 0;
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004314}
4315
4316
Mukul Sharmaf9047232017-03-02 16:58:56 +05304317bool wma_is_vdev_up(uint8_t vdev_id)
4318{
4319 struct wlan_objmgr_vdev *vdev;
4320 tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
4321 enum wlan_vdev_state state = WLAN_VDEV_S_INIT;
4322
4323 if (!wma) {
4324 WMA_LOGE("%s: WMA context is invald!", __func__);
4325 return false;
4326 }
4327
4328 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
4329 WLAN_LEGACY_WMA_ID);
4330 if (vdev) {
4331 wlan_vdev_obj_lock(vdev);
4332 state = wlan_vdev_mlme_get_state(vdev);
4333 wlan_vdev_obj_unlock(vdev);
4334 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4335 }
Mukul Sharmaf9047232017-03-02 16:58:56 +05304336 return (state == WLAN_VDEV_S_RUN) ? true : false;
4337}
4338
Dustin Brownec2c92e2017-07-26 11:13:49 -07004339void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004340{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004341 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4342
4343 cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4344 qdf_wake_lock_timeout_acquire(wl, msec);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004345 qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004346}
4347
Dustin Brownec2c92e2017-07-26 11:13:49 -07004348void wma_release_wakelock(qdf_wake_lock_t *wl)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004349{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004350 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4351
4352 qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004353 qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004354}
4355
Dustin Brownd5f12942017-03-10 11:06:25 -08004356QDF_STATUS
4357wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
4358{
4359 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004360 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
Dustin Brownd5f12942017-03-10 11:06:25 -08004361
Dustin Brownec2c92e2017-07-26 11:13:49 -07004362 wma_acquire_wakelock(&vdev->vdev_start_wakelock,
4363 WMA_VDEV_START_REQUEST_TIMEOUT);
Dustin Brownd5f12942017-03-10 11:06:25 -08004364 status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
4365 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004366 wma_release_wakelock(&vdev->vdev_start_wakelock);
Dustin Brownd5f12942017-03-10 11:06:25 -08004367
4368 return status;
4369}
4370
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004371QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4372{
4373 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004374 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004375
Dustin Brownec2c92e2017-07-26 11:13:49 -07004376 wma_acquire_wakelock(&vdev->vdev_stop_wakelock,
4377 WMA_VDEV_STOP_REQUEST_TIMEOUT);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004378 status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id);
4379 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004380 wma_release_wakelock(&vdev->vdev_stop_wakelock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004381
4382 return status;
4383}
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004384
Rajeev Kumar Sirasanagandla996e5292016-11-22 21:20:33 +05304385QDF_STATUS wma_get_rcpi_req(WMA_HANDLE handle,
4386 struct sme_rcpi_req *rcpi_request)
4387{
4388 tp_wma_handle wma_handle = (tp_wma_handle) handle;
4389 struct rcpi_req cmd = {0};
4390 struct wma_txrx_node *iface;
4391 struct sme_rcpi_req *node_rcpi_req;
4392
4393 WMA_LOGD("%s: Enter", __func__);
4394 iface = &wma_handle->interfaces[rcpi_request->session_id];
4395 /* command is in progress */
4396 if (iface->rcpi_req != NULL) {
4397 WMA_LOGE("%s : previous rcpi request is pending", __func__);
4398 return QDF_STATUS_SUCCESS;
4399 }
4400
4401 node_rcpi_req = qdf_mem_malloc(sizeof(*node_rcpi_req));
4402 if (!node_rcpi_req) {
4403 WMA_LOGE("Failed to allocate memory for rcpi_request");
4404 return QDF_STATUS_E_NOMEM;
4405 }
4406
4407 *node_rcpi_req = *rcpi_request;
4408 iface->rcpi_req = node_rcpi_req;
4409
4410 cmd.vdev_id = rcpi_request->session_id;
4411 qdf_mem_copy(cmd.mac_addr, &rcpi_request->mac_addr, QDF_MAC_ADDR_SIZE);
Tushnim Bhattacharyya0725f1a2018-03-28 13:01:45 -07004412 cmd.measurement_type = rcpi_request->measurement_type;
Rajeev Kumar Sirasanagandla996e5292016-11-22 21:20:33 +05304413
4414 if (wmi_unified_send_request_get_rcpi_cmd(wma_handle->wmi_handle,
4415 &cmd)) {
4416 WMA_LOGE("%s: Failed to send WMI_REQUEST_RCPI_CMDID",
4417 __func__);
4418 iface->rcpi_req = NULL;
4419 qdf_mem_free(node_rcpi_req);
4420 return QDF_STATUS_E_FAILURE;
4421 }
4422
4423 WMA_LOGD("%s: Exit", __func__);
4424
4425 return QDF_STATUS_SUCCESS;
4426}
4427
4428int wma_rcpi_event_handler(void *handle, uint8_t *cmd_param_info,
Rajeev Kumar Sirasanagandla4f20b672018-03-12 13:52:50 +05304429 uint32_t len)
Rajeev Kumar Sirasanagandla996e5292016-11-22 21:20:33 +05304430{
4431 struct rcpi_res res = {0};
4432 struct sme_rcpi_req *rcpi_req;
4433 struct qdf_mac_addr qdf_mac;
4434 struct wma_txrx_node *iface;
4435 QDF_STATUS status = QDF_STATUS_SUCCESS;
4436 tp_wma_handle wma_handle = (tp_wma_handle)handle;
4437
4438 status = wmi_extract_rcpi_response_event(wma_handle->wmi_handle,
4439 cmd_param_info, &res);
4440 if (status == QDF_STATUS_E_INVAL)
4441 return -EINVAL;
4442
4443 iface = &wma_handle->interfaces[res.vdev_id];
4444 if (!iface->rcpi_req) {
4445 WMI_LOGE("rcpi_req buffer not available");
4446 return 0;
4447 }
4448
4449 rcpi_req = iface->rcpi_req;
4450 if (!rcpi_req->rcpi_callback) {
4451 iface->rcpi_req = NULL;
4452 qdf_mem_free(rcpi_req);
4453 return 0;
4454 }
4455
4456 if ((res.measurement_type == RCPI_MEASUREMENT_TYPE_INVALID) ||
4457 (res.vdev_id != rcpi_req->session_id) ||
4458 (res.measurement_type != rcpi_req->measurement_type) ||
4459 (qdf_mem_cmp(res.mac_addr, &rcpi_req->mac_addr,
4460 QDF_MAC_ADDR_SIZE))) {
4461 WMI_LOGE("invalid rcpi_response");
4462 iface->rcpi_req = NULL;
4463 qdf_mem_free(rcpi_req);
4464 return 0;
4465 }
4466
4467 qdf_mem_copy(&qdf_mac, res.mac_addr, QDF_MAC_ADDR_SIZE);
4468 (rcpi_req->rcpi_callback)(rcpi_req->rcpi_context, qdf_mac,
4469 res.rcpi_value, status);
4470 iface->rcpi_req = NULL;
4471 qdf_mem_free(rcpi_req);
4472
4473 return 0;
4474}
4475
Srinivas Girigowda4d65ebe2017-10-13 21:41:42 -07004476
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004477
Dustin Brownec2c92e2017-07-26 11:13:49 -07004478QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
4479 struct vdev_up_params *params,
4480 uint8_t bssid[IEEE80211_ADDR_LEN])
4481{
4482 QDF_STATUS status;
4483 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
4484
Varun Reddy Yeturu5303e082017-10-24 14:20:00 -07004485 if (wma_is_vdev_up(params->vdev_id)) {
4486 WMA_LOGD("vdev %d is already up for bssid %pM. Do not send",
4487 params->vdev_id, bssid);
4488 return QDF_STATUS_SUCCESS;
4489 }
Dustin Brownec2c92e2017-07-26 11:13:49 -07004490 status = wmi_unified_vdev_up_send(wma->wmi_handle, bssid, params);
4491 wma_release_wakelock(&vdev->vdev_start_wakelock);
4492
4493 return status;
4494}
4495
4496QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4497{
4498 QDF_STATUS status;
4499 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
4500
Tushnim Bhattacharyyaeb622b02018-05-07 13:50:51 -07004501 wma->interfaces[vdev_id].roaming_in_progress = false;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004502 status = wmi_unified_vdev_down_send(wma->wmi_handle, vdev_id);
4503 wma_release_wakelock(&vdev->vdev_start_wakelock);
4504
4505 return status;
4506}
4507
Qiwei Cai3719efe2018-06-11 21:09:29 +08004508#ifdef WLAN_FEATURE_LINK_LAYER_STATS
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004509tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
4510{
4511 switch (type) {
4512 case WMI_PEER_TYPE_DEFAULT:
4513 return WIFI_PEER_STA;
4514 case WMI_PEER_TYPE_BSS:
4515 return WIFI_PEER_AP;
4516 case WMI_PEER_TYPE_TDLS:
4517 return WIFI_PEER_TDLS;
4518 case WMI_PEER_TYPE_NAN_DATA:
4519 return WIFI_PEER_NAN;
4520 default:
4521 WMA_LOGE("Cannot map wmi_peer_type %d to HAL peer type", type);
4522 return WIFI_PEER_INVALID;
4523 }
4524}
Qiwei Cai3719efe2018-06-11 21:09:29 +08004525#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304526
Rachit Kankanef6834c42018-08-02 18:47:50 +05304527#ifdef FEATURE_WLAN_DYNAMIC_CVM
Nachiket Kukade8983cf62017-10-12 18:14:48 +05304528/**
4529 * wma_set_vc_mode_config() - set voltage corner mode config to FW.
4530 * @wma_handle: pointer to wma handle.
4531 * @vc_bitmap: value needs to set to firmware.
4532 *
4533 * At the time of driver startup, set operating voltage corner mode
4534 * for differenet phymode and bw configurations.
4535 *
4536 * Return: QDF_STATUS.
4537 */
4538QDF_STATUS wma_set_vc_mode_config(void *wma_handle,
4539 uint32_t vc_bitmap)
4540{
4541 int32_t ret;
4542 tp_wma_handle wma = (tp_wma_handle)wma_handle;
4543 struct pdev_params pdevparam;
4544
4545 pdevparam.param_id = WMI_PDEV_UPDATE_WDCVS_ALGO;
4546 pdevparam.param_value = vc_bitmap;
4547
4548 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
4549 &pdevparam,
4550 WMA_WILDCARD_PDEV_ID);
4551 if (ret) {
4552 WMA_LOGE("Fail to Set Voltage Corner config (0x%x)",
4553 vc_bitmap);
4554 return QDF_STATUS_E_FAILURE;
4555 }
4556
4557 WMA_LOGD("Successfully Set Voltage Corner config (0x%x)",
4558 vc_bitmap);
4559
4560 return QDF_STATUS_SUCCESS;
4561}
Rachit Kankanef6834c42018-08-02 18:47:50 +05304562#endif
Nachiket Kukade8983cf62017-10-12 18:14:48 +05304563
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304564int wma_chip_power_save_failure_detected_handler(void *handle,
4565 uint8_t *cmd_param_info,
4566 uint32_t len)
4567{
4568 tp_wma_handle wma = (tp_wma_handle)handle;
4569 WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
4570 wmi_chip_power_save_failure_detected_fixed_param *event;
4571 struct chip_pwr_save_fail_detected_params pwr_save_fail_params;
4572 tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(
4573 QDF_MODULE_ID_PE);
4574 if (wma == NULL) {
4575 WMA_LOGE("%s: wma_handle is NULL", __func__);
4576 return -EINVAL;
4577 }
4578 if (!mac) {
4579 WMA_LOGE("%s: Invalid mac context", __func__);
4580 return -EINVAL;
4581 }
4582 if (!mac->sme.chip_power_save_fail_cb) {
4583 WMA_LOGE("%s: Callback not registered", __func__);
4584 return -EINVAL;
4585 }
4586
4587 param_buf =
4588 (WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
4589 cmd_param_info;
4590 if (!param_buf) {
4591 WMA_LOGE("%s: Invalid pwr_save_fail_params breached event",
4592 __func__);
4593 return -EINVAL;
4594 }
4595 event = param_buf->fixed_param;
4596 pwr_save_fail_params.failure_reason_code =
4597 event->power_save_failure_reason_code;
4598 pwr_save_fail_params.wake_lock_bitmap[0] =
4599 event->protocol_wake_lock_bitmap[0];
4600 pwr_save_fail_params.wake_lock_bitmap[1] =
4601 event->protocol_wake_lock_bitmap[1];
4602 pwr_save_fail_params.wake_lock_bitmap[2] =
4603 event->protocol_wake_lock_bitmap[2];
4604 pwr_save_fail_params.wake_lock_bitmap[3] =
4605 event->protocol_wake_lock_bitmap[3];
Jeff Johnson6aaaa992018-06-30 10:43:04 -07004606 mac->sme.chip_power_save_fail_cb(mac->hdd_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304607 &pwr_save_fail_params);
4608
4609 WMA_LOGD("%s: Invoke HDD pwr_save_fail callback", __func__);
4610 return 0;
4611}
Rajeev Kumar Sirasanagandla4f20b672018-03-12 13:52:50 +05304612
4613int wma_roam_scan_stats_event_handler(void *handle, uint8_t *event,
4614 uint32_t len)
4615{
4616 tp_wma_handle wma_handle;
4617 wmi_unified_t wmi_handle;
4618 struct sir_roam_scan_stats *roam_scan_stats_req = NULL;
4619 struct wma_txrx_node *iface = NULL;
4620 struct wmi_roam_scan_stats_res *res = NULL;
4621 int ret = 0;
4622 uint32_t vdev_id;
4623 QDF_STATUS status;
4624
4625 wma_handle = handle;
4626 if (!wma_handle) {
4627 WMA_LOGE(FL("NULL wma_handle"));
4628 return -EINVAL;
4629 }
4630
4631 wmi_handle = wma_handle->wmi_handle;
4632 if (!wmi_handle) {
4633 WMA_LOGE(FL("NULL wmi_handle"));
4634 return -EINVAL;
4635 }
4636
4637 status = wmi_extract_roam_scan_stats_res_evt(wmi_handle, event,
4638 &vdev_id,
4639 &res);
4640
4641 /* vdev_id can be invalid though status is success, hence validate */
4642 if (vdev_id >= wma_handle->max_bssid) {
4643 WMA_LOGE(FL("Received invalid vdev_id: %d"), vdev_id);
4644 ret = -EINVAL;
4645 goto free_res;
4646 }
4647
4648 /* Get interface for valid vdev_id */
4649 iface = &wma_handle->interfaces[vdev_id];
4650 if (!iface) {
4651 WMI_LOGE(FL("Interface not available for vdev_id: %d"),
4652 vdev_id);
4653 ret = -EINVAL;
4654 goto free_res;
4655 }
4656
4657 roam_scan_stats_req = iface->roam_scan_stats_req;
4658 iface->roam_scan_stats_req = NULL;
4659 if (!roam_scan_stats_req) {
4660 WMI_LOGE(FL("No pending request vdev_id: %d"), vdev_id);
4661 ret = -EINVAL;
4662 goto free_res;
4663 }
4664
4665 if (!QDF_IS_STATUS_SUCCESS(status) ||
4666 !roam_scan_stats_req->cb ||
4667 roam_scan_stats_req->vdev_id != vdev_id) {
4668 WMI_LOGE(FL("roam_scan_stats buffer not available"));
4669 ret = -EINVAL;
4670 goto free_roam_scan_stats_req;
4671 }
4672
4673 roam_scan_stats_req->cb(roam_scan_stats_req->context, res);
4674
4675free_roam_scan_stats_req:
4676 qdf_mem_free(roam_scan_stats_req);
4677 roam_scan_stats_req = NULL;
4678
4679free_res:
4680 qdf_mem_free(res);
4681 res = NULL;
4682
4683 return ret;
4684}
4685
4686QDF_STATUS wma_get_roam_scan_stats(WMA_HANDLE handle,
4687 struct sir_roam_scan_stats *req)
4688{
4689 tp_wma_handle wma_handle = (tp_wma_handle)handle;
4690 struct wmi_roam_scan_stats_req cmd = {0};
4691 struct wma_txrx_node *iface;
4692 struct sir_roam_scan_stats *node_req = NULL;
4693
4694 WMA_LOGD("%s: Enter", __func__);
4695 iface = &wma_handle->interfaces[req->vdev_id];
4696 /* command is in progress */
4697 if (iface->roam_scan_stats_req) {
4698 WMA_LOGE(FL("previous roam scan stats req is pending"));
4699 return QDF_STATUS_SUCCESS;
4700 }
4701
4702 node_req = qdf_mem_malloc(sizeof(*node_req));
4703 if (!node_req) {
4704 WMA_LOGE("Failed to allocate memory for roam scan stats req");
4705 return QDF_STATUS_E_NOMEM;
4706 }
4707
4708 *node_req = *req;
4709 iface->roam_scan_stats_req = node_req;
4710 cmd.vdev_id = req->vdev_id;
4711
4712 if (wmi_unified_send_roam_scan_stats_cmd(wma_handle->wmi_handle,
4713 &cmd)) {
4714 WMA_LOGE("%s: Failed to send WMI_REQUEST_ROAM_SCAN_STATS_CMDID",
4715 __func__);
4716 iface->roam_scan_stats_req = NULL;
4717 qdf_mem_free(node_req);
4718 return QDF_STATUS_E_FAILURE;
4719 }
4720
4721 WMA_LOGD("%s: Exit", __func__);
4722
4723 return QDF_STATUS_SUCCESS;
4724}