blob: 314100d2818f7d1eb1913adf2311ac23cf752f6d [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyad07dc902017-01-11 12:49:53 -08002 * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_utis.c
30 * This file contains utilities and stats related functions.
31 */
32
33/* Header files */
34
35#include "wma.h"
36#include "wma_api.h"
37#include "cds_api.h"
38#include "wmi_unified_api.h"
39#include "wlan_qct_sys.h"
40#include "wni_api.h"
41#include "ani_global.h"
42#include "wmi_unified.h"
43#include "wni_cfg.h"
44#include "cfg_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045
Nirav Shahcbc6d722016-03-01 16:24:53 +053046#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053047#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053048#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080049
50#include "wma_types.h"
51#include "lim_api.h"
52#include "lim_session_utils.h"
53
54#include "cds_utils.h"
55
56#if !defined(REMOVE_PKT_LOG)
57#include "pktlog_ac.h"
58#endif /* REMOVE_PKT_LOG */
59
60#include "dbglog_host.h"
61#include "csr_api.h"
62#include "ol_fw.h"
63
64#include "dfs.h"
65#include "wma_internal.h"
Chandrasekaran, Manishekar0d814c72015-11-05 10:42:48 +053066#include "cds_concurrency.h"
Govind Singhd76a5b02016-03-08 15:12:14 +053067#include "wmi_unified_param.h"
Naveen Rawatc0c91cd2015-11-05 14:27:37 -080068#include "linux/ieee80211.h"
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080069#include <cdp_txrx_handle.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070/* MCS Based rate table */
71/* HT MCS parameters with Nss = 1 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080072static struct index_data_rate_type mcs_nss1[] = {
73 /* MCS L20 S20 L40 S40 */
74 {0, {65, 72}, {135, 150 } },
75 {1, {130, 144}, {270, 300 } },
76 {2, {195, 217}, {405, 450 } },
77 {3, {260, 289}, {540, 600 } },
78 {4, {390, 433}, {815, 900 } },
79 {5, {520, 578}, {1080, 1200} },
80 {6, {585, 650}, {1215, 1350} },
81 {7, {650, 722}, {1350, 1500} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082};
83
84/* HT MCS parameters with Nss = 2 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080085static struct index_data_rate_type mcs_nss2[] = {
86 /* MCS L20 S20 L40 S40 */
87 {0, {130, 144}, {270, 300 } },
88 {1, {260, 289}, {540, 600 } },
89 {2, {390, 433}, {810, 900 } },
90 {3, {520, 578}, {1080, 1200} },
91 {4, {780, 867}, {1620, 1800} },
92 {5, {1040, 1156}, {2160, 2400} },
93 {6, {1170, 1300}, {2430, 2700} },
94 {7, {1300, 1440}, {2700, 3000} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095};
96
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097/* MCS Based VHT rate table */
98/* MCS parameters with Nss = 1*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -080099static struct index_vht_data_rate_type vht_mcs_nss1[] = {
100 /* MCS L20 S20 L40 S40 L80 S80 */
101 {0, {65, 72 }, {135, 150}, {293, 325} },
102 {1, {130, 144}, {270, 300}, {585, 650} },
103 {2, {195, 217}, {405, 450}, {878, 975} },
104 {3, {260, 289}, {540, 600}, {1170, 1300} },
105 {4, {390, 433}, {810, 900}, {1755, 1950} },
106 {5, {520, 578}, {1080, 1200}, {2340, 2600} },
107 {6, {585, 650}, {1215, 1350}, {2633, 2925} },
108 {7, {650, 722}, {1350, 1500}, {2925, 3250} },
109 {8, {780, 867}, {1620, 1800}, {3510, 3900} },
110 {9, {865, 960}, {1800, 2000}, {3900, 4333} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111};
112
113/*MCS parameters with Nss = 2*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800114static struct index_vht_data_rate_type vht_mcs_nss2[] = {
115 /* MCS L20 S20 L40 S40 L80 S80 */
116 {0, {130, 144}, {270, 300}, { 585, 650} },
117 {1, {260, 289}, {540, 600}, {1170, 1300} },
118 {2, {390, 433}, {810, 900}, {1755, 1950} },
119 {3, {520, 578}, {1080, 1200}, {2340, 2600} },
120 {4, {780, 867}, {1620, 1800}, {3510, 3900} },
121 {5, {1040, 1156}, {2160, 2400}, {4680, 5200} },
122 {6, {1170, 1300}, {2430, 2700}, {5265, 5850} },
123 {7, {1300, 1444}, {2700, 3000}, {5850, 6500} },
124 {8, {1560, 1733}, {3240, 3600}, {7020, 7800} },
125 {9, {1730, 1920}, {3600, 4000}, {7800, 8667} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800126};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127
128#ifdef BIG_ENDIAN_HOST
129
130/* ############# function definitions ############ */
131
132/**
133 * wma_swap_bytes() - swap bytes
134 * @pv: buffer
135 * @n: swap bytes
136 *
137 * Return: none
138 */
139void wma_swap_bytes(void *pv, uint32_t n)
140{
141 int32_t no_words;
142 int32_t i;
143 uint32_t *word_ptr;
144
145 no_words = n / sizeof(uint32_t);
146 word_ptr = (uint32_t *) pv;
147 for (i = 0; i < no_words; i++) {
148 *(word_ptr + i) = __cpu_to_le32(*(word_ptr + i));
149 }
150}
151
152#define SWAPME(x, len) wma_swap_bytes(&x, len);
153#endif /* BIG_ENDIAN_HOST */
154
155/**
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800156 * wma_mcs_rate_match() - find the match mcs rate
157 * @match_rate: the rate to look up
158 * @is_sgi: return if the SGI rate is found
159 * @nss: the nss in use
160 * @nss1_rate: the nss1 rate
161 * @nss1_srate: the nss1 SGI rate
162 * @nss2_rate: the nss2 rate
163 * @nss2_srate: the nss2 SGI rate
164 *
165 * This is a helper function to find the match of the tx_rate
166 * in terms of the nss1/nss2 rate with non-SGI/SGI.
167 *
168 * Return: the found rate or 0 otherwise
169 */
170static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi,
171 uint8_t nss, uint16_t nss1_rate,
172 uint16_t nss1_srate,
173 uint16_t nss2_rate,
174 uint16_t nss2_srate)
175{
176 WMA_LOGD("%s match_rate: %d, %d %d %d %d",
177 __func__, match_rate, nss1_rate, nss1_srate, nss2_rate,
178 nss2_srate);
179
180 if (match_rate == nss1_rate) {
181 return nss1_rate;
182 } else if (match_rate == nss1_srate) {
183 *is_sgi = true;
184 return nss1_srate;
185 } else if (nss == 2 && match_rate == nss2_rate)
186 return nss2_rate;
187 else if (nss == 2 && match_rate == nss2_srate) {
188 *is_sgi = true;
189 return nss2_srate;
190 } else
191 return 0;
192}
193
194/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 * wma_get_mcs_idx() - get mcs index
196 * @maxRate: max rate
197 * @rate_flags: rate flags
198 * @nss: number of nss
199 * @mcsRateFlag: mcs rate flag
200 *
201 * Return: return mcs index
202 */
203static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
204 uint8_t nss, uint8_t *mcsRateFlag)
205{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800206 uint8_t index = 0;
Arif Hussainb8fef842016-07-19 09:43:13 -0700207 uint16_t match_rate = 0;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800208 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800210 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
211 __func__, maxRate, rate_flags, nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212
213 *mcsRateFlag = rate_flags;
214 *mcsRateFlag &= ~eHAL_TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800215 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 if (rate_flags & eHAL_TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800217 /* check for vht80 nss1/2 rate set */
218 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
219 vht_mcs_nss1[index].ht80_rate[0],
220 vht_mcs_nss1[index].ht80_rate[1],
221 vht_mcs_nss2[index].ht80_rate[0],
222 vht_mcs_nss2[index].ht80_rate[1]);
223 if (match_rate)
224 goto rate_found;
225 }
226 if ((rate_flags & eHAL_TX_RATE_VHT40) |
227 (rate_flags & eHAL_TX_RATE_VHT80)) {
228 /* check for vht40 nss1/2 rate set */
229 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
230 vht_mcs_nss1[index].ht40_rate[0],
231 vht_mcs_nss1[index].ht40_rate[1],
232 vht_mcs_nss2[index].ht40_rate[0],
233 vht_mcs_nss2[index].ht40_rate[1]);
234 if (match_rate) {
235 *mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
236 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237 }
238 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800239 if ((rate_flags & eHAL_TX_RATE_VHT20) |
240 (rate_flags & eHAL_TX_RATE_VHT40) |
241 (rate_flags & eHAL_TX_RATE_VHT80)) {
242 /* check for vht20 nss1/2 rate set */
243 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
244 vht_mcs_nss1[index].ht20_rate[0],
245 vht_mcs_nss1[index].ht20_rate[1],
246 vht_mcs_nss2[index].ht20_rate[0],
247 vht_mcs_nss2[index].ht20_rate[1]);
248 if (match_rate) {
249 *mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 |
250 eHAL_TX_RATE_VHT40);
251 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 }
253 }
254 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800255 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800257 /* check for ht40 nss1/2 rate set */
258 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
259 mcs_nss1[index].ht40_rate[0],
260 mcs_nss1[index].ht40_rate[1],
261 mcs_nss2[index].ht40_rate[0],
262 mcs_nss2[index].ht40_rate[1]);
263 if (match_rate) {
264 *mcsRateFlag = eHAL_TX_RATE_HT40;
265 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 }
267 }
wadesongbf665542017-02-28 14:30:51 +0800268 if ((rate_flags & eHAL_TX_RATE_HT20) ||
269 (rate_flags & eHAL_TX_RATE_HT40)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800270 /* check for ht20 nss1/2 rate set */
271 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
272 mcs_nss1[index].ht20_rate[0],
273 mcs_nss1[index].ht20_rate[1],
274 mcs_nss2[index].ht20_rate[0],
275 mcs_nss2[index].ht20_rate[1]);
276 if (match_rate) {
277 *mcsRateFlag = eHAL_TX_RATE_HT20;
278 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 }
280 }
281 }
282
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800283rate_found:
284 /* set SGI flag only if this is SGI rate */
285 if (match_rate && is_sgi == true)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 *mcsRateFlag |= eHAL_TX_RATE_SGI;
287
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800288 WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
289 __func__, match_rate, index, *mcsRateFlag, is_sgi);
290
291 return match_rate ? index : INVALID_MCS_IDX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292}
293
294/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530295 * wma_peek_vdev_req() - peek what request message is queued for response.
296 * the function does not delete the node after found
297 * @wma: WMA handle
298 * @vdev_id: vdev ID
299 * @type: request message type
300 *
301 * Return: the request message found
302 */
303static struct wma_target_req *wma_peek_vdev_req(tp_wma_handle wma,
304 uint8_t vdev_id, uint8_t type)
305{
306 struct wma_target_req *req_msg = NULL;
307 bool found = false;
308 qdf_list_node_t *node1 = NULL, *node2 = NULL;
309
310 qdf_spin_lock_bh(&wma->vdev_respq_lock);
311 if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&wma->vdev_resp_queue,
312 &node2)) {
313 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530314 return NULL;
315 }
316
317 do {
318 node1 = node2;
319 req_msg = qdf_container_of(node1, struct wma_target_req, node);
320 if (req_msg->vdev_id != vdev_id)
321 continue;
322 if (req_msg->type != type)
323 continue;
324
325 found = true;
326 break;
327 } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&wma->vdev_resp_queue,
328 node1, &node2));
329 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
330 if (!found) {
331 WMA_LOGP(FL("target request not found for vdev_id %d type %d"),
332 vdev_id, type);
333 return NULL;
334 }
335 WMA_LOGD(FL("target request found for vdev id: %d type %d msg %d"),
336 vdev_id, type, req_msg->msg_type);
337 return req_msg;
338}
339
340void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id,
341 int32_t rssi)
342{
343 struct sir_lost_link_info *lost_link_info;
344 QDF_STATUS qdf_status;
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800345 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530346
347 /* report lost link information only for STA mode */
Mukul Sharmaf9047232017-03-02 16:58:56 +0530348 if (wma_is_vdev_up(vdev_id) &&
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530349 (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) &&
350 (0 == wma->interfaces[vdev_id].sub_type)) {
351 lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
352 if (NULL == lost_link_info) {
353 WMA_LOGE("%s: failed to allocate memory", __func__);
354 return;
355 }
356 lost_link_info->vdev_id = vdev_id;
357 lost_link_info->rssi = rssi;
358 sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
359 sme_msg.bodyptr = lost_link_info;
360 sme_msg.bodyval = 0;
361 WMA_LOGI("%s: post msg to SME, bss_idx %d, rssi %d", __func__,
362 lost_link_info->vdev_id, lost_link_info->rssi);
363
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800364 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530365 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
366 WMA_LOGE("%s: fail to post msg to SME", __func__);
367 qdf_mem_free(lost_link_info);
368 }
369 }
370}
371
372/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 * host_map_smps_mode() - map fw smps mode to tSmpsModeValue
374 * @fw_smps_mode: fw smps mode
375 *
376 * Return: return tSmpsModeValue
377 */
378tSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
379{
380 tSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
381 switch (fw_smps_mode) {
382 case WMI_SMPS_FORCED_MODE_STATIC:
383 smps_mode = STATIC_SMPS_MODE;
384 break;
385 case WMI_SMPS_FORCED_MODE_DYNAMIC:
386 smps_mode = DYNAMIC_SMPS_MODE;
387 break;
388 default:
389 smps_mode = SMPS_MODE_DISABLED;
390 }
391
392 return smps_mode;
393}
394
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800395/**
396 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
397 * mode commmand param
398 * @smps_mode: SMPS mode according to the protocol
399 *
400 * Return: int > 0 for success else failure
401 */
402int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
403{
404 int param = -EINVAL;
405
406 switch (smps_mode) {
407 case STATIC_SMPS_MODE:
408 param = WMI_SMPS_FORCED_MODE_STATIC;
409 break;
410 case DYNAMIC_SMPS_MODE:
411 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
412 break;
413 case SMPS_MODE_DISABLED:
414 param = WMI_SMPS_FORCED_MODE_DISABLED;
415 break;
416 default:
417 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
418 smps_mode);
419 }
420 return param;
421}
422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423#ifdef WLAN_FEATURE_STATS_EXT
424/**
425 * wma_stats_ext_event_handler() - extended stats event handler
426 * @handle: wma handle
427 * @event_buf: event buffer received from fw
428 * @len: length of data
429 *
430 * Return: 0 for success or error code
431 */
432int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
433 uint32_t len)
434{
435 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
436 tSirStatsExtEvent *stats_ext_event;
437 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530438 QDF_STATUS status;
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800439 struct scheduler_msg cds_msg;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800440 uint8_t *buf_ptr;
441 uint32_t alloc_len;
442
443 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
444
445 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
446 if (!param_buf) {
447 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
448 return -EINVAL;
449 }
450
451 stats_ext_info = param_buf->fixed_param;
452 buf_ptr = (uint8_t *) stats_ext_info;
453
454 alloc_len = sizeof(tSirStatsExtEvent);
455 alloc_len += stats_ext_info->data_len;
456
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530457 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 if (NULL == stats_ext_event) {
459 WMA_LOGE("%s: Memory allocation failure", __func__);
460 return -ENOMEM;
461 }
462
463 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
464
465 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
466 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530467 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800468 buf_ptr, stats_ext_event->event_data_len);
469
470 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
471 cds_msg.bodyptr = (void *)stats_ext_event;
472 cds_msg.bodyval = 0;
473
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800474 status = scheduler_post_msg(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530475 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530477 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478 return -EFAULT;
479 }
480
481 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
482 return 0;
483}
484#endif /* WLAN_FEATURE_STATS_EXT */
485
Nirav Shah93e789e2016-04-14 19:47:43 +0530486
Govind Singha471e5e2015-10-12 17:11:14 +0530487/**
488 * wma_profile_data_report_event_handler() - fw profiling handler
489 * @handle: wma handle
490 * @event_buf: event buffer received from fw
491 * @len: length of data
492 *
493 * Return: 0 for success or error code
494 */
495int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
496 uint32_t len)
497{
498 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
499 wmi_wlan_profile_ctx_t *profile_ctx;
500 wmi_wlan_profile_t *profile_data;
501 uint32_t i = 0;
502 uint32_t entries;
503 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530504 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530505 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
506
507 if (!param_buf) {
508 WMA_LOGE("%s: Invalid profile data event buf", __func__);
509 return -EINVAL;
510 }
511 profile_ctx = param_buf->profile_ctx;
512 buf_ptr = (uint8_t *)profile_ctx;
513 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
514 profile_data = (wmi_wlan_profile_t *) buf_ptr;
515 entries = profile_ctx->bin_count;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530516 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530517 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530518 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530519 "TOT: %d\n"
520 "tx_msdu_cnt: %d\n"
521 "tx_mpdu_cnt: %d\n"
522 "tx_ppdu_cnt: %d\n"
523 "rx_msdu_cnt: %d\n"
524 "rx_mpdu_cnt: %d\n"
525 "bin_count: %d\n",
526 profile_ctx->tot,
527 profile_ctx->tx_msdu_cnt,
528 profile_ctx->tx_mpdu_cnt,
529 profile_ctx->tx_ppdu_cnt,
530 profile_ctx->rx_msdu_cnt,
531 profile_ctx->rx_mpdu_cnt,
532 profile_ctx->bin_count);
533
Nirav Shah93e789e2016-04-14 19:47:43 +0530534 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
535 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
536
Govind Singha471e5e2015-10-12 17:11:14 +0530537 for (i = 0; i < entries; i++) {
538 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
539 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530540 snprintf(temp_str, sizeof(temp_str),
541 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530542 profile_data[i].id,
543 profile_data[i].cnt,
544 profile_data[i].tot,
545 profile_data[i].min,
546 profile_data[i].max,
547 profile_data[i].hist_intvl,
548 profile_data[i].hist[0],
549 profile_data[i].hist[1],
550 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530551 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
552 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530553 }
554
555 return 0;
556}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557
558#ifdef WLAN_FEATURE_LINK_LAYER_STATS
559
560/**
561 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
562 * @handle: wma handle
563 * @cmd_param_info: data received with event from fw
564 * @len: length of data
565 *
566 * Return: 0 for success or error code
567 */
568static int wma_unified_link_peer_stats_event_handler(void *handle,
569 uint8_t *cmd_param_info,
570 uint32_t len)
571{
572 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
573 wmi_peer_stats_event_fixed_param *fixed_param;
574 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
575 wmi_rate_stats *rate_stats;
576 tSirLLStatsResults *link_stats_results;
577 uint8_t *results, *t_peer_stats, *t_rate_stats;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +0530578 uint32_t count, num_rates = 0, rate_cnt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
580 size_t peer_info_size, peer_stats_size, rate_stats_size;
581 size_t link_stats_results_size;
582
Anurag Chouhan6d760662016-02-20 16:05:43 +0530583 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584
585 if (!pMac) {
586 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
587 return -EINVAL;
588 }
589
590 if (!pMac->sme.pLinkLayerStatsIndCallback) {
591 WMA_LOGD("%s: HDD callback is null", __func__);
592 return -EINVAL;
593 }
594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
596 if (!param_tlvs) {
597 WMA_LOGA("%s: Invalid stats event", __func__);
598 return -EINVAL;
599 }
600 /*
601 * cmd_param_info contains
602 * wmi_peer_stats_event_fixed_param fixed_param;
603 * num_peers * size of(struct wmi_peer_link_stats)
604 * num_rates * size of(struct wmi_rate_stats)
605 * num_rates is the sum of the rates of all the peers.
606 */
607 fixed_param = param_tlvs->fixed_param;
608 peer_stats = param_tlvs->peer_stats;
609 rate_stats = param_tlvs->peer_rate_stats;
610
611 if (!fixed_param || !peer_stats ||
612 (peer_stats->num_rates && !rate_stats)) {
613 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
614 return -EINVAL;
615 }
616
617 /*
618 * num_rates - sum of the rates of all the peers
619 */
620 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
621 for (count = 0; count < fixed_param->num_peers; count++) {
622 num_rates += temp_peer_stats->num_rates;
623 temp_peer_stats++;
624 }
625
626 peer_stats_size = sizeof(tSirWifiPeerStat);
627 peer_info_size = sizeof(tSirWifiPeerInfo);
628 rate_stats_size = sizeof(tSirWifiRateStat);
629 link_stats_results_size =
630 sizeof(*link_stats_results) + peer_stats_size +
631 (fixed_param->num_peers * peer_info_size) +
632 (num_rates * rate_stats_size);
633
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530634 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 if (NULL == link_stats_results) {
636 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
637 __func__, link_stats_results_size);
638 return -ENOMEM;
639 }
640
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530641 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642
643 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
644 link_stats_results->rspId = fixed_param->request_id;
645 link_stats_results->ifaceId = 0;
646 link_stats_results->num_peers = fixed_param->num_peers;
647 link_stats_results->peer_event_number = fixed_param->peer_event_number;
648 link_stats_results->moreResultToFollow = fixed_param->more_data;
649
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530650 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 &fixed_param->num_peers, peer_stats_size);
652
653 results = (uint8_t *) link_stats_results->results;
654 t_peer_stats = (uint8_t *) peer_stats;
655 t_rate_stats = (uint8_t *) rate_stats;
656 next_res_offset = peer_stats_size;
657 next_peer_offset = WMI_TLV_HDR_SIZE;
658 next_rate_offset = WMI_TLV_HDR_SIZE;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +0530659 for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530660 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 t_peer_stats + next_peer_offset, peer_info_size);
662 next_res_offset += peer_info_size;
663
664 /* Copy rate stats associated with this peer */
665 for (count = 0; count < peer_stats->num_rates; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800666 rate_stats++;
667
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530668 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 t_rate_stats + next_rate_offset,
670 rate_stats_size);
671 next_res_offset += rate_stats_size;
672 next_rate_offset += sizeof(*rate_stats);
673 }
674 next_peer_offset += sizeof(*peer_stats);
675 peer_stats++;
676 }
677
678 /* call hdd callback with Link Layer Statistics
679 * vdev_id/ifacId in link_stats_results will be
680 * used to retrieve the correct HDD context
681 */
682 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
683 WMA_LINK_LAYER_STATS_RESULTS_RSP,
684 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530685 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686
687 return 0;
688}
689
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700690/**
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700691 * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
692 * @handle: WMI handle
693 *
694 * Return: 0 on success, error number otherwise.
695 */
696static int wma_unified_radio_tx_mem_free(void *handle)
697{
698 tp_wma_handle wma_handle = (tp_wma_handle) handle;
699 tSirWifiRadioStat *rs_results;
700 uint32_t i = 0;
701
702 if (!wma_handle->link_stats_results)
703 return 0;
704
705 rs_results = (tSirWifiRadioStat *)&wma_handle->link_stats_results->results[0];
706 for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
707 rs_results += i;
708 if (rs_results->tx_time_per_power_level) {
709 qdf_mem_free(rs_results->tx_time_per_power_level);
710 rs_results->tx_time_per_power_level = NULL;
711 }
712
713 if (rs_results->channels) {
714 qdf_mem_free(rs_results->channels);
715 rs_results->channels = NULL;
716 }
717 }
718
719 qdf_mem_free(wma_handle->link_stats_results);
720 wma_handle->link_stats_results = NULL;
721
722 return 0;
723}
724
725/**
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700726 * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
727 * @handle: WMI handle
728 * @cmd_param_info: command param info
729 * @len: Length of @cmd_param_info
730 *
731 * This is the WMI event handler function to receive radio stats tx
732 * power level stats.
733 *
734 * Return: 0 on success, error number otherwise.
735*/
736static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
737 u_int8_t *cmd_param_info, u_int32_t len)
738{
739 tp_wma_handle wma_handle = (tp_wma_handle) handle;
740 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
741 wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
742 uint8_t *tx_power_level_values;
743 tSirLLStatsResults *link_stats_results;
744 tSirWifiRadioStat *rs_results;
745
746 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
747
748 if (!mac) {
749 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
750 return -EINVAL;
751 }
752
753 if (!mac->sme.pLinkLayerStatsIndCallback) {
754 WMA_LOGD("%s: HDD callback is null", __func__);
755 return -EINVAL;
756 }
757
758 param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)cmd_param_info;
759 if (!param_tlvs) {
760 WMA_LOGA("%s: Invalid tx power level stats event", __func__);
761 return -EINVAL;
762 }
763
764 fixed_param = param_tlvs->fixed_param;
765 if (!fixed_param) {
766 WMA_LOGA("%s: Invalid param_tlvs for Radio tx_power level Stats", __func__);
767 return -EINVAL;
768 }
769
770 link_stats_results = wma_handle->link_stats_results;
Srinivas Girigowda52cbce42016-10-25 14:11:58 -0700771 if (!link_stats_results) {
772 WMA_LOGA("%s: link_stats_results is NULL", __func__);
773 return -EINVAL;
774 }
775
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700776 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 -0700777 __func__, fixed_param->total_num_tx_power_levels,
778 fixed_param->num_tx_power_levels,
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700779 fixed_param->power_level_offset,
780 fixed_param->radio_id);
781
782 rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] + fixed_param->radio_id;
783 tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700784
785 rs_results->total_num_tx_power_levels =
786 fixed_param->total_num_tx_power_levels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700787 if (!rs_results->total_num_tx_power_levels) {
788 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700789 goto post_stats;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700790 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700791
792 if (!rs_results->tx_time_per_power_level) {
793 rs_results->tx_time_per_power_level = qdf_mem_malloc(
794 sizeof(uint32_t) *
795 rs_results->total_num_tx_power_levels);
796 if (!rs_results->tx_time_per_power_level) {
797 WMA_LOGA("%s: Mem alloc failed for tx power level stats", __func__);
798 /* In error case, atleast send the radio stats without
799 * tx_power_level stats */
800 rs_results->total_num_tx_power_levels = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700801 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700802 goto post_stats;
803 }
804 }
805 qdf_mem_copy(&rs_results->tx_time_per_power_level[fixed_param->power_level_offset],
806 tx_power_level_values,
807 sizeof(uint32_t) * fixed_param->num_tx_power_levels);
808 if (rs_results->total_num_tx_power_levels ==
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700809 (fixed_param->num_tx_power_levels + fixed_param->power_level_offset)) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700810 link_stats_results->moreResultToFollow = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700811 link_stats_results->nr_received++;
812 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700813
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700814 WMA_LOGD("%s: moreResultToFollow: %u nr: %u nr_received: %u",
815 __func__, link_stats_results->moreResultToFollow,
816 link_stats_results->num_radio,
817 link_stats_results->nr_received);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700818
819 /* If still data to receive, return from here */
820 if (link_stats_results->moreResultToFollow)
821 return 0;
822
823post_stats:
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700824 if (link_stats_results->num_radio != link_stats_results->nr_received) {
825 /* Not received all radio stats yet, don't post yet */
826 return 0;
827 }
828
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700829 /* call hdd callback with Link Layer Statistics
830 * vdev_id/ifacId in link_stats_results will be
831 * used to retrieve the correct HDD context
832 */
833 mac->sme.pLinkLayerStatsIndCallback(mac->hHdd,
834 WMA_LINK_LAYER_STATS_RESULTS_RSP,
835 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700836 wma_unified_radio_tx_mem_free(handle);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700837
838 return 0;
839}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840
841/**
842 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
843 * @handle: wma handle
844 * @cmd_param_info: data received with event from fw
845 * @len: length of data
846 *
847 * Return: 0 for success or error code
848 */
849static int wma_unified_link_radio_stats_event_handler(void *handle,
850 uint8_t *cmd_param_info,
851 uint32_t len)
852{
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700853 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
855 wmi_radio_link_stats_event_fixed_param *fixed_param;
856 wmi_radio_link_stats *radio_stats;
857 wmi_channel_stats *channel_stats;
858 tSirLLStatsResults *link_stats_results;
859 uint8_t *results, *t_radio_stats, *t_channel_stats;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700860 uint32_t next_chan_offset, count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861 size_t radio_stats_size, chan_stats_size;
862 size_t link_stats_results_size;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700863 tSirWifiRadioStat *rs_results;
864 tSirWifiChannelStats *chn_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800865
Anurag Chouhan6d760662016-02-20 16:05:43 +0530866 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867
868 if (!pMac) {
869 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
870 return -EINVAL;
871 }
872
873 if (!pMac->sme.pLinkLayerStatsIndCallback) {
874 WMA_LOGD("%s: HDD callback is null", __func__);
875 return -EINVAL;
876 }
877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
879 if (!param_tlvs) {
880 WMA_LOGA("%s: Invalid stats event", __func__);
881 return -EINVAL;
882 }
883
884 /*
885 * cmd_param_info contains
886 * wmi_radio_link_stats_event_fixed_param fixed_param;
887 * size of(struct wmi_radio_link_stats);
888 * num_channels * size of(struct wmi_channel_stats)
889 */
890 fixed_param = param_tlvs->fixed_param;
891 radio_stats = param_tlvs->radio_stats;
892 channel_stats = param_tlvs->channel_stats;
893
894 if (!fixed_param || !radio_stats ||
895 (radio_stats->num_channels && !channel_stats)) {
896 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
897 return -EINVAL;
898 }
899
900 radio_stats_size = sizeof(tSirWifiRadioStat);
901 chan_stats_size = sizeof(tSirWifiChannelStats);
902 link_stats_results_size = sizeof(*link_stats_results) +
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700903 fixed_param->num_radio * radio_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700905 if (!wma_handle->link_stats_results) {
906 wma_handle->link_stats_results = qdf_mem_malloc(link_stats_results_size);
907 if (NULL == wma_handle->link_stats_results) {
908 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
909 __func__, link_stats_results_size);
910 return -ENOMEM;
911 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 }
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700913 link_stats_results = wma_handle->link_stats_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700915 WMA_LOGD("Radio stats Fixed Param:");
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700916 WMA_LOGD("req_id: %u num_radio: %u more_radio_events: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 fixed_param->request_id, fixed_param->num_radio,
918 fixed_param->more_radio_events);
919
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700920 WMA_LOGD("Radio Info: radio_id: %u on_time: %u tx_time: %u rx_time: %u on_time_scan: %u "
921 "on_time_nbd: %u on_time_gscan: %u on_time_roam_scan: %u "
922 "on_time_pno_scan: %u on_time_hs20: %u num_channels: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 radio_stats->radio_id, radio_stats->on_time,
924 radio_stats->tx_time, radio_stats->rx_time,
925 radio_stats->on_time_scan, radio_stats->on_time_nbd,
926 radio_stats->on_time_gscan,
927 radio_stats->on_time_roam_scan,
928 radio_stats->on_time_pno_scan,
929 radio_stats->on_time_hs20, radio_stats->num_channels);
930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
932 link_stats_results->rspId = fixed_param->request_id;
933 link_stats_results->ifaceId = 0;
934 link_stats_results->num_radio = fixed_param->num_radio;
935 link_stats_results->peer_event_number = 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700936
937 /*
938 * Backward compatibility:
939 * There are firmware(s) which will send Radio stats only with
940 * more_radio_events set to 0 and firmware which sends Radio stats
941 * followed by tx_power level stats with more_radio_events set to 1.
942 * if more_radio_events is set to 1, buffer the radio stats and
943 * wait for tx_power_level stats.
944 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800945 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
946
947 results = (uint8_t *) link_stats_results->results;
948 t_radio_stats = (uint8_t *) radio_stats;
949 t_channel_stats = (uint8_t *) channel_stats;
950
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700951 rs_results = (tSirWifiRadioStat *) &results[0] + radio_stats->radio_id;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -0700952 rs_results->radio = radio_stats->radio_id;
953 rs_results->onTime = radio_stats->on_time;
954 rs_results->txTime = radio_stats->tx_time;
955 rs_results->rxTime = radio_stats->rx_time;
956 rs_results->onTimeScan = radio_stats->on_time_scan;
957 rs_results->onTimeNbd = radio_stats->on_time_nbd;
958 rs_results->onTimeGscan = radio_stats->on_time_gscan;
959 rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
960 rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
961 rs_results->onTimeHs20 = radio_stats->on_time_hs20;
962 rs_results->total_num_tx_power_levels = 0;
963 rs_results->tx_time_per_power_level = NULL;
964 rs_results->numChannels = radio_stats->num_channels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700965 rs_results->channels = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700967 if (rs_results->numChannels) {
968 rs_results->channels = (tSirWifiChannelStats *) qdf_mem_malloc(
969 radio_stats->num_channels *
970 chan_stats_size);
971 if (rs_results->channels == NULL) {
972 WMA_LOGD("%s: could not allocate mem for channel stats (size=%zu)",
973 __func__, radio_stats->num_channels * chan_stats_size);
974 wma_unified_radio_tx_mem_free(handle);
975 return -ENOMEM;
976 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977
Srinivas Girigowda57b450e2016-10-27 21:00:46 -0700978 chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
979 next_chan_offset = WMI_TLV_HDR_SIZE;
980 WMA_LOGD("Channel Stats Info");
981 for (count = 0; count < radio_stats->num_channels; count++) {
982 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u "
983 "center_freq1 %u radio_awake_time %u cca_busy_time %u",
984 channel_stats->channel_width,
985 channel_stats->center_freq,
986 channel_stats->center_freq0,
987 channel_stats->center_freq1,
988 channel_stats->radio_awake_time,
989 channel_stats->cca_busy_time);
990 channel_stats++;
991
992 qdf_mem_copy(chn_results,
993 t_channel_stats + next_chan_offset,
994 chan_stats_size);
995 chn_results++;
996 next_chan_offset += sizeof(*channel_stats);
997 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998 }
999
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001000 if (link_stats_results->moreResultToFollow) {
1001 /* More results coming, don't post yet */
1002 return 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001003 } else {
1004 link_stats_results->nr_received++;
1005 }
1006
1007 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1008 /* Not received all radio stats yet, don't post yet */
1009 return 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001010 }
1011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1013 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1014 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001015 wma_unified_radio_tx_mem_free(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016
1017 return 0;
1018}
1019
1020/**
1021 * wma_register_ll_stats_event_handler() - register link layer stats related
1022 * event handler
1023 * @wma_handle: wma handle
1024 *
1025 * Return: none
1026 */
1027void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
1028{
1029 if (NULL == wma_handle) {
1030 WMA_LOGE("%s: wma_handle is NULL", __func__);
1031 return;
1032 }
1033
1034 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301035 WMI_IFACE_LINK_STATS_EVENTID,
1036 wma_unified_link_iface_stats_event_handler,
1037 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301039 WMI_PEER_LINK_STATS_EVENTID,
1040 wma_unified_link_peer_stats_event_handler,
1041 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301043 WMI_RADIO_LINK_STATS_EVENTID,
1044 wma_unified_link_radio_stats_event_handler,
1045 WMA_RX_SERIALIZER_CTX);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001046 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1047 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID,
1048 wma_unified_radio_tx_power_level_stats_event_handler,
1049 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001050
1051 return;
1052}
1053
1054
1055/**
1056 * wma_process_ll_stats_clear_req() - clear link layer stats
1057 * @wma: wma handle
1058 * @clearReq: ll stats clear request command params
1059 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301060 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001061 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301062QDF_STATUS wma_process_ll_stats_clear_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 (tp_wma_handle wma, const tpSirLLStatsClearReq clearReq)
1064{
Govind Singh4863da42016-03-08 11:45:00 +05301065 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 int ret;
1067
1068 if (!clearReq || !wma) {
1069 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301070 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 }
1072
Govind Singh4863da42016-03-08 11:45:00 +05301073 cmd.stop_req = clearReq->stopReq;
1074 cmd.sta_id = clearReq->staId;
1075 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001076
Govind Singh4863da42016-03-08 11:45:00 +05301077 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
1078 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001079 if (ret) {
1080 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301081 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 }
1083
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301084 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001085}
1086
1087/**
1088 * wma_process_ll_stats_set_req() - link layer stats set request
1089 * @wma: wma handle
1090 * @setReq: ll stats set request command params
1091 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301092 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001093 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301094QDF_STATUS wma_process_ll_stats_set_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001095 (tp_wma_handle wma, const tpSirLLStatsSetReq setReq)
1096{
Govind Singh4863da42016-03-08 11:45:00 +05301097 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001098 int ret;
1099
1100 if (!setReq || !wma) {
1101 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301102 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 }
1104
Govind Singh4863da42016-03-08 11:45:00 +05301105 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
1106 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107 setReq->aggressiveStatisticsGathering;
1108
Govind Singh4863da42016-03-08 11:45:00 +05301109 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
1110 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 if (ret) {
1112 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301113 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 }
1115
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301116 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117}
1118
1119/**
1120 * wma_process_ll_stats_get_req() - link layer stats get request
1121 * @wma:wma handle
1122 * @getReq:ll stats get request command params
1123 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301124 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001125 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301126QDF_STATUS wma_process_ll_stats_get_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001127 (tp_wma_handle wma, const tpSirLLStatsGetReq getReq)
1128{
Govind Singh4863da42016-03-08 11:45:00 +05301129 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130 int ret;
1131
1132 if (!getReq || !wma) {
1133 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301134 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135 }
1136
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +05301137 if (!wma->interfaces[getReq->staId].vdev_active) {
1138 WMA_LOGE("%s: vdev not created yet", __func__);
1139 return QDF_STATUS_E_FAILURE;
1140 }
1141
Govind Singh4863da42016-03-08 11:45:00 +05301142 cmd.req_id = getReq->reqId;
1143 cmd.param_id_mask = getReq->paramIdMask;
1144 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145
Govind Singh4863da42016-03-08 11:45:00 +05301146 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
1147 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 if (ret) {
1149 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301150 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 }
1152
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301153 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154}
1155
1156/**
1157 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
1158 * @wma:wma handle
1159 * @cmd_param_info: data from event
1160 * @len: length
1161 *
1162 * Return: 0 for success or error code
1163 */
1164int wma_unified_link_iface_stats_event_handler(void *handle,
1165 uint8_t *cmd_param_info,
1166 uint32_t len)
1167{
1168 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1169 wmi_iface_link_stats_event_fixed_param *fixed_param;
1170 wmi_iface_link_stats *link_stats;
1171 wmi_wmm_ac_stats *ac_stats;
1172 tSirLLStatsResults *link_stats_results;
1173 uint8_t *results, *t_link_stats, *t_ac_stats;
1174 uint32_t next_res_offset, next_ac_offset, count;
1175 uint32_t roaming_offset, roaming_size;
1176 size_t link_stats_size, ac_stats_size, iface_info_size;
1177 size_t link_stats_results_size;
1178
Anurag Chouhan6d760662016-02-20 16:05:43 +05301179 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001180
1181 if (!pMac) {
1182 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1183 return -EINVAL;
1184 }
1185
1186 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1187 WMA_LOGD("%s: HDD callback is null", __func__);
1188 return -EINVAL;
1189 }
1190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001191 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1192 if (!param_tlvs) {
1193 WMA_LOGA("%s: Invalid stats event", __func__);
1194 return -EINVAL;
1195 }
1196
1197 /*
1198 * cmd_param_info contains
1199 * wmi_iface_link_stats_event_fixed_param fixed_param;
1200 * wmi_iface_link_stats iface_link_stats;
1201 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
1202 */
1203 fixed_param = param_tlvs->fixed_param;
1204 link_stats = param_tlvs->iface_link_stats;
1205 ac_stats = param_tlvs->ac;
1206
1207 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats)) {
1208 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
1209 return -EINVAL;
1210 }
1211
1212 link_stats_size = sizeof(tSirWifiIfaceStat);
1213 iface_info_size = sizeof(tSirWifiInterfaceInfo);
1214 ac_stats_size = sizeof(tSirWifiWmmAcStat);
1215 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
1216
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301217 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 if (!link_stats_results) {
1219 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1220 __func__, link_stats_results_size);
1221 return -ENOMEM;
1222 }
1223
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301224 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225
1226 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
1227 link_stats_results->rspId = fixed_param->request_id;
1228 link_stats_results->ifaceId = fixed_param->vdev_id;
1229 link_stats_results->num_peers = link_stats->num_peers;
1230 link_stats_results->peer_event_number = 0;
1231 link_stats_results->moreResultToFollow = 0;
1232
1233 results = (uint8_t *) link_stats_results->results;
1234 t_link_stats = (uint8_t *) link_stats;
1235 t_ac_stats = (uint8_t *) ac_stats;
1236
1237 /* Copy roaming state */
1238 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
1239 roaming_size = member_size(tSirWifiInterfaceInfo, roaming);
1240
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 roaming_size);
1243
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 qdf_mem_copy(results + iface_info_size,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 t_link_stats + WMI_TLV_HDR_SIZE,
1246 link_stats_size - iface_info_size -
1247 WIFI_AC_MAX * ac_stats_size);
1248
1249 next_res_offset = link_stats_size - WIFI_AC_MAX * ac_stats_size;
1250 next_ac_offset = WMI_TLV_HDR_SIZE;
1251
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252 for (count = 0; count < link_stats->num_ac; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 ac_stats++;
1254
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301255 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256 t_ac_stats + next_ac_offset, ac_stats_size);
1257 next_res_offset += ac_stats_size;
1258 next_ac_offset += sizeof(*ac_stats);
1259 }
1260
1261 /* call hdd callback with Link Layer Statistics
1262 * vdev_id/ifacId in link_stats_results will be
1263 * used to retrieve the correct HDD context
1264 */
1265 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1266 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1267 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301268 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269
1270 return 0;
1271}
1272
1273#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1274
1275/**
1276 * wma_update_pdev_stats() - update pdev stats
1277 * @wma: wma handle
1278 * @pdev_stats: pdev stats
1279 *
1280 * Return: none
1281 */
1282static void wma_update_pdev_stats(tp_wma_handle wma,
1283 wmi_pdev_stats *pdev_stats)
1284{
1285 tAniGetPEStatsRsp *stats_rsp_params;
1286 uint32_t temp_mask;
1287 uint8_t *stats_buf;
1288 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
1289 struct wma_txrx_node *node;
1290 uint8_t i;
1291
1292 for (i = 0; i < wma->max_bssid; i++) {
1293 node = &wma->interfaces[i];
1294 stats_rsp_params = node->stats_rsp;
1295 if (stats_rsp_params) {
1296 node->fw_stats_set |= FW_PDEV_STATS_SET;
1297 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
1298 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1299 temp_mask = stats_rsp_params->statsMask;
1300 if (temp_mask & (1 << eCsrSummaryStats))
1301 stats_buf += sizeof(tCsrSummaryStatsInfo);
1302
1303 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
1304 classa_stats =
1305 (tCsrGlobalClassAStatsInfo *) stats_buf;
1306 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
1307 }
1308 }
1309 }
1310}
1311
1312/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05301313 * wma_vdev_stats_lost_link_helper() - helper function to extract
1314 * lost link information from vdev statistics event while deleting BSS.
1315 * @wma: WMA handle
1316 * @vdev_stats: statistics information from firmware
1317 *
1318 * This is for informing HDD to collect lost link information while
1319 * disconnection. Following conditions to check
1320 * 1. vdev is up
1321 * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to
1322 * zero, hence add the check here to indicate the event comes during deleting
1323 * BSS
1324 * 3. DELETE_BSS is the request message queued. Put this condition check on the
1325 * last one as it consumes more resource searching entries in the list
1326 *
1327 * Return: none
1328 */
1329static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma,
1330 wmi_vdev_stats *vdev_stats)
1331{
1332 struct wma_txrx_node *node;
1333 int32_t rssi;
1334 struct wma_target_req *req_msg;
1335 static const uint8_t zero_mac[QDF_MAC_ADDR_SIZE] = {0};
1336
1337 node = &wma->interfaces[vdev_stats->vdev_id];
Mukul Sharmaf9047232017-03-02 16:58:56 +05301338 if (wma_is_vdev_up(vdev_stats->vdev_id) &&
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05301339 qdf_mem_cmp(node->bssid, zero_mac, QDF_MAC_ADDR_SIZE)) {
1340 req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id,
1341 WMA_TARGET_REQ_TYPE_VDEV_STOP);
1342 if ((NULL == req_msg) ||
1343 (WMA_DELETE_BSS_REQ != req_msg->msg_type)) {
1344 WMA_LOGD(FL("cannot find DELETE_BSS request message"));
1345 return;
1346 }
1347 WMA_LOGD(FL("get vdev id %d, beancon snr %d, data snr %d"),
1348 vdev_stats->vdev_id,
1349 vdev_stats->vdev_snr.bcn_snr,
1350 vdev_stats->vdev_snr.dat_snr);
1351 if (WMA_TGT_INVALID_SNR != vdev_stats->vdev_snr.bcn_snr)
1352 rssi = vdev_stats->vdev_snr.bcn_snr;
1353 else if (WMA_TGT_INVALID_SNR != vdev_stats->vdev_snr.dat_snr)
1354 rssi = vdev_stats->vdev_snr.dat_snr;
1355 else
1356 rssi = WMA_TGT_INVALID_SNR;
1357
1358 /* Get the absolute rssi value from the current rssi value */
1359 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
1360 wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi);
1361 }
1362}
1363
1364/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 * wma_update_vdev_stats() - update vdev stats
1366 * @wma: wma handle
1367 * @vdev_stats: vdev stats
1368 *
1369 * Return: none
1370 */
1371static void wma_update_vdev_stats(tp_wma_handle wma,
1372 wmi_vdev_stats *vdev_stats)
1373{
1374 tAniGetPEStatsRsp *stats_rsp_params;
1375 tCsrSummaryStatsInfo *summary_stats = NULL;
1376 uint8_t *stats_buf;
1377 struct wma_txrx_node *node;
1378 uint8_t i;
1379 int8_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301380 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08001382 struct scheduler_msg sme_msg = { 0 };
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001383 int8_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384
Naveen Rawat2cb788d2016-10-11 17:44:44 -07001385 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
1386 dat_snr = vdev_stats->vdev_snr.dat_snr;
1387 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
1388 vdev_stats->vdev_id, bcn_snr, dat_snr);
1389
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 node = &wma->interfaces[vdev_stats->vdev_id];
1391 stats_rsp_params = node->stats_rsp;
1392 if (stats_rsp_params) {
1393 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1394 node->fw_stats_set |= FW_VDEV_STATS_SET;
1395 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
1396 vdev_stats->vdev_id);
1397 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
1398 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
1399 for (i = 0; i < 4; i++) {
1400 summary_stats->tx_frm_cnt[i] =
1401 vdev_stats->tx_frm_cnt[i];
1402 summary_stats->fail_cnt[i] =
1403 vdev_stats->fail_cnt[i];
1404 summary_stats->multiple_retry_cnt[i] =
1405 vdev_stats->multiple_retry_cnt[i];
1406 }
1407
1408 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
1409 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
1410 summary_stats->rx_discard_cnt =
1411 vdev_stats->rx_discard_cnt;
1412 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
1413 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
1414 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07001415 /* Update SNR and RSSI in SummaryStats */
1416 if (bcn_snr != WMA_TGT_INVALID_SNR) {
1417 summary_stats->snr = bcn_snr;
1418 summary_stats->rssi =
1419 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
1420 } else if (dat_snr != WMA_TGT_INVALID_SNR) {
1421 summary_stats->snr = dat_snr;
1422 summary_stats->rssi =
1423 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
1424 } else {
1425 summary_stats->snr = WMA_TGT_INVALID_SNR;
1426 summary_stats->rssi = 0;
1427 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001428 }
1429 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430
1431 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001432 if ((bcn_snr == WMA_TGT_INVALID_SNR) &&
1433 (dat_snr == WMA_TGT_INVALID_SNR)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 /*
1435 * Firmware sends invalid snr till it sees
1436 * Beacon/Data after connection since after
1437 * vdev up fw resets the snr to invalid.
1438 * In this duartion Host will return the last know
1439 * rssi during connection.
1440 */
1441 WMA_LOGE("Invalid SNR from firmware");
1442
1443 } else {
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001444 if (bcn_snr != WMA_TGT_INVALID_SNR) {
1445 rssi = bcn_snr;
1446 } else if (dat_snr != WMA_TGT_INVALID_SNR) {
1447 rssi = dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 }
1449
1450 /*
1451 * Get the absolute rssi value from the current rssi value
1452 * the sinr value is hardcoded into 0 in the core stack
1453 */
1454 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
1455 }
1456
1457 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
1458 pGetRssiReq->sessionId);
1459
1460 /* update the average rssi value to UMAC layer */
1461 if (NULL != pGetRssiReq->rssiCallback) {
1462 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
1463 pGetRssiReq->staId,
1464 pGetRssiReq->pDevContext);
1465 }
1466
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301467 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 wma->pGetRssiReq = NULL;
1469 }
1470
1471 if (node->psnr_req) {
1472 tAniGetSnrReq *p_snr_req = node->psnr_req;
1473
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001474 if (bcn_snr != WMA_TGT_INVALID_SNR)
1475 p_snr_req->snr = bcn_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001476 else
Naveen Rawat2cb788d2016-10-11 17:44:44 -07001477 p_snr_req->snr = dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478
1479 sme_msg.type = eWNI_SME_SNR_IND;
1480 sme_msg.bodyptr = p_snr_req;
1481 sme_msg.bodyval = 0;
1482
Rajeev Kumarb60abe42017-01-21 15:39:31 -08001483 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301484 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001485 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301486 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001487 }
1488
1489 node->psnr_req = NULL;
1490 }
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05301491 wma_vdev_stats_lost_link_helper(wma, vdev_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492}
1493
1494/**
1495 * wma_post_stats() - update stats to PE
1496 * @wma: wma handle
1497 * @node: txrx node
1498 *
1499 * Return: none
1500 */
1501static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
1502{
1503 tAniGetPEStatsRsp *stats_rsp_params;
1504
1505 stats_rsp_params = node->stats_rsp;
1506 /* send response to UMAC */
1507 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, (void *)stats_rsp_params, 0);
1508 node->stats_rsp = NULL;
1509 node->fw_stats_set = 0;
1510}
1511
1512/**
1513 * wma_update_peer_stats() - update peer stats
1514 * @wma: wma handle
1515 * @peer_stats: peer stats
1516 *
1517 * Return: none
1518 */
1519static void wma_update_peer_stats(tp_wma_handle wma,
1520 wmi_peer_stats *peer_stats)
1521{
1522 tAniGetPEStatsRsp *stats_rsp_params;
1523 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
1524 struct wma_txrx_node *node;
1525 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
1526 uint32_t temp_mask;
1527
1528 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
1529 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
1530 return;
1531
1532 node = &wma->interfaces[vdev_id];
1533 if (node->stats_rsp) {
1534 node->fw_stats_set |= FW_PEER_STATS_SET;
1535 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
1536 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
1537 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1538 temp_mask = stats_rsp_params->statsMask;
1539 if (temp_mask & (1 << eCsrSummaryStats))
1540 stats_buf += sizeof(tCsrSummaryStatsInfo);
1541
1542 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
1543 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
1544 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
1545 /*The linkspeed returned by fw is in kbps so convert
1546 *it in to units of 500kbps which is expected by UMAC*/
1547 if (peer_stats->peer_tx_rate) {
1548 classa_stats->tx_rate =
1549 peer_stats->peer_tx_rate / 500;
1550 }
1551
1552 classa_stats->tx_rate_flags = node->rate_flags;
1553 if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) {
1554 classa_stats->mcs_index =
1555 wma_get_mcs_idx((peer_stats->peer_tx_rate /
1556 100), node->rate_flags,
1557 node->nss, &mcsRateFlags);
Jeff Johnsonad0b2c62017-03-16 14:37:38 -07001558 classa_stats->nss = node->nss;
1559 classa_stats->mcs_rate_flags = mcsRateFlags;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001560 }
1561 /* FW returns tx power in intervals of 0.5 dBm
1562 Convert it back to intervals of 1 dBm */
1563 classa_stats->max_pwr =
1564 roundup(classa_stats->max_pwr, 2) >> 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001565 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001566 }
1567}
1568
1569/**
1570 * wma_post_link_status() - post link status to SME
1571 * @pGetLinkStatus: SME Link status
1572 * @link_status: Link status
1573 *
1574 * Return: none
1575 */
1576void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
1577 uint8_t link_status)
1578{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301579 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08001580 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581
1582 pGetLinkStatus->linkStatus = link_status;
1583 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
1584 sme_msg.bodyptr = pGetLinkStatus;
1585 sme_msg.bodyval = 0;
1586
Rajeev Kumarb60abe42017-01-21 15:39:31 -08001587 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301588 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001589 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301590 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591 }
1592}
1593
1594/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301595 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
1596 * @wma: wma handle
1597 * @rssi_stats: rssi stats
1598 * @rssi_per_chain_stats: buffer where rssi stats to be stored
1599 *
1600 * This function stores per chain rssi stats received from fw for all vdevs for
1601 * which the stats were requested into a csr stats structure.
1602 *
1603 * Return: void
1604 */
1605static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
1606 wmi_rssi_stats *rssi_stats,
1607 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
1608{
1609 int i;
1610 int8_t bcn_snr, dat_snr;
1611
1612 for (i = 0; i < NUM_CHAINS_MAX; i++) {
1613 bcn_snr = rssi_stats->rssi_avg_beacon[i];
1614 dat_snr = rssi_stats->rssi_avg_data[i];
1615 WMA_LOGD("chain %d beacon snr %d data snr %d",
1616 i, bcn_snr, dat_snr);
1617 if (dat_snr != WMA_TGT_INVALID_SNR)
1618 rssi_per_chain_stats->rssi[i] = dat_snr;
1619 else if (bcn_snr != WMA_TGT_INVALID_SNR)
1620 rssi_per_chain_stats->rssi[i] = bcn_snr;
1621 else
1622 /*
1623 * Firmware sends invalid snr till it sees
1624 * Beacon/Data after connection since after
1625 * vdev up fw resets the snr to invalid.
1626 * In this duartion Host will return an invalid rssi
1627 * value.
1628 */
1629 rssi_per_chain_stats->rssi[i] = WMA_TGT_RSSI_INVALID;
1630
1631 /*
1632 * Get the absolute rssi value from the current rssi value the
1633 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
1634 */
1635 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
1636 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
1637 rssi_per_chain_stats->peer_mac_addr);
1638 }
1639}
1640
1641/**
1642 * wma_update_rssi_stats() - to update rssi stats for all vdevs
1643 * for which the stats were requested.
1644 * @wma: wma handle
1645 * @rssi_stats: rssi stats
1646 *
1647 * This function updates the rssi stats for all vdevs for which
1648 * the stats were requested.
1649 *
1650 * Return: void
1651 */
1652static void wma_update_rssi_stats(tp_wma_handle wma,
1653 wmi_rssi_stats *rssi_stats)
1654{
1655 tAniGetPEStatsRsp *stats_rsp_params;
1656 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
1657 struct wma_txrx_node *node;
1658 uint8_t *stats_buf;
1659 uint32_t temp_mask;
1660 uint8_t vdev_id;
1661
1662 vdev_id = rssi_stats->vdev_id;
1663 node = &wma->interfaces[vdev_id];
1664 if (node->stats_rsp) {
1665 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
1666 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
1667 vdev_id);
1668 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
1669 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1670 temp_mask = stats_rsp_params->statsMask;
1671
1672 if (temp_mask & (1 << eCsrSummaryStats))
1673 stats_buf += sizeof(tCsrSummaryStatsInfo);
1674 if (temp_mask & (1 << eCsrGlobalClassAStats))
1675 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301676 if (temp_mask & (1 << eCsrGlobalClassDStats))
1677 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301678
1679 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
1680 rssi_per_chain_stats =
1681 (struct csr_per_chain_rssi_stats_info *)stats_buf;
1682 wma_update_per_chain_rssi_stats(wma, rssi_stats,
1683 rssi_per_chain_stats);
1684 }
1685 }
1686}
1687
1688
1689/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690 * wma_link_status_event_handler() - link status event handler
1691 * @handle: wma handle
1692 * @cmd_param_info: data from event
1693 * @len: length
1694 *
1695 * Return: 0 for success or error code
1696 */
1697int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
1698 uint32_t len)
1699{
1700 tp_wma_handle wma = (tp_wma_handle) handle;
1701 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
1702 wmi_vdev_rate_stats_event_fixed_param *event;
1703 wmi_vdev_rate_ht_info *ht_info;
1704 struct wma_txrx_node *intr = wma->interfaces;
1705 uint8_t link_status = LINK_STATUS_LEGACY;
1706 int i;
1707
1708 param_buf =
1709 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
1710 if (!param_buf) {
1711 WMA_LOGA("%s: Invalid stats event", __func__);
1712 return -EINVAL;
1713 }
1714
1715 event = (wmi_vdev_rate_stats_event_fixed_param *) param_buf->fixed_param;
1716 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
1717
1718 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
1719 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
1720 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
1721 __func__, ht_info->vdevid, ht_info->tx_nss,
1722 ht_info->rx_nss, ht_info->tx_preamble,
1723 ht_info->rx_preamble);
1724 if (ht_info->vdevid < wma->max_bssid
1725 && intr[ht_info->vdevid].plink_status_req) {
1726 if (ht_info->tx_nss || ht_info->rx_nss)
1727 link_status = LINK_STATUS_MIMO;
1728
1729 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
1730 (ht_info->rx_preamble == LINK_RATE_VHT))
1731 link_status |= LINK_STATUS_VHT;
1732
1733 if (intr[ht_info->vdevid].nss == 2)
1734 link_status |= LINK_SUPPORT_MIMO;
1735
1736 if (intr[ht_info->vdevid].rate_flags &
1737 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
1738 eHAL_TX_RATE_VHT80))
1739 link_status |= LINK_SUPPORT_VHT;
1740
1741 wma_post_link_status(intr[ht_info->vdevid].plink_status_req,
1742 link_status);
1743 intr[ht_info->vdevid].plink_status_req = NULL;
1744 link_status = LINK_STATUS_LEGACY;
1745 }
1746
1747 ht_info++;
1748 }
1749
1750 return 0;
1751}
1752
1753/**
1754 * wma_stats_event_handler() - stats event handler
1755 * @handle: wma handle
1756 * @cmd_param_info: data from event
1757 * @len: length
1758 *
1759 * Return: 0 for success or error code
1760 */
1761int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
1762 uint32_t len)
1763{
1764 tp_wma_handle wma = (tp_wma_handle) handle;
1765 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
1766 wmi_stats_event_fixed_param *event;
1767 wmi_pdev_stats *pdev_stats;
1768 wmi_vdev_stats *vdev_stats;
1769 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301770 wmi_rssi_stats *rssi_stats;
1771 wmi_per_chain_rssi_stats *rssi_event;
1772 struct wma_txrx_node *node;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001773 uint8_t i, *temp;
1774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
1776 if (!param_buf) {
1777 WMA_LOGA("%s: Invalid stats event", __func__);
1778 return -EINVAL;
1779 }
1780 event = param_buf->fixed_param;
1781 temp = (uint8_t *) param_buf->data;
1782
1783 WMA_LOGD("%s: num_stats: pdev: %u vdev: %u peer %u",
1784 __func__, event->num_pdev_stats, event->num_vdev_stats,
1785 event->num_peer_stats);
1786 if (event->num_pdev_stats > 0) {
1787 for (i = 0; i < event->num_pdev_stats; i++) {
1788 pdev_stats = (wmi_pdev_stats *) temp;
1789 wma_update_pdev_stats(wma, pdev_stats);
1790 temp += sizeof(wmi_pdev_stats);
1791 }
1792 }
1793
1794 if (event->num_vdev_stats > 0) {
1795 for (i = 0; i < event->num_vdev_stats; i++) {
1796 vdev_stats = (wmi_vdev_stats *) temp;
1797 wma_update_vdev_stats(wma, vdev_stats);
1798 temp += sizeof(wmi_vdev_stats);
1799 }
1800 }
1801
1802 if (event->num_peer_stats > 0) {
1803 for (i = 0; i < event->num_peer_stats; i++) {
1804 peer_stats = (wmi_peer_stats *) temp;
1805 wma_update_peer_stats(wma, peer_stats);
1806 temp += sizeof(wmi_peer_stats);
1807 }
1808 }
1809
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301810 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
1811 if (rssi_event) {
Himanshu Agarwalcd8a84a2016-07-21 14:59:50 +05301812 if (((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
1813 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) &&
1814 ((rssi_event->tlv_header & 0x0000FFFF) ==
1815 WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats))) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301816 if (rssi_event->num_per_chain_rssi_stats > 0) {
1817 temp = (uint8_t *) rssi_event;
1818 temp += sizeof(*rssi_event);
Dustin Brownc4a5ba22016-11-10 17:21:18 -08001819
1820 /* skip past struct array tlv header */
1821 temp += WMI_TLV_HDR_SIZE;
1822
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301823 for (i = 0;
1824 i < rssi_event->num_per_chain_rssi_stats;
1825 i++) {
1826 rssi_stats = (wmi_rssi_stats *)temp;
1827 wma_update_rssi_stats(wma, rssi_stats);
1828 temp += sizeof(wmi_rssi_stats);
1829 }
1830 }
1831 }
1832 }
1833
1834 for (i = 0; i < wma->max_bssid; i++) {
1835 node = &wma->interfaces[i];
1836 if (node->fw_stats_set & FW_PEER_STATS_SET) {
1837 WMA_LOGD("<--STATS RSP VDEV_ID:%d", i);
1838 wma_post_stats(wma, node);
1839 }
1840 }
1841
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001842 WMA_LOGI("%s: Exit", __func__);
1843 return 0;
1844}
1845
1846/**
1847 * wma_send_link_speed() - send link speed to SME
1848 * @link_speed: link speed
1849 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301850 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301852QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301854 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08001855 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 tSirLinkSpeedInfo *ls_ind =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301857 (tSirLinkSpeedInfo *) qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 if (!ls_ind) {
1859 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301860 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 } else {
1862 ls_ind->estLinkSpeed = link_speed;
1863 sme_msg.type = eWNI_SME_LINK_SPEED_IND;
1864 sme_msg.bodyptr = ls_ind;
1865 sme_msg.bodyval = 0;
1866
Rajeev Kumarb60abe42017-01-21 15:39:31 -08001867 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301868 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869 WMA_LOGE("%s: Fail to post linkspeed ind msg",
1870 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301871 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001872 }
1873 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301874 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875}
1876
1877/**
1878 * wma_link_speed_event_handler() - link speed event handler
1879 * @handle: wma handle
1880 * @cmd_param_info: event data
1881 * @len: length
1882 *
1883 * Return: 0 for success or error code
1884 */
1885int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
1886 uint32_t len)
1887{
1888 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
1889 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301890 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891
1892 param_buf =
1893 (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *) cmd_param_info;
1894 if (!param_buf) {
1895 WMA_LOGE("%s: Invalid linkspeed event", __func__);
1896 return -EINVAL;
1897 }
1898 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301899 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
1900 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 return -EINVAL;
1902 }
1903 return 0;
1904}
1905
1906/**
1907 * wma_wni_cfg_dnld() - cfg download request
1908 * @handle: wma handle
1909 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301910 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301912QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301914 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301915 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916
1917 WMA_LOGD("%s: Enter", __func__);
1918
1919 if (NULL == mac) {
1920 WMA_LOGP("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301921 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301922 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 }
1924
1925 process_cfg_download_req(mac);
1926
1927 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301928 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929}
1930
1931/**
1932 * wma_unified_debug_print_event_handler() - debug print event handler
1933 * @handle: wma handle
1934 * @datap: data pointer
1935 * @len: length
1936 *
1937 * Return: 0 for success or error code
1938 */
1939int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
1940 uint32_t len)
1941{
1942 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
1943 uint8_t *data;
1944 uint32_t datalen;
1945
1946 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
1947 if (!param_buf) {
1948 WMA_LOGE("Get NULL point message from FW");
1949 return -ENOMEM;
1950 }
1951 data = param_buf->data;
1952 datalen = param_buf->num_data;
1953
1954#ifdef BIG_ENDIAN_HOST
1955 {
1956 char dbgbuf[500] = { 0 };
1957 memcpy(dbgbuf, data, datalen);
1958 SWAPME(dbgbuf, datalen);
1959 WMA_LOGD("FIRMWARE:%s", dbgbuf);
1960 return 0;
1961 }
1962#else
1963 WMA_LOGD("FIRMWARE:%s", data);
1964 return 0;
1965#endif /* BIG_ENDIAN_HOST */
1966}
1967
1968/**
1969 * wma_check_scan_in_progress() - check scan is progress or not
1970 * @handle: wma handle
1971 *
1972 * Return: true/false
1973 */
1974bool wma_check_scan_in_progress(WMA_HANDLE handle)
1975{
Nitesh Shah0f3fce52016-10-13 22:01:41 +05301976 tp_wma_handle wma = handle;
1977 return qdf_atomic_read(&wma->num_pending_scans) > 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978}
1979
1980/**
1981 * wma_is_sap_active() - check sap is active or not
1982 * @handle: wma handle
1983 *
1984 * Return: true/false
1985 */
1986bool wma_is_sap_active(tp_wma_handle wma_handle)
1987{
1988 int i;
1989
1990 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05301991 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 continue;
1993 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
1994 wma_handle->interfaces[i].sub_type == 0)
1995 return true;
1996 }
1997 return false;
1998}
1999
2000/**
2001 * wma_is_p2p_go_active() - check p2p go is active or not
2002 * @handle: wma handle
2003 *
2004 * Return: true/false
2005 */
2006bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
2007{
2008 int i;
2009
2010 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05302011 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 continue;
2013 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
2014 wma_handle->interfaces[i].sub_type ==
2015 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
2016 return true;
2017 }
2018 return false;
2019}
2020
2021/**
2022 * wma_is_p2p_cli_active() - check p2p cli is active or not
2023 * @handle: wma handle
2024 *
2025 * Return: true/false
2026 */
2027bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
2028{
2029 int i;
2030
2031 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05302032 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033 continue;
2034 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
2035 wma_handle->interfaces[i].sub_type ==
2036 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
2037 return true;
2038 }
2039 return false;
2040}
2041
2042/**
2043 * wma_is_sta_active() - check sta is active or not
2044 * @handle: wma handle
2045 *
2046 * Return: true/false
2047 */
2048bool wma_is_sta_active(tp_wma_handle wma_handle)
2049{
2050 int i;
2051
2052 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05302053 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054 continue;
2055 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
2056 wma_handle->interfaces[i].sub_type == 0)
2057 return true;
2058 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
2059 return true;
2060 }
2061 return false;
2062}
2063
2064/**
2065 * wma_peer_phymode() - get phymode
2066 * @nw_type: nw type
2067 * @sta_type: sta type
2068 * @is_ht: is ht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002069 * @ch_width: supported channel width
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 * @is_vht: is vht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002071 * @is_he: is HE supported
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 *
2073 * Return: WLAN_PHY_MODE
2074 */
2075WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
2076 uint8_t is_ht, uint8_t ch_width,
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002077 uint8_t is_vht, bool is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078{
2079 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
2080
2081 switch (nw_type) {
2082 case eSIR_11B_NW_TYPE:
2083 phymode = MODE_11B;
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002084 if (is_ht || is_vht || is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 WMA_LOGE("HT/VHT is enabled with 11B NW type");
2086 break;
2087 case eSIR_11G_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002088 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002089 phymode = MODE_11G;
2090 break;
2091 }
2092 if (CH_WIDTH_40MHZ < ch_width)
2093 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
2094 if (ch_width)
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002095 phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ?
2096 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002097 else
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002098 phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ?
2099 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100 break;
2101 case eSIR_11A_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002102 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103 phymode = MODE_11A;
2104 break;
2105 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002106 if (is_he) {
2107 if (ch_width == CH_WIDTH_160MHZ)
2108 phymode = MODE_11AX_HE160;
2109 else if (ch_width == CH_WIDTH_80P80MHZ)
2110 phymode = MODE_11AX_HE80_80;
2111 else if (ch_width == CH_WIDTH_80MHZ)
2112 phymode = MODE_11AX_HE80;
2113 else
2114 phymode = (ch_width) ?
2115 MODE_11AX_HE40 : MODE_11AX_HE20;
2116 } else if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117 if (ch_width == CH_WIDTH_160MHZ)
2118 phymode = MODE_11AC_VHT160;
2119 else if (ch_width == CH_WIDTH_80P80MHZ)
2120 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07002121 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 phymode = MODE_11AC_VHT80;
2123 else
2124 phymode = (ch_width) ?
2125 MODE_11AC_VHT40 : MODE_11AC_VHT20;
2126 } else
2127 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
2128 break;
2129 default:
2130 WMA_LOGP("%s: Invalid nw type %d", __func__, nw_type);
2131 break;
2132 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08002133 WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"),
2134 nw_type, is_ht, ch_width, is_vht, is_he, phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002135
2136 return phymode;
2137}
2138
2139/**
2140 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
2141 * @wma_handle: wma handle
2142 * @vdev_id: vdev id
2143 * @value: value
2144 *
2145 * Return: 0 for success or return error
2146 */
2147int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
2148 uint8_t vdev_id, uint32_t value)
2149{
2150 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08002151 struct cdp_vdev *vdev;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05302152 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2153
2154 if (!soc) {
2155 WMA_LOGE("%s:SOC context is NULL", __func__);
2156 return -EINVAL;
2157 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002158
2159 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
2160 if (!vdev) {
2161 WMA_LOGE("%s:Invalid vdev handle", __func__);
2162 return -EINVAL;
2163 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302164 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165 req.stats_type_reset_mask = value;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08002166 cdp_fw_stats_get(soc, vdev, &req, false, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167
2168 return 0;
2169}
2170
2171#ifdef HELIUMPLUS
Jeff Johnson560dc562017-03-17 15:19:31 -07002172#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 ((_mask) = 1 << (_rate_info ## _V2))
2174#else /* !HELIUMPLUS */
Jeff Johnson560dc562017-03-17 15:19:31 -07002175#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 ((_mask) = 1 << (_rate_info))
2177#endif
2178
Nirav Shah93e789e2016-04-14 19:47:43 +05302179#ifdef HELIUMPLUS
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002180static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05302181{
2182 if (value > (HTT_DBG_NUM_STATS + 1) ||
2183 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
2184 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
2185 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
2186 WMA_LOGE("%s: Not supported", __func__);
2187 return false;
2188 }
2189 return true;
2190}
2191#else
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002192static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05302193{
2194 if (value > (HTT_DBG_NUM_STATS + 1) ||
2195 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
2196 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
2197 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
2198 WMA_LOGE("%s: Not supported", __func__);
2199 return false;
2200 }
2201 return true;
2202}
2203#endif
2204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002205/**
2206 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
2207 * @wma_handle: wma handle
2208 * @vdev_id: vdev id
2209 * @value: value
2210 *
2211 * Return: 0 for success or return error
2212 */
2213int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
2214 uint8_t vdev_id, uint32_t value)
2215{
2216 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08002217 struct cdp_vdev *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 uint32_t l_up_mask;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05302219 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2220
2221 if (!soc) {
2222 WMA_LOGE("%s:SOC context is NULL", __func__);
2223 return -EINVAL;
2224 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225
2226 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
2227 if (!vdev) {
2228 WMA_LOGE("%s:Invalid vdev handle", __func__);
2229 return -EINVAL;
2230 }
Nirav Shah93e789e2016-04-14 19:47:43 +05302231
2232 if (wma_is_valid_fw_stats_cmd(value) == false)
2233 return -EINVAL;
2234
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302235 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236 req.print.verbose = 1;
2237
Nirav Shah93e789e2016-04-14 19:47:43 +05302238 /* TODO: Need to check how to avoid mem leak*/
2239 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240 req.stats_type_upload_mask = l_up_mask;
2241
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08002242 cdp_fw_stats_get(soc, vdev, &req, false, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002243
2244 return 0;
2245}
2246
2247/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002248 * wma_get_stats_rsp_buf() - fill get stats response buffer
2249 * @get_stats_param: get stats parameters
2250 *
2251 * Return: stats response buffer
2252 */
2253static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
2254 (tAniGetPEStatsReq *get_stats_param)
2255{
2256 tAniGetPEStatsRsp *stats_rsp_params;
Jeff Johnsondfd360e2017-03-10 16:23:07 -08002257 uint32_t len, temp_mask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258
2259 len = sizeof(tAniGetPEStatsRsp);
2260 temp_mask = get_stats_param->statsMask;
2261
Jeff Johnsondfd360e2017-03-10 16:23:07 -08002262 if (temp_mask & (1 << eCsrSummaryStats))
2263 len += sizeof(tCsrSummaryStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264
Jeff Johnsondfd360e2017-03-10 16:23:07 -08002265 if (temp_mask & (1 << eCsrGlobalClassAStats))
2266 len += sizeof(tCsrGlobalClassAStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267
Jeff Johnsondfd360e2017-03-10 16:23:07 -08002268 if (temp_mask & (1 << eCsrGlobalClassDStats))
2269 len += sizeof(tCsrGlobalClassDStatsInfo);
2270
Jeff Johnsondfd360e2017-03-10 16:23:07 -08002271 if (temp_mask & (1 << csr_per_chain_rssi_stats))
2272 len += sizeof(struct csr_per_chain_rssi_stats_info);
2273
2274 stats_rsp_params = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 if (!stats_rsp_params) {
2276 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302277 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 return NULL;
2279 }
2280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002281 stats_rsp_params->staId = get_stats_param->staId;
2282 stats_rsp_params->statsMask = get_stats_param->statsMask;
2283 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
2284 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302285 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 return stats_rsp_params;
2287}
2288
2289/**
2290 * wma_get_stats_req() - get stats request
2291 * @handle: wma handle
2292 * @get_stats_param: stats params
2293 *
2294 * Return: none
2295 */
2296void wma_get_stats_req(WMA_HANDLE handle,
2297 tAniGetPEStatsReq *get_stats_param)
2298{
2299 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2300 struct wma_txrx_node *node;
Govind Singh4863da42016-03-08 11:45:00 +05302301 struct pe_stats_req cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05302303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002304
2305 WMA_LOGD("%s: Enter", __func__);
2306 node = &wma_handle->interfaces[get_stats_param->sessionId];
2307 if (node->stats_rsp) {
2308 pGetPEStatsRspParams = node->stats_rsp;
2309 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
2310 pGetPEStatsRspParams->statsMask ==
2311 get_stats_param->statsMask) {
2312 WMA_LOGI("Stats for staId %d with stats mask %d "
2313 "is pending.... ignore new request",
2314 get_stats_param->staId,
2315 get_stats_param->statsMask);
2316 goto end;
2317 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302318 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319 node->stats_rsp = NULL;
2320 node->fw_stats_set = 0;
2321 }
2322 }
2323
2324 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
2325 if (!pGetPEStatsRspParams)
2326 goto end;
2327
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 node->fw_stats_set = 0;
2329 node->stats_rsp = pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05302330
2331 cmd.session_id = get_stats_param->sessionId;
2332 if (wmi_unified_get_stats_cmd(wma_handle->wmi_handle, &cmd,
2333 node->bssid)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002334
2335 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
2336 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 goto failed;
2338 }
2339
2340 goto end;
2341failed:
2342
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302343 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 node->stats_rsp = NULL;
2345 /* send response to UMAC */
2346 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
2347 0);
2348end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302349 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 WMA_LOGD("%s: Exit", __func__);
2351 return;
2352}
2353
2354/**
2355 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
2356 * @vdev_id: vdev id
2357 * @buffer_size: size of buffer
2358 *
2359 * Return: none
2360 */
2361void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
2362{
2363 tp_wma_handle wma;
2364 struct beacon_info *beacon;
2365 uint8_t *buf;
2366 uint32_t buf_size;
2367
Anurag Chouhan6d760662016-02-20 16:05:43 +05302368 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002369 if (!wma) {
2370 WMA_LOGE("%s: Invalid WMA handle", __func__);
2371 return NULL;
2372 }
2373
2374 if (vdev_id >= wma->max_bssid) {
2375 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2376 return NULL;
2377 }
2378
2379 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
2380 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
2381 return NULL;
2382 }
2383
2384 beacon = wma->interfaces[vdev_id].beacon;
2385
2386 if (!beacon) {
2387 WMA_LOGE("%s: beacon invalid", __func__);
2388 return NULL;
2389 }
2390
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302391 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392
Nirav Shahcbc6d722016-03-01 16:24:53 +05302393 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302394 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395
2396 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302397 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
2399 return NULL;
2400 }
2401
Nirav Shahcbc6d722016-03-01 16:24:53 +05302402 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002403
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302404 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405
2406 if (buffer_size)
2407 *buffer_size = buf_size;
2408
2409 return buf;
2410}
2411
2412/**
2413 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
2414 * @vdev_id: vdev id
2415 *
2416 * Return: mac address
2417 */
2418uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
2419{
2420 tp_wma_handle wma;
2421
Anurag Chouhan6d760662016-02-20 16:05:43 +05302422 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 if (!wma) {
2424 WMA_LOGE("%s: Invalid WMA handle", __func__);
2425 return NULL;
2426 }
2427
2428 if (vdev_id >= wma->max_bssid) {
2429 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2430 return NULL;
2431 }
2432
2433 return wma->interfaces[vdev_id].addr;
2434}
2435
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08002436QDF_STATUS wma_get_connection_info(uint8_t vdev_id,
2437 struct policy_mgr_vdev_entry_info *conn_table_entry)
2438{
2439 struct wma_txrx_node *wma_conn_table_entry;
2440
2441 wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id);
2442 if (NULL == wma_conn_table_entry) {
2443 WMA_LOGE("%s: can't find vdev_id %d in WMA table", __func__, vdev_id);
2444 return QDF_STATUS_E_FAILURE;
2445 }
2446 conn_table_entry->chan_width = wma_conn_table_entry->chan_width;
2447 conn_table_entry->mac_id = wma_conn_table_entry->mac_id;
2448 conn_table_entry->mhz = wma_conn_table_entry->mhz;
2449 conn_table_entry->sub_type = wma_conn_table_entry->sub_type;
2450 conn_table_entry->type = wma_conn_table_entry->type;
2451
2452 return QDF_STATUS_SUCCESS;
2453}
2454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455/**
2456 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
2457 * @vdev_id: vdev id
2458 *
2459 * Return: entry from vdev table
2460 */
2461struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
2462{
2463 tp_wma_handle wma;
2464
Anurag Chouhan6d760662016-02-20 16:05:43 +05302465 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 if (!wma) {
2467 WMA_LOGE("%s: Invalid WMA handle", __func__);
2468 return NULL;
2469 }
2470
2471 if (vdev_id >= wma->max_bssid) {
2472 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2473 return NULL;
2474 }
2475
2476 return &wma->interfaces[vdev_id];
2477}
2478
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479#if defined(QCA_WIFI_FTM)
2480/**
2481 * wma_utf_rsp() - utf response
2482 * @wma_handle: wma handle
2483 * @payload: payload
2484 * @len: length of payload
2485 *
2486 * Return: 0 for success or error code
2487 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002488static int wma_utf_rsp(tp_wma_handle wma_handle, uint8_t **payload,
2489 uint32_t *len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490{
2491 int ret = -1;
2492 uint32_t payload_len;
2493
2494 payload_len = wma_handle->utf_event_info.length;
2495 if (payload_len) {
2496 ret = 0;
2497
2498 /*
2499 * The first 4 bytes holds the payload size
2500 * and the actual payload sits next to it
2501 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302502 *payload = (uint8_t *) qdf_mem_malloc((uint32_t) payload_len
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 + sizeof(A_UINT32));
2504 *(A_UINT32 *) &(*payload[0]) =
2505 wma_handle->utf_event_info.length;
2506 memcpy(*payload + sizeof(A_UINT32),
2507 wma_handle->utf_event_info.data, payload_len);
2508 wma_handle->utf_event_info.length = 0;
2509 *len = payload_len;
2510 }
2511
2512 return ret;
2513}
2514
2515/**
2516 * wma_post_ftm_response() - post ftm response to upper layer
2517 * @wma_handle: wma handle
2518 *
2519 * Return: none
2520 */
2521static void wma_post_ftm_response(tp_wma_handle wma_handle)
2522{
2523 int ret;
2524 uint8_t *payload;
2525 uint32_t data_len;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002526 struct scheduler_msg msg = { 0 };
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302527 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528
2529 ret = wma_utf_rsp(wma_handle, &payload, &data_len);
2530
2531 if (ret) {
2532 return;
2533 }
2534
2535 sys_build_message_header(SYS_MSG_ID_FTM_RSP, &msg);
2536 msg.bodyptr = payload;
2537 msg.bodyval = 0;
2538
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002539 status = scheduler_post_msg(QDF_MODULE_ID_SYS, &msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302541 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 WMA_LOGE("failed to post ftm response to SYS");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302543 qdf_mem_free(payload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 }
2545}
2546
2547/**
2548 * wma_process_utf_event() - process utf event
2549 * @handle: wma handle
2550 * @datap: data buffer
2551 * @dataplen: data length
2552 *
2553 * Return: 0 for success or error code
2554 */
2555static int
2556wma_process_utf_event(WMA_HANDLE handle, uint8_t *datap, uint32_t dataplen)
2557{
2558 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05302559 struct seg_hdr_info segHdrInfo;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 uint8_t totalNumOfSegments, currentSeq;
2561 WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf;
2562 uint8_t *data;
2563 uint32_t datalen;
2564
2565 param_buf = (WMI_PDEV_UTF_EVENTID_param_tlvs *) datap;
2566 if (!param_buf) {
2567 WMA_LOGE("Get NULL point message from FW");
2568 return -EINVAL;
2569 }
2570 data = param_buf->data;
2571 datalen = param_buf->num_data;
2572
Govind Singhd76a5b02016-03-08 15:12:14 +05302573 segHdrInfo = *(struct seg_hdr_info *) &(data[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574
2575 wma_handle->utf_event_info.currentSeq = (segHdrInfo.segmentInfo & 0xF);
2576
2577 currentSeq = (segHdrInfo.segmentInfo & 0xF);
2578 totalNumOfSegments = (segHdrInfo.segmentInfo >> 4) & 0xF;
2579
2580 datalen = datalen - sizeof(segHdrInfo);
2581
2582 if (currentSeq == 0) {
2583 wma_handle->utf_event_info.expectedSeq = 0;
2584 wma_handle->utf_event_info.offset = 0;
2585 } else {
2586 if (wma_handle->utf_event_info.expectedSeq != currentSeq)
2587 WMA_LOGE("Mismatch in expecting seq expected"
2588 " Seq %d got seq %d",
2589 wma_handle->utf_event_info.expectedSeq,
2590 currentSeq);
2591 }
2592
2593 memcpy(&wma_handle->utf_event_info.
2594 data[wma_handle->utf_event_info.offset],
2595 &data[sizeof(segHdrInfo)], datalen);
2596 wma_handle->utf_event_info.offset =
2597 wma_handle->utf_event_info.offset + datalen;
2598 wma_handle->utf_event_info.expectedSeq++;
2599
2600 if (wma_handle->utf_event_info.expectedSeq == totalNumOfSegments) {
2601 if (wma_handle->utf_event_info.offset != segHdrInfo.len)
2602 WMA_LOGE("All segs received total len mismatch.."
2603 " len %zu total len %d",
2604 wma_handle->utf_event_info.offset,
2605 segHdrInfo.len);
2606
2607 wma_handle->utf_event_info.length =
2608 wma_handle->utf_event_info.offset;
2609 }
2610
2611 wma_post_ftm_response(wma_handle);
2612
2613 return 0;
2614}
2615
2616/**
2617 * wma_utf_detach() - utf detach
2618 * @wma_handle: wma handle
2619 *
2620 * Return: none
2621 */
2622void wma_utf_detach(tp_wma_handle wma_handle)
2623{
2624 if (wma_handle->utf_event_info.data) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302625 qdf_mem_free(wma_handle->utf_event_info.data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 wma_handle->utf_event_info.data = NULL;
2627 wma_handle->utf_event_info.length = 0;
2628 wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
2629 WMI_PDEV_UTF_EVENTID);
2630 }
2631}
2632
2633/**
2634 * wma_utf_attach() - utf attach
2635 * @wma_handle: wma handle
2636 *
2637 * Return: none
2638 */
2639void wma_utf_attach(tp_wma_handle wma_handle)
2640{
2641 int ret;
2642
2643 wma_handle->utf_event_info.data = (unsigned char *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302644 qdf_mem_malloc(MAX_UTF_EVENT_LENGTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 wma_handle->utf_event_info.length = 0;
2646
2647 ret = wmi_unified_register_event_handler(wma_handle->wmi_handle,
2648 WMI_PDEV_UTF_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05302649 wma_process_utf_event,
2650 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651
2652 if (ret)
2653 WMA_LOGP("%s: Failed to register UTF event callback", __func__);
2654}
2655
2656/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 * wma_utf_cmd() - utf command
2658 * @wma_handle: wma handle
2659 * @data: data
2660 * @len: length
2661 *
Govind Singhd76a5b02016-03-08 15:12:14 +05302662 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002664static QDF_STATUS wma_utf_cmd(tp_wma_handle wma_handle, uint8_t *data,
2665 uint16_t len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666{
Govind Singhd76a5b02016-03-08 15:12:14 +05302667 struct pdev_utf_params param = {0};
2668
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 wma_handle->utf_event_info.length = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05302670 param.utf_payload = data;
2671 param.len = len;
2672
2673 return wmi_unified_pdev_utf_cmd_send(wma_handle->wmi_handle, &param,
2674 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675}
2676
2677/**
2678 * wma_process_ftm_command() - process ftm command
2679 * @wma_handle: wma handle
2680 * @msg_buffer: message buffer
2681 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302682 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302684QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685wma_process_ftm_command(tp_wma_handle wma_handle,
2686 struct ar6k_testmode_cmd_data *msg_buffer)
2687{
2688 uint8_t *data = NULL;
2689 uint16_t len = 0;
2690 int ret;
2691
2692 if (!msg_buffer)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302693 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002694
Anurag Chouhan6d760662016-02-20 16:05:43 +05302695 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 WMA_LOGE("FTM command issued in non-FTM mode");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302697 qdf_mem_free(msg_buffer->data);
2698 qdf_mem_free(msg_buffer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302699 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 }
2701
2702 data = msg_buffer->data;
2703 len = msg_buffer->len;
2704
2705 ret = wma_utf_cmd(wma_handle, data, len);
2706
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302707 qdf_mem_free(msg_buffer->data);
2708 qdf_mem_free(msg_buffer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709
2710 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302711 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002712
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302713 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714}
2715#endif /* QCA_WIFI_FTM */
2716
2717/**
2718 * wma_get_wcnss_software_version() - get wcnss software version
2719 * @p_cds_gctx: cds context
2720 * @pVersion: version pointer
2721 * @versionBufferSize: buffer size
2722 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302723 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302725QDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002726 uint8_t *pVersion,
2727 uint32_t versionBufferSize)
2728{
2729 tp_wma_handle wma_handle;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302730 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731
2732 if (NULL == wma_handle) {
2733 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302734 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 }
2736
2737 snprintf(pVersion, versionBufferSize, "%x",
2738 (unsigned int)wma_handle->target_fw_version);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302739 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740}
2741
2742/**
2743 * wma_get_tx_rx_ss_from_config() - Get Tx/Rx spatial stream from HW mode config
2744 * @mac_ss: Config which indicates the HW mode as per 'hw_mode_ss_config'
2745 * @tx_ss: Contains the Tx spatial stream
2746 * @rx_ss: Contains the Rx spatial stream
2747 *
2748 * Returns the number of spatial streams of Tx and Rx
2749 *
2750 * Return: None
2751 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07002752static void wma_get_tx_rx_ss_from_config(enum hw_mode_ss_config mac_ss,
2753 uint32_t *tx_ss, uint32_t *rx_ss)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754{
2755 switch (mac_ss) {
2756 case HW_MODE_SS_0x0:
2757 *tx_ss = 0;
2758 *rx_ss = 0;
2759 break;
2760 case HW_MODE_SS_1x1:
2761 *tx_ss = 1;
2762 *rx_ss = 1;
2763 break;
2764 case HW_MODE_SS_2x2:
2765 *tx_ss = 2;
2766 *rx_ss = 2;
2767 break;
2768 case HW_MODE_SS_3x3:
2769 *tx_ss = 3;
2770 *rx_ss = 3;
2771 break;
2772 case HW_MODE_SS_4x4:
2773 *tx_ss = 4;
2774 *rx_ss = 4;
2775 break;
2776 default:
2777 *tx_ss = 0;
2778 *rx_ss = 0;
2779 }
2780}
2781
2782/**
2783 * wma_get_matching_hw_mode_index() - Get matching HW mode index
2784 * @wma: WMA handle
2785 * @mac0_tx_ss: Number of tx spatial streams of MAC0
2786 * @mac0_rx_ss: Number of rx spatial streams of MAC0
2787 * @mac0_bw: Bandwidth of MAC0 of type 'hw_mode_bandwidth'
2788 * @mac1_tx_ss: Number of tx spatial streams of MAC1
2789 * @mac1_rx_ss: Number of rx spatial streams of MAC1
2790 * @mac1_bw: Bandwidth of MAC1 of type 'hw_mode_bandwidth'
2791 * @dbs: DBS capability of type 'hw_mode_dbs_capab'
2792 * @dfs: Agile DFS capability of type 'hw_mode_agile_dfs_capab'
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302793 * @sbs: SBS capability of type 'hw_mode_sbs_capab'
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002794 *
2795 * Fetches the HW mode index corresponding to the HW mode provided
2796 *
2797 * Return: Positive hw mode index in case a match is found or a negative
2798 * value, otherwise
2799 */
2800static int8_t wma_get_matching_hw_mode_index(tp_wma_handle wma,
2801 uint32_t mac0_tx_ss, uint32_t mac0_rx_ss,
2802 enum hw_mode_bandwidth mac0_bw,
2803 uint32_t mac1_tx_ss, uint32_t mac1_rx_ss,
2804 enum hw_mode_bandwidth mac1_bw,
2805 enum hw_mode_dbs_capab dbs,
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302806 enum hw_mode_agile_dfs_capab dfs,
2807 enum hw_mode_sbs_capab sbs)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808{
2809 uint32_t i;
2810 uint32_t t_mac0_tx_ss, t_mac0_rx_ss, t_mac0_bw;
2811 uint32_t t_mac1_tx_ss, t_mac1_rx_ss, t_mac1_bw;
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302812 uint32_t dbs_mode, agile_dfs_mode, sbs_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 int8_t found = -EINVAL;
2814
2815 if (!wma) {
2816 WMA_LOGE("%s: Invalid WMA handle", __func__);
2817 return found;
2818 }
2819
2820 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302821 t_mac0_tx_ss = WMA_HW_MODE_MAC0_TX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822 wma->hw_mode.hw_mode_list[i]);
2823 if (t_mac0_tx_ss != mac0_tx_ss)
2824 continue;
2825
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302826 t_mac0_rx_ss = WMA_HW_MODE_MAC0_RX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002827 wma->hw_mode.hw_mode_list[i]);
2828 if (t_mac0_rx_ss != mac0_rx_ss)
2829 continue;
2830
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302831 t_mac0_bw = WMA_HW_MODE_MAC0_BANDWIDTH_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 wma->hw_mode.hw_mode_list[i]);
Nitesh Shah877ad5d2016-09-22 19:27:58 +05302833 /*
2834 * Firmware advertises max bw capability as CBW 80+80
2835 * for single MAC. Thus CBW 20/40/80 should also be
2836 * supported, if CBW 80+80 is supported.
2837 */
2838 if (t_mac0_bw < mac0_bw)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 continue;
2840
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302841 t_mac1_tx_ss = WMA_HW_MODE_MAC1_TX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002842 wma->hw_mode.hw_mode_list[i]);
2843 if (t_mac1_tx_ss != mac1_tx_ss)
2844 continue;
2845
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302846 t_mac1_rx_ss = WMA_HW_MODE_MAC1_RX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 wma->hw_mode.hw_mode_list[i]);
2848 if (t_mac1_rx_ss != mac1_rx_ss)
2849 continue;
2850
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302851 t_mac1_bw = WMA_HW_MODE_MAC1_BANDWIDTH_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 wma->hw_mode.hw_mode_list[i]);
Nitesh Shah877ad5d2016-09-22 19:27:58 +05302853 if (t_mac1_bw < mac1_bw)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002854 continue;
2855
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302856 dbs_mode = WMA_HW_MODE_DBS_MODE_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857 wma->hw_mode.hw_mode_list[i]);
2858 if (dbs_mode != dbs)
2859 continue;
2860
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302861 agile_dfs_mode = WMA_HW_MODE_AGILE_DFS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 wma->hw_mode.hw_mode_list[i]);
2863 if (agile_dfs_mode != dfs)
2864 continue;
2865
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302866 sbs_mode = WMA_HW_MODE_SBS_MODE_GET(
2867 wma->hw_mode.hw_mode_list[i]);
2868 if (sbs_mode != sbs)
2869 continue;
2870
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 found = i;
2872 WMA_LOGI("%s: hw_mode index %d found",
2873 __func__, i);
2874 break;
2875 }
2876 return found;
2877}
2878
2879/**
2880 * wma_get_hw_mode_from_dbs_hw_list() - Get hw_mode index
2881 * @mac0_ss: MAC0 spatial stream configuration
2882 * @mac0_bw: MAC0 bandwidth configuration
2883 * @mac1_ss: MAC1 spatial stream configuration
2884 * @mac1_bw: MAC1 bandwidth configuration
2885 * @dbs: HW DBS capability
2886 * @dfs: HW Agile DFS capability
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302887 * @sbs: HW SBS capability
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888 *
2889 * Get the HW mode index corresponding to the HW modes spatial stream,
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302890 * bandwidth, DBS, Agile DFS and SBS capability
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 *
2892 * Return: Index number if a match is found or -negative value if not found
2893 */
2894int8_t wma_get_hw_mode_idx_from_dbs_hw_list(enum hw_mode_ss_config mac0_ss,
2895 enum hw_mode_bandwidth mac0_bw,
2896 enum hw_mode_ss_config mac1_ss,
2897 enum hw_mode_bandwidth mac1_bw,
2898 enum hw_mode_dbs_capab dbs,
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302899 enum hw_mode_agile_dfs_capab dfs,
2900 enum hw_mode_sbs_capab sbs)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901{
2902 tp_wma_handle wma;
2903 uint32_t mac0_tx_ss, mac0_rx_ss;
2904 uint32_t mac1_tx_ss, mac1_rx_ss;
2905
Anurag Chouhan6d760662016-02-20 16:05:43 +05302906 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 if (!wma) {
2908 WMA_LOGE("%s: Invalid WMA handle", __func__);
2909 return -EINVAL;
2910 }
2911
2912 wma_get_tx_rx_ss_from_config(mac0_ss, &mac0_tx_ss, &mac0_rx_ss);
2913 wma_get_tx_rx_ss_from_config(mac1_ss, &mac1_tx_ss, &mac1_rx_ss);
2914
2915 WMA_LOGI("%s: MAC0: TxSS=%d, RxSS=%d, BW=%d",
2916 __func__, mac0_tx_ss, mac0_rx_ss, mac0_bw);
2917 WMA_LOGI("%s: MAC1: TxSS=%d, RxSS=%d, BW=%d",
2918 __func__, mac1_tx_ss, mac1_rx_ss, mac1_bw);
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302919 WMA_LOGI("%s: DBS=%d, Agile DFS=%d, SBS=%d",
2920 __func__, dbs, dfs, sbs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921
2922 return wma_get_matching_hw_mode_index(wma, mac0_tx_ss, mac0_rx_ss,
2923 mac0_bw,
2924 mac1_tx_ss, mac1_rx_ss,
2925 mac1_bw,
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302926 dbs, dfs, sbs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927}
2928
2929/**
2930 * wma_get_hw_mode_from_idx() - Get HW mode based on index
2931 * @idx: HW mode index
2932 * @hw_mode: HW mode params
2933 *
2934 * Fetches the HW mode parameters
2935 *
2936 * Return: Success if hw mode is obtained and the hw mode params
2937 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302938QDF_STATUS wma_get_hw_mode_from_idx(uint32_t idx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002939 struct sir_hw_mode_params *hw_mode)
2940{
2941 tp_wma_handle wma;
2942 uint32_t param;
2943
Anurag Chouhan6d760662016-02-20 16:05:43 +05302944 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 if (!wma) {
2946 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302947 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 }
2949
2950 if (idx > wma->num_dbs_hw_modes) {
2951 WMA_LOGE("%s: Invalid index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302952 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 }
2954
Mahesh Kumar Kalikot Veetild43e1652015-11-02 15:35:10 -08002955 if (!wma->num_dbs_hw_modes) {
2956 WMA_LOGE("%s: No dbs hw modes available", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302957 return QDF_STATUS_E_FAILURE;
Mahesh Kumar Kalikot Veetild43e1652015-11-02 15:35:10 -08002958 }
2959
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 param = wma->hw_mode.hw_mode_list[idx];
2961
Nitesh Shah5b7bae02016-09-28 18:58:33 +05302962 hw_mode->mac0_tx_ss = WMA_HW_MODE_MAC0_TX_STREAMS_GET(param);
2963 hw_mode->mac0_rx_ss = WMA_HW_MODE_MAC0_RX_STREAMS_GET(param);
2964 hw_mode->mac0_bw = WMA_HW_MODE_MAC0_BANDWIDTH_GET(param);
2965 hw_mode->mac1_tx_ss = WMA_HW_MODE_MAC1_TX_STREAMS_GET(param);
2966 hw_mode->mac1_rx_ss = WMA_HW_MODE_MAC1_RX_STREAMS_GET(param);
2967 hw_mode->mac1_bw = WMA_HW_MODE_MAC1_BANDWIDTH_GET(param);
2968 hw_mode->dbs_cap = WMA_HW_MODE_DBS_MODE_GET(param);
2969 hw_mode->agile_dfs_cap = WMA_HW_MODE_AGILE_DFS_GET(param);
2970 hw_mode->sbs_cap = WMA_HW_MODE_SBS_MODE_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302972 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973}
2974
2975/**
2976 * wma_get_num_dbs_hw_modes() - Get number of HW mode
2977 *
2978 * Fetches the number of DBS HW modes returned by the FW
2979 *
2980 * Return: Negative value on error or returns the number of DBS HW modes
2981 */
2982int8_t wma_get_num_dbs_hw_modes(void)
2983{
2984 tp_wma_handle wma;
2985
Anurag Chouhan6d760662016-02-20 16:05:43 +05302986 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 if (!wma) {
2988 WMA_LOGE("%s: Invalid WMA handle", __func__);
2989 return -EINVAL;
2990 }
2991 return wma->num_dbs_hw_modes;
2992}
2993
2994/**
2995 * wma_is_hw_dbs_capable() - Check if HW is DBS capable
2996 *
2997 * Checks if the HW is DBS capable
2998 *
2999 * Return: true if the HW is DBS capable
3000 */
3001bool wma_is_hw_dbs_capable(void)
3002{
3003 tp_wma_handle wma;
3004 uint32_t param, i, found = 0;
3005
Anurag Chouhan6d760662016-02-20 16:05:43 +05303006 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 if (!wma) {
3008 WMA_LOGE("%s: Invalid WMA handle", __func__);
3009 return false;
3010 }
3011
3012 if (!wma_is_dbs_enable()) {
3013 WMA_LOGI("%s: DBS is disabled", __func__);
3014 return false;
3015 }
3016
3017 WMA_LOGI("%s: DBS service bit map: %d", __func__,
3018 WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3019 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT));
3020
3021 /* The agreement with FW is that: To know if the target is DBS
3022 * capable, DBS needs to be supported both in the HW mode list
3023 * and in the service ready event
3024 */
3025 if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3026 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT)))
3027 return false;
3028
3029 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
3030 param = wma->hw_mode.hw_mode_list[i];
3031 WMA_LOGI("%s: HW param: %x", __func__, param);
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303032 if (WMA_HW_MODE_DBS_MODE_GET(param)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 WMA_LOGI("%s: HW (%d) is DBS capable", __func__, i);
3034 found = 1;
3035 break;
3036 }
3037 }
3038
3039 if (found)
3040 return true;
3041
3042 return false;
3043}
3044
3045/**
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003046 * wma_is_hw_sbs_capable() - Check if HW is SBS capable
3047 *
3048 * Checks if the HW is SBS capable
3049 *
3050 * Return: true if the HW is SBS capable
3051 */
3052bool wma_is_hw_sbs_capable(void)
3053{
3054 tp_wma_handle wma;
3055 uint32_t param, i, found = 0;
3056
3057 wma = cds_get_context(QDF_MODULE_ID_WMA);
3058 if (!wma) {
3059 WMA_LOGE("%s: Invalid WMA handle", __func__);
3060 return false;
3061 }
3062
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003063 /* The agreement with FW is that: To know if the target is SBS
3064 * capable, SBS needs to be supported both in the HW mode list
3065 * and DBS needs to be supported in the service ready event
3066 */
3067 if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
Archana Ramachandran92b4bf12017-03-17 15:41:53 -07003068 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT))) {
3069 WMA_LOGE("%s: SBS cannot be supported since DBS is disabled",
3070 __func__);
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003071 return false;
Archana Ramachandran92b4bf12017-03-17 15:41:53 -07003072 }
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003073
3074 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
3075 param = wma->hw_mode.hw_mode_list[i];
3076 WMA_LOGI("%s: HW param: %x", __func__, param);
3077 if (WMA_HW_MODE_SBS_MODE_GET(param)) {
3078 WMA_LOGI("%s: HW (%d) is SBS capable", __func__, i);
3079 found = 1;
3080 break;
3081 }
3082 }
3083
3084 if (found)
3085 return true;
3086
Archana Ramachandran92b4bf12017-03-17 15:41:53 -07003087 return false;
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003088}
3089
Nitesh Shaha3dfea32017-02-09 19:18:57 +05303090/*
3091 * wma_get_cds_hw_mode_change_from_hw_mode_index - Returns value in terms of
3092 * cds_hw_mode_change enums derived from hw_mode_index.
3093 *
3094 * Returns cds_hw_mode_change value derived from hw_mode_index.
3095 *
3096 * Return: value in terms of cds_hw_mode_change enums.
3097 */
3098enum cds_hw_mode_change
3099wma_get_cds_hw_mode_change_from_hw_mode_index(uint32_t hw_mode_index)
3100{
3101 tp_wma_handle wma;
3102 uint32_t param = 0;
3103 enum cds_hw_mode_change value = CDS_HW_MODE_NOT_IN_PROGRESS;
3104
3105 wma = cds_get_context(QDF_MODULE_ID_WMA);
3106 if (!wma) {
3107 WMA_LOGE("%s: Invalid WMA handle", __func__);
3108 goto ret_value;
3109 }
3110
3111 WMA_LOGI("%s: HW param: %x", __func__, param);
3112
3113 param = wma->hw_mode.hw_mode_list[hw_mode_index];
3114 if (WMA_HW_MODE_DBS_MODE_GET(param)) {
3115 WMA_LOGI("%s: DBS is requested with HW (%d)", __func__,
3116 hw_mode_index);
3117 value = CDS_DBS_IN_PROGRESS;
3118 goto ret_value;
3119 }
3120
3121 if (WMA_HW_MODE_SBS_MODE_GET(param)) {
3122 WMA_LOGI("%s: SBS is requested with HW (%d)", __func__,
3123 hw_mode_index);
3124 value = CDS_SBS_IN_PROGRESS;
3125 goto ret_value;
3126 }
3127
3128 value = CDS_SMM_IN_PROGRESS;
3129 WMA_LOGI("%s: SMM is requested with HW (%d)", __func__,
3130 hw_mode_index);
3131ret_value:
3132 return value;
3133}
3134
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003135/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
3137 * @vdev_id: VDEV whose MAC ID is required
3138 *
3139 * Get MAC id corresponding to a vdev id from the WMA structure
3140 *
3141 * Return: Negative value on failure and MAC id on success
3142 */
3143int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
3144{
3145 tp_wma_handle wma;
3146
Anurag Chouhan6d760662016-02-20 16:05:43 +05303147 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 if (!wma) {
3149 WMA_LOGE("%s: Invalid WMA handle", __func__);
3150 return -EINVAL;
3151 }
3152
3153 if (wma->interfaces)
3154 return wma->interfaces[vdev_id].mac_id;
3155
3156 return -EINVAL;
3157}
3158
3159/**
3160 * wma_get_old_and_new_hw_index() - Get the old and new HW index
3161 * @old_hw_mode_index: Value at this pointer contains the old HW mode index
3162 * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX
3163 * @new_hw_mode_index: Value at this pointer contains the new HW mode index
3164 * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX
3165 *
3166 * Get the old and new HW index configured in the driver
3167 *
3168 * Return: Failure in case the HW mode indices cannot be fetched and Success
3169 * otherwise. When no HW mode transition has happened the values of
3170 * old_hw_mode_index and new_hw_mode_index will be the same.
3171 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303172QDF_STATUS wma_get_old_and_new_hw_index(uint32_t *old_hw_mode_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 uint32_t *new_hw_mode_index)
3174{
3175 tp_wma_handle wma;
3176
Anurag Chouhan6d760662016-02-20 16:05:43 +05303177 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 if (!wma) {
3179 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303180 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003181 }
3182
3183 *old_hw_mode_index = wma->old_hw_mode_index;
3184 *new_hw_mode_index = wma->new_hw_mode_index;
3185
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303186 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187}
3188
3189/**
3190 * wma_update_intf_hw_mode_params() - Update WMA params
3191 * @vdev_id: VDEV id whose params needs to be updated
3192 * @mac_id: MAC id to be updated
3193 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
3194 *
3195 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
3196 *
3197 * Return: None
3198 */
3199void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
3200 uint32_t cfgd_hw_mode_index)
3201{
3202 tp_wma_handle wma;
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08003203 uint32_t param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204
Anurag Chouhan6d760662016-02-20 16:05:43 +05303205 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 if (!wma) {
3207 WMA_LOGE("%s: Invalid WMA handle", __func__);
3208 return;
3209 }
3210
3211 if (!wma->interfaces) {
3212 WMA_LOGE("%s: Interface is NULL", __func__);
3213 return;
3214 }
3215
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08003216 if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) {
3217 WMA_LOGE("%s: Invalid index", __func__);
3218 return;
3219 }
3220
3221 param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 wma->interfaces[vdev_id].mac_id = mac_id;
3223 if (mac_id == 0) {
3224 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303225 WMA_HW_MODE_MAC0_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003226 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303227 WMA_HW_MODE_MAC0_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 } else {
3229 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303230 WMA_HW_MODE_MAC1_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003231 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303232 WMA_HW_MODE_MAC1_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233 }
3234}
3235
3236/**
3237 * wma_get_dbs_hw_modes() - Get the DBS HW modes for userspace
3238 * @one_by_one_dbs: 1x1 DBS capability of HW
3239 * @two_by_two_dbs: 2x2 DBS capability of HW
3240 *
3241 * Provides the DBS HW mode capability such as whether
3242 * 1x1 DBS, 2x2 DBS is supported by the HW or not.
3243 *
3244 * Return: Failure in case of error and 0 on success
3245 * one_by_one_dbs/two_by_two_dbs will be false,
3246 * if they are not supported.
3247 * one_by_one_dbs/two_by_two_dbs will be true,
3248 * if they are supported.
3249 * false values of one_by_one_dbs/two_by_two_dbs,
3250 * indicate DBS is disabled
3251 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303252QDF_STATUS wma_get_dbs_hw_modes(bool *one_by_one_dbs, bool *two_by_two_dbs)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253{
3254 tp_wma_handle wma;
3255 uint32_t i;
3256 int8_t found_one_by_one = -EINVAL, found_two_by_two = -EINVAL;
3257 uint32_t conf1_tx_ss, conf1_rx_ss;
3258 uint32_t conf2_tx_ss, conf2_rx_ss;
3259
3260 *one_by_one_dbs = false;
3261 *two_by_two_dbs = false;
3262
3263 if (wma_is_hw_dbs_capable() == false) {
3264 WMA_LOGE("%s: HW is not DBS capable", __func__);
3265 /* Caller will understand that DBS is disabled */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267
3268 }
3269
Anurag Chouhan6d760662016-02-20 16:05:43 +05303270 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271 if (!wma) {
3272 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303273 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 }
3275
3276 /* To check 1x1 capability */
3277 wma_get_tx_rx_ss_from_config(HW_MODE_SS_1x1,
3278 &conf1_tx_ss, &conf1_rx_ss);
3279 /* To check 2x2 capability */
3280 wma_get_tx_rx_ss_from_config(HW_MODE_SS_2x2,
3281 &conf2_tx_ss, &conf2_rx_ss);
3282
3283 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
3284 uint32_t t_conf0_tx_ss, t_conf0_rx_ss;
3285 uint32_t t_conf1_tx_ss, t_conf1_rx_ss;
3286 uint32_t dbs_mode;
3287
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303288 t_conf0_tx_ss = WMA_HW_MODE_MAC0_TX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 wma->hw_mode.hw_mode_list[i]);
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303290 t_conf0_rx_ss = WMA_HW_MODE_MAC0_RX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291 wma->hw_mode.hw_mode_list[i]);
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303292 t_conf1_tx_ss = WMA_HW_MODE_MAC1_TX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003293 wma->hw_mode.hw_mode_list[i]);
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303294 t_conf1_rx_ss = WMA_HW_MODE_MAC1_RX_STREAMS_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 wma->hw_mode.hw_mode_list[i]);
Nitesh Shah5b7bae02016-09-28 18:58:33 +05303296 dbs_mode = WMA_HW_MODE_DBS_MODE_GET(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003297 wma->hw_mode.hw_mode_list[i]);
3298
3299 if (((((t_conf0_tx_ss == conf1_tx_ss) &&
3300 (t_conf0_rx_ss == conf1_rx_ss)) ||
3301 ((t_conf1_tx_ss == conf1_tx_ss) &&
3302 (t_conf1_rx_ss == conf1_rx_ss))) &&
3303 (dbs_mode == HW_MODE_DBS)) &&
3304 (found_one_by_one < 0)) {
3305 found_one_by_one = i;
3306 WMA_LOGI("%s: 1x1 hw_mode index %d found",
3307 __func__, i);
3308 /* Once an entry is found, need not check for 1x1
3309 * again
3310 */
3311 continue;
3312 }
3313
3314 if (((((t_conf0_tx_ss == conf2_tx_ss) &&
3315 (t_conf0_rx_ss == conf2_rx_ss)) ||
3316 ((t_conf1_tx_ss == conf2_tx_ss) &&
3317 (t_conf1_rx_ss == conf2_rx_ss))) &&
3318 (dbs_mode == HW_MODE_DBS)) &&
3319 (found_two_by_two < 0)) {
3320 found_two_by_two = i;
3321 WMA_LOGI("%s: 2x2 hw_mode index %d found",
3322 __func__, i);
3323 /* Once an entry is found, need not check for 2x2
3324 * again
3325 */
3326 continue;
3327 }
3328 }
3329
3330 if (found_one_by_one >= 0)
3331 *one_by_one_dbs = true;
3332 if (found_two_by_two >= 0)
3333 *two_by_two_dbs = true;
3334
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303335 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336}
3337
3338/**
3339 * wma_get_current_hw_mode() - Get current HW mode params
3340 * @hw_mode: HW mode parameters
3341 *
3342 * Provides the current HW mode parameters if the HW mode is initialized
3343 * in the driver
3344 *
3345 * Return: Success if the current HW mode params are successfully populated
3346 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303347QDF_STATUS wma_get_current_hw_mode(struct sir_hw_mode_params *hw_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303349 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003350 uint32_t old_hw_index = 0, new_hw_index = 0;
3351
3352 WMA_LOGI("%s: Get the current hw mode", __func__);
3353
3354 status = wma_get_old_and_new_hw_index(&old_hw_index,
3355 &new_hw_index);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303356 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357 WMA_LOGE("%s: Failed to get HW mode index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303358 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359 }
3360
3361 if (new_hw_index == WMA_DEFAULT_HW_MODE_INDEX) {
3362 WMA_LOGE("%s: HW mode is not yet initialized", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303363 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 }
3365
3366 status = wma_get_hw_mode_from_idx(new_hw_index, hw_mode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303367 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003368 WMA_LOGE("%s: Failed to get HW mode index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303369 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003370 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372}
3373
3374/**
Krunal Soni4274f362016-12-14 19:55:25 -08003375 * wma_is_current_hwmode_dbs() - Check if current hw mode is DBS
3376 *
3377 * Checks if current hardware mode of the system is DBS or no
3378 *
3379 * Return: true or false
3380 */
3381bool wma_is_current_hwmode_dbs(void)
3382{
3383 struct sir_hw_mode_params hw_mode;
3384
3385 if (!wma_is_hw_dbs_capable())
3386 return false;
3387 if (QDF_STATUS_SUCCESS != wma_get_current_hw_mode(&hw_mode))
3388 return false;
3389 if (hw_mode.dbs_cap)
3390 return true;
3391 return false;
3392}
3393
3394/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 * wma_is_dbs_enable() - Check if master DBS control is enabled
3396 *
3397 * Checks if the master DBS control is enabled. This will be used
3398 * to override any other DBS capability
3399 *
3400 * Return: True if master DBS control is enabled
3401 */
3402bool wma_is_dbs_enable(void)
3403{
3404 tp_wma_handle wma;
3405
3406 if (wma_is_dual_mac_disabled_in_ini())
3407 return false;
3408
Anurag Chouhan6d760662016-02-20 16:05:43 +05303409 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003410 if (!wma) {
3411 WMA_LOGE("%s: Invalid WMA handle", __func__);
3412 return false;
3413 }
3414
3415 WMA_LOGD("%s: DBS=%d", __func__,
3416 WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config));
3417
3418 if (WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config))
3419 return true;
3420
3421 return false;
3422}
3423
3424/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 * wma_get_updated_scan_config() - Get the updated scan configuration
3426 * @scan_config: Pointer containing the updated scan config
3427 * @dbs_scan: 0 or 1 indicating if DBS scan needs to be enabled/disabled
3428 * @dbs_plus_agile_scan: 0 or 1 indicating if DBS plus agile scan needs to be
3429 * enabled/disabled
3430 * @single_mac_scan_with_dfs: 0 or 1 indicating if single MAC scan with DFS
3431 * needs to be enabled/disabled
3432 *
3433 * Takes the current scan configuration and set the necessary scan config
3434 * bits to either 0/1 and provides the updated value to the caller who
3435 * can use this to pass it on to the FW
3436 *
3437 * Return: 0 on success
3438 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303439QDF_STATUS wma_get_updated_scan_config(uint32_t *scan_config,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440 bool dbs_scan,
3441 bool dbs_plus_agile_scan,
3442 bool single_mac_scan_with_dfs)
3443{
3444 tp_wma_handle wma;
3445
Anurag Chouhan6d760662016-02-20 16:05:43 +05303446 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447 if (!wma) {
3448 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303449 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003450 }
3451 *scan_config = wma->dual_mac_cfg.cur_scan_config;
3452
3453 WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_SET(*scan_config, dbs_scan);
3454 WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_SET(*scan_config,
3455 dbs_plus_agile_scan);
3456 WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_SET(*scan_config,
3457 single_mac_scan_with_dfs);
3458
3459 WMA_LOGD("%s: *scan_config:%x ", __func__, *scan_config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303460 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003461}
3462
3463/**
3464 * wma_get_updated_fw_mode_config() - Get the updated fw mode configuration
3465 * @fw_mode_config: Pointer containing the updated fw mode config
3466 * @dbs: 0 or 1 indicating if DBS needs to be enabled/disabled
3467 * @agile_dfs: 0 or 1 indicating if agile DFS needs to be enabled/disabled
3468 *
3469 * Takes the current fw mode configuration and set the necessary fw mode config
3470 * bits to either 0/1 and provides the updated value to the caller who
3471 * can use this to pass it on to the FW
3472 *
3473 * Return: 0 on success
3474 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303475QDF_STATUS wma_get_updated_fw_mode_config(uint32_t *fw_mode_config,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 bool dbs,
3477 bool agile_dfs)
3478{
3479 tp_wma_handle wma;
3480
Anurag Chouhan6d760662016-02-20 16:05:43 +05303481 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482 if (!wma) {
3483 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303484 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485 }
3486 *fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3487
3488 WMI_DBS_FW_MODE_CFG_DBS_SET(*fw_mode_config, dbs);
3489 WMI_DBS_FW_MODE_CFG_AGILE_DFS_SET(*fw_mode_config, agile_dfs);
3490
3491 WMA_LOGD("%s: *fw_mode_config:%x ", __func__, *fw_mode_config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303492 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493}
3494
3495/**
3496 * wma_get_dbs_config() - Get DBS bit
3497 *
3498 * Gets the DBS bit of fw_mode_config_bits
3499 *
3500 * Return: 0 or 1 to indicate the DBS bit
3501 */
3502bool wma_get_dbs_config(void)
3503{
3504 tp_wma_handle wma;
3505 uint32_t fw_mode_config;
3506
3507 if (wma_is_dual_mac_disabled_in_ini())
3508 return false;
3509
Anurag Chouhan6d760662016-02-20 16:05:43 +05303510 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511 if (!wma) {
3512 WMA_LOGE("%s: Invalid WMA handle", __func__);
3513 /* We take that it is disabled and proceed */
3514 return false;
3515 }
3516 fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3517
3518 return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config);
3519}
3520
3521/**
3522 * wma_get_agile_dfs_config() - Get Agile DFS bit
3523 *
3524 * Gets the Agile DFS bit of fw_mode_config_bits
3525 *
3526 * Return: 0 or 1 to indicate the Agile DFS bit
3527 */
3528bool wma_get_agile_dfs_config(void)
3529{
3530 tp_wma_handle wma;
3531 uint32_t fw_mode_config;
3532
3533 if (wma_is_dual_mac_disabled_in_ini())
3534 return false;
3535
Anurag Chouhan6d760662016-02-20 16:05:43 +05303536 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 if (!wma) {
3538 WMA_LOGE("%s: Invalid WMA handle", __func__);
3539 /* We take that it is disabled and proceed */
3540 return false;
3541 }
3542 fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3543
3544 return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config);
3545}
3546
3547/**
3548 * wma_get_dbs_scan_config() - Get DBS scan bit
3549 *
3550 * Gets the DBS scan bit of concurrent_scan_config_bits
3551 *
3552 * Return: 0 or 1 to indicate the DBS scan bit
3553 */
3554bool wma_get_dbs_scan_config(void)
3555{
3556 tp_wma_handle wma;
3557 uint32_t scan_config;
3558
3559 if (wma_is_dual_mac_disabled_in_ini())
3560 return false;
3561
Anurag Chouhan6d760662016-02-20 16:05:43 +05303562 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003563 if (!wma) {
3564 WMA_LOGE("%s: Invalid WMA handle", __func__);
3565 /* We take that it is disabled and proceed */
3566 return false;
3567 }
3568 scan_config = wma->dual_mac_cfg.cur_scan_config;
3569
3570 return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config);
3571}
3572
3573/**
3574 * wma_get_dbs_plus_agile_scan_config() - Get DBS plus agile scan bit
3575 *
3576 * Gets the DBS plus agile scan bit of concurrent_scan_config_bits
3577 *
3578 * Return: 0 or 1 to indicate the DBS plus agile scan bit
3579 */
3580bool wma_get_dbs_plus_agile_scan_config(void)
3581{
3582 tp_wma_handle wma;
3583 uint32_t scan_config;
3584
3585 if (wma_is_dual_mac_disabled_in_ini())
3586 return false;
3587
Anurag Chouhan6d760662016-02-20 16:05:43 +05303588 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 if (!wma) {
3590 WMA_LOGE("%s: Invalid WMA handle", __func__);
3591 /* We take that it is disabled and proceed */
3592 return false;
3593 }
3594 scan_config = wma->dual_mac_cfg.cur_scan_config;
3595
3596 return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config);
3597}
3598
3599/**
3600 * wma_get_single_mac_scan_with_dfs_config() - Get Single MAC scan with DFS bit
3601 *
3602 * Gets the Single MAC scan with DFS bit of concurrent_scan_config_bits
3603 *
3604 * Return: 0 or 1 to indicate the Single MAC scan with DFS bit
3605 */
3606bool wma_get_single_mac_scan_with_dfs_config(void)
3607{
3608 tp_wma_handle wma;
3609 uint32_t scan_config;
3610
3611 if (wma_is_dual_mac_disabled_in_ini())
3612 return false;
3613
Anurag Chouhan6d760662016-02-20 16:05:43 +05303614 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003615 if (!wma) {
3616 WMA_LOGE("%s: Invalid WMA handle", __func__);
3617 /* We take that it is disabled and proceed */
3618 return false;
3619 }
3620 scan_config = wma->dual_mac_cfg.cur_scan_config;
3621
3622 return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config);
3623}
3624
3625/**
3626 * wma_is_dual_mac_disabled_in_ini() - Check if dual mac is disabled in INI
3627 *
3628 * Checks if the dual mac feature is disabled in INI
3629 *
3630 * Return: true if the dual mac feature is disabled from INI
3631 */
3632bool wma_is_dual_mac_disabled_in_ini(void)
3633{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303634 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635
3636 if (!mac) {
3637 WMA_LOGE("%s: Invalid mac pointer", __func__);
3638 return true;
3639 }
3640
3641 if (mac->dual_mac_feature_disable)
3642 return true;
3643
3644 return false;
3645}
3646
3647/**
3648 * wma_get_prev_dbs_config() - Get prev DBS bit
3649 *
3650 * Gets the previous DBS bit of fw_mode_config_bits
3651 *
3652 * Return: 0 or 1 to indicate the DBS bit
3653 */
3654bool wma_get_prev_dbs_config(void)
3655{
3656 tp_wma_handle wma;
3657 uint32_t fw_mode_config;
3658
3659 if (wma_is_dual_mac_disabled_in_ini())
3660 return false;
3661
Anurag Chouhan6d760662016-02-20 16:05:43 +05303662 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003663 if (!wma) {
3664 WMA_LOGE("%s: Invalid WMA handle", __func__);
3665 /* We take that it is disabled and proceed */
3666 return false;
3667 }
3668 fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config;
3669
3670 return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config);
3671}
3672
3673/**
3674 * wma_get_prev_agile_dfs_config() - Get prev Agile DFS bit
3675 *
3676 * Gets the previous Agile DFS bit of fw_mode_config_bits
3677 *
3678 * Return: 0 or 1 to indicate the Agile DFS bit
3679 */
3680bool wma_get_prev_agile_dfs_config(void)
3681{
3682 tp_wma_handle wma;
3683 uint32_t fw_mode_config;
3684
3685 if (wma_is_dual_mac_disabled_in_ini())
3686 return false;
3687
Anurag Chouhan6d760662016-02-20 16:05:43 +05303688 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 if (!wma) {
3690 WMA_LOGE("%s: Invalid WMA handle", __func__);
3691 /* We take that it is disabled and proceed */
3692 return false;
3693 }
3694 fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config;
3695
3696 return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config);
3697}
3698
3699/**
3700 * wma_get_prev_dbs_scan_config() - Get prev DBS scan bit
3701 *
3702 * Gets the previous DBS scan bit of concurrent_scan_config_bits
3703 *
3704 * Return: 0 or 1 to indicate the DBS scan bit
3705 */
3706bool wma_get_prev_dbs_scan_config(void)
3707{
3708 tp_wma_handle wma;
3709 uint32_t scan_config;
3710
3711 if (wma_is_dual_mac_disabled_in_ini())
3712 return false;
3713
Anurag Chouhan6d760662016-02-20 16:05:43 +05303714 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 if (!wma) {
3716 WMA_LOGE("%s: Invalid WMA handle", __func__);
3717 /* We take that it is disabled and proceed */
3718 return false;
3719 }
3720 scan_config = wma->dual_mac_cfg.prev_scan_config;
3721
3722 return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config);
3723}
3724
3725/**
3726 * wma_get_prev_dbs_plus_agile_scan_config() - Get prev DBS plus agile scan bit
3727 *
3728 * Gets the previous DBS plus agile scan bit of concurrent_scan_config_bits
3729 *
3730 * Return: 0 or 1 to indicate the DBS plus agile scan bit
3731 */
3732bool wma_get_prev_dbs_plus_agile_scan_config(void)
3733{
3734 tp_wma_handle wma;
3735 uint32_t scan_config;
3736
3737 if (wma_is_dual_mac_disabled_in_ini())
3738 return false;
3739
Anurag Chouhan6d760662016-02-20 16:05:43 +05303740 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741 if (!wma) {
3742 WMA_LOGE("%s: Invalid WMA handle", __func__);
3743 /* We take that it is disabled and proceed */
3744 return false;
3745 }
3746 scan_config = wma->dual_mac_cfg.prev_scan_config;
3747
3748 return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config);
3749}
3750
3751/**
3752 * wma_get_prev_single_mac_scan_with_dfs_config() - Get prev Single MAC scan
3753 * with DFS bit
3754 *
3755 * Gets the previous Single MAC scan with DFS bit of concurrent_scan_config_bits
3756 *
3757 * Return: 0 or 1 to indicate the Single MAC scan with DFS bit
3758 */
3759bool wma_get_prev_single_mac_scan_with_dfs_config(void)
3760{
3761 tp_wma_handle wma;
3762 uint32_t scan_config;
3763
3764 if (wma_is_dual_mac_disabled_in_ini())
3765 return false;
3766
Anurag Chouhan6d760662016-02-20 16:05:43 +05303767 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 if (!wma) {
3769 WMA_LOGE("%s: Invalid WMA handle", __func__);
3770 /* We take that it is disabled and proceed */
3771 return false;
3772 }
3773 scan_config = wma->dual_mac_cfg.prev_scan_config;
3774
3775 return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config);
3776}
3777
3778/**
3779 * wma_is_scan_simultaneous_capable() - Check if scan parallelization is
3780 * supported or not
3781 *
3782 * currently scan parallelization feature support is dependent on DBS but
3783 * it can be independent in future.
3784 *
3785 * Return: True if master DBS control is enabled
3786 */
3787bool wma_is_scan_simultaneous_capable(void)
3788{
3789 if (wma_is_hw_dbs_capable())
3790 return true;
3791
3792 return false;
3793}
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003794
3795/**
3796 * wma_get_vht_ch_width - return vht channel width
3797 *
3798 * Return: return vht channel width
3799 */
3800uint32_t wma_get_vht_ch_width(void)
3801{
3802 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303803 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003804
3805 if (NULL == wm_hdl)
3806 return fw_ch_wd;
3807
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07003808 if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003809 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07003810 else if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
3811 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003812
3813 return fw_ch_wd;
3814}
Govind Singhd76a5b02016-03-08 15:12:14 +05303815
3816/**
Krunal Soniaa664da2016-06-15 23:46:40 -07003817 * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
3818 * @mask: given bitmask
3819 *
3820 * This helper function should return number of setbits from bitmask
3821 *
3822 * Return: number of setbits from bitmask
3823 */
3824uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
3825{
3826 uint32_t num_of_setbits = 0;
3827
3828 while (mask) {
3829 mask &= (mask - 1);
3830 num_of_setbits++;
3831 }
3832 return num_of_setbits;
3833}
3834
3835/**
Govind Singhd76a5b02016-03-08 15:12:14 +05303836 * wma_config_debug_module_cmd - set debug log config
3837 * @wmi_handle: wmi layer handle
3838 * @param: debug log parameter
3839 * @val: debug log value
3840 * @module_id_bitmap: debug module id bitmap
3841 * @bitmap_len: debug module bitmap length
3842 *
3843 * Return: QDF_STATUS_SUCCESS for success or error code
3844 */
3845QDF_STATUS
3846wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
3847 A_UINT32 val, A_UINT32 *module_id_bitmap,
3848 A_UINT32 bitmap_len)
3849{
3850 struct dbglog_params dbg_param;
3851 dbg_param.param = param;
3852 dbg_param.val = val;
3853 dbg_param.module_id_bitmap = module_id_bitmap;
3854 dbg_param.bitmap_len = bitmap_len;
3855
3856 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
3857}
Peng Xu8fdaa492016-06-22 10:20:47 -07003858
3859/**
3860 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
3861 *
3862 * This function checks if driver is capable of p2p listen offload
3863 * true: capable of p2p offload
3864 * false: not capable
3865 *
3866 * Return: true - capable, false - not capable
3867 */
3868bool wma_is_p2p_lo_capable(void)
3869{
3870 tp_wma_handle wma;
3871
3872 wma = cds_get_context(QDF_MODULE_ID_WMA);
3873 if (!wma) {
3874 WMA_LOGE("%s: Invalid WMA handle", __func__);
3875 return false;
3876 }
3877
3878 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3879 WMI_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT))
3880 return true;
3881
3882 return false;
3883}
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003884
3885/**
3886 * wma_is_hw_dbs_2x2_capable() - if hardware is capable of dbs 2x2
3887 *
3888 * This function checks if hw_modes supported are always capable of
3889 * DBS 2x2.
3890 * true: DBS 2x2 can always be supported
3891 * false: hw_modes support DBS 1x1 as well
3892 *
3893 * Return: true - DBS2x2, false - DBS1x1
3894 */
3895bool wma_is_hw_dbs_2x2_capable(void)
3896{
3897 tp_wma_handle wma;
Tushnim Bhattacharyyadb55e2c2017-01-13 16:23:34 -08003898 int i, param;
3899 uint32_t dbs, tx_chain0, rx_chain0, tx_chain1, rx_chain1;
3900 uint32_t final_min_rf_chains = 2;
3901 uint32_t min_rf_chains, min_mac0_rf_chains, min_mac1_rf_chains;
3902 bool is_dbs_found = false;
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003903
3904 wma = cds_get_context(QDF_MODULE_ID_WMA);
3905 if (!wma) {
3906 WMA_LOGE("%s: Invalid WMA handle", __func__);
3907 return false;
3908 }
3909
Tushnim Bhattacharyyadb55e2c2017-01-13 16:23:34 -08003910 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
3911 param = wma->hw_mode.hw_mode_list[i];
3912 tx_chain0 = WMA_HW_MODE_MAC0_TX_STREAMS_GET(param);
3913 rx_chain0 = WMA_HW_MODE_MAC0_RX_STREAMS_GET(param);
3914 dbs = WMA_HW_MODE_DBS_MODE_GET(param);
3915 tx_chain1 = WMA_HW_MODE_MAC1_TX_STREAMS_GET(param);
3916 rx_chain1 = WMA_HW_MODE_MAC1_RX_STREAMS_GET(param);
3917
3918 if (dbs) {
3919 min_mac0_rf_chains = QDF_MIN(tx_chain0, rx_chain0);
3920 min_mac1_rf_chains = QDF_MIN(tx_chain1, rx_chain1);
3921 min_rf_chains = QDF_MIN(min_mac0_rf_chains,
3922 min_mac1_rf_chains);
3923 is_dbs_found = true;
3924 } else {
3925 continue;
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003926 }
Tushnim Bhattacharyyadb55e2c2017-01-13 16:23:34 -08003927 final_min_rf_chains = QDF_MIN(final_min_rf_chains,
3928 min_rf_chains);
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003929 }
Tushnim Bhattacharyyadb55e2c2017-01-13 16:23:34 -08003930 if (false == is_dbs_found)
3931 final_min_rf_chains = 0;
3932
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08003933 return (final_min_rf_chains == 2) ? true : false;
3934}
Mukul Sharmaf9047232017-03-02 16:58:56 +05303935
3936bool wma_is_vdev_up(uint8_t vdev_id)
3937{
3938 struct wlan_objmgr_vdev *vdev;
3939 tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
3940 enum wlan_vdev_state state = WLAN_VDEV_S_INIT;
3941
3942 if (!wma) {
3943 WMA_LOGE("%s: WMA context is invald!", __func__);
3944 return false;
3945 }
3946
3947 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
3948 WLAN_LEGACY_WMA_ID);
3949 if (vdev) {
3950 wlan_vdev_obj_lock(vdev);
3951 state = wlan_vdev_mlme_get_state(vdev);
3952 wlan_vdev_obj_unlock(vdev);
3953 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
3954 }
3955
3956 return (state == WLAN_VDEV_S_RUN) ? true : false;
3957}
3958
Dustin Brownbf6d16b2017-03-03 11:41:05 -08003959void wma_acquire_wmi_resp_wakelock(t_wma_handle *wma, uint32_t msec)
3960{
3961 cds_host_diag_log_work(&wma->wmi_cmd_rsp_wake_lock,
3962 msec,
3963 WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
3964 qdf_wake_lock_timeout_acquire(&wma->wmi_cmd_rsp_wake_lock, msec);
3965 qdf_runtime_pm_prevent_suspend(wma->wmi_cmd_rsp_runtime_lock);
3966}
3967
3968void wma_release_wmi_resp_wakelock(t_wma_handle *wma)
3969{
3970 qdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock,
3971 WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
3972 qdf_runtime_pm_allow_suspend(wma->wmi_cmd_rsp_runtime_lock);
3973}
3974
Dustin Brownd5f12942017-03-10 11:06:25 -08003975QDF_STATUS
3976wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
3977{
3978 QDF_STATUS status;
3979
3980 wma_acquire_wmi_resp_wakelock(wma, WMA_VDEV_START_REQUEST_TIMEOUT);
3981 status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
3982 if (QDF_IS_STATUS_ERROR(status))
3983 wma_release_wmi_resp_wakelock(wma);
3984
3985 return status;
3986}
3987
Dustin Brownbf6d16b2017-03-03 11:41:05 -08003988QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
3989{
3990 QDF_STATUS status;
3991
3992 wma_acquire_wmi_resp_wakelock(wma, WMA_VDEV_STOP_REQUEST_TIMEOUT);
3993 status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id);
3994 if (QDF_IS_STATUS_ERROR(status))
3995 wma_release_wmi_resp_wakelock(wma);
3996
3997 return status;
3998}
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003999
4000bool wma_is_service_enabled(WMI_SERVICE service_type)
4001{
4002 tp_wma_handle wma;
4003 wma = cds_get_context(QDF_MODULE_ID_WMA);
4004 if (!wma) {
4005 WMA_LOGE("%s: Invalid WMA handle", __func__);
4006 return false;
4007 }
4008
4009 return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, service_type);
4010}