blob: aa18f515acb545d72dd4840b219f88e5218b7337 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302 * Copyright (c) 2013-2016 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#include "ol_txrx_peer_find.h"
50
51#include "wma_types.h"
52#include "lim_api.h"
53#include "lim_session_utils.h"
54
55#include "cds_utils.h"
56
57#if !defined(REMOVE_PKT_LOG)
58#include "pktlog_ac.h"
59#endif /* REMOVE_PKT_LOG */
60
61#include "dbglog_host.h"
62#include "csr_api.h"
63#include "ol_fw.h"
64
65#include "dfs.h"
66#include "wma_internal.h"
Chandrasekaran, Manishekar0d814c72015-11-05 10:42:48 +053067#include "cds_concurrency.h"
Govind Singhd76a5b02016-03-08 15:12:14 +053068#include "wmi_unified_param.h"
Naveen Rawatc0c91cd2015-11-05 14:27:37 -080069#include "linux/ieee80211.h"
70
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071/* MCS Based rate table */
72/* HT MCS parameters with Nss = 1 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080073static struct index_data_rate_type mcs_nss1[] = {
74 /* MCS L20 S20 L40 S40 */
75 {0, {65, 72}, {135, 150 } },
76 {1, {130, 144}, {270, 300 } },
77 {2, {195, 217}, {405, 450 } },
78 {3, {260, 289}, {540, 600 } },
79 {4, {390, 433}, {815, 900 } },
80 {5, {520, 578}, {1080, 1200} },
81 {6, {585, 650}, {1215, 1350} },
82 {7, {650, 722}, {1350, 1500} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083};
84
85/* HT MCS parameters with Nss = 2 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080086static struct index_data_rate_type mcs_nss2[] = {
87 /* MCS L20 S20 L40 S40 */
88 {0, {130, 144}, {270, 300 } },
89 {1, {260, 289}, {540, 600 } },
90 {2, {390, 433}, {810, 900 } },
91 {3, {520, 578}, {1080, 1200} },
92 {4, {780, 867}, {1620, 1800} },
93 {5, {1040, 1156}, {2160, 2400} },
94 {6, {1170, 1300}, {2430, 2700} },
95 {7, {1300, 1440}, {2700, 3000} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096};
97
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098/* MCS Based VHT rate table */
99/* MCS parameters with Nss = 1*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800100static struct index_vht_data_rate_type vht_mcs_nss1[] = {
101 /* MCS L20 S20 L40 S40 L80 S80 */
102 {0, {65, 72 }, {135, 150}, {293, 325} },
103 {1, {130, 144}, {270, 300}, {585, 650} },
104 {2, {195, 217}, {405, 450}, {878, 975} },
105 {3, {260, 289}, {540, 600}, {1170, 1300} },
106 {4, {390, 433}, {810, 900}, {1755, 1950} },
107 {5, {520, 578}, {1080, 1200}, {2340, 2600} },
108 {6, {585, 650}, {1215, 1350}, {2633, 2925} },
109 {7, {650, 722}, {1350, 1500}, {2925, 3250} },
110 {8, {780, 867}, {1620, 1800}, {3510, 3900} },
111 {9, {865, 960}, {1800, 2000}, {3900, 4333} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112};
113
114/*MCS parameters with Nss = 2*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800115static struct index_vht_data_rate_type vht_mcs_nss2[] = {
116 /* MCS L20 S20 L40 S40 L80 S80 */
117 {0, {130, 144}, {270, 300}, { 585, 650} },
118 {1, {260, 289}, {540, 600}, {1170, 1300} },
119 {2, {390, 433}, {810, 900}, {1755, 1950} },
120 {3, {520, 578}, {1080, 1200}, {2340, 2600} },
121 {4, {780, 867}, {1620, 1800}, {3510, 3900} },
122 {5, {1040, 1156}, {2160, 2400}, {4680, 5200} },
123 {6, {1170, 1300}, {2430, 2700}, {5265, 5850} },
124 {7, {1300, 1444}, {2700, 3000}, {5850, 6500} },
125 {8, {1560, 1733}, {3240, 3600}, {7020, 7800} },
126 {9, {1730, 1920}, {3600, 4000}, {7800, 8667} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128
129#ifdef BIG_ENDIAN_HOST
130
131/* ############# function definitions ############ */
132
133/**
134 * wma_swap_bytes() - swap bytes
135 * @pv: buffer
136 * @n: swap bytes
137 *
138 * Return: none
139 */
140void wma_swap_bytes(void *pv, uint32_t n)
141{
142 int32_t no_words;
143 int32_t i;
144 uint32_t *word_ptr;
145
146 no_words = n / sizeof(uint32_t);
147 word_ptr = (uint32_t *) pv;
148 for (i = 0; i < no_words; i++) {
149 *(word_ptr + i) = __cpu_to_le32(*(word_ptr + i));
150 }
151}
152
153#define SWAPME(x, len) wma_swap_bytes(&x, len);
154#endif /* BIG_ENDIAN_HOST */
155
156/**
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800157 * wma_mcs_rate_match() - find the match mcs rate
158 * @match_rate: the rate to look up
159 * @is_sgi: return if the SGI rate is found
160 * @nss: the nss in use
161 * @nss1_rate: the nss1 rate
162 * @nss1_srate: the nss1 SGI rate
163 * @nss2_rate: the nss2 rate
164 * @nss2_srate: the nss2 SGI rate
165 *
166 * This is a helper function to find the match of the tx_rate
167 * in terms of the nss1/nss2 rate with non-SGI/SGI.
168 *
169 * Return: the found rate or 0 otherwise
170 */
171static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi,
172 uint8_t nss, uint16_t nss1_rate,
173 uint16_t nss1_srate,
174 uint16_t nss2_rate,
175 uint16_t nss2_srate)
176{
177 WMA_LOGD("%s match_rate: %d, %d %d %d %d",
178 __func__, match_rate, nss1_rate, nss1_srate, nss2_rate,
179 nss2_srate);
180
181 if (match_rate == nss1_rate) {
182 return nss1_rate;
183 } else if (match_rate == nss1_srate) {
184 *is_sgi = true;
185 return nss1_srate;
186 } else if (nss == 2 && match_rate == nss2_rate)
187 return nss2_rate;
188 else if (nss == 2 && match_rate == nss2_srate) {
189 *is_sgi = true;
190 return nss2_srate;
191 } else
192 return 0;
193}
194
195/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196 * wma_get_mcs_idx() - get mcs index
197 * @maxRate: max rate
198 * @rate_flags: rate flags
199 * @nss: number of nss
200 * @mcsRateFlag: mcs rate flag
201 *
202 * Return: return mcs index
203 */
204static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
205 uint8_t nss, uint8_t *mcsRateFlag)
206{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800207 uint8_t index = 0;
Arif Hussainb8fef842016-07-19 09:43:13 -0700208 uint16_t match_rate = 0;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800209 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800211 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
212 __func__, maxRate, rate_flags, nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213
214 *mcsRateFlag = rate_flags;
215 *mcsRateFlag &= ~eHAL_TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800216 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 if (rate_flags & eHAL_TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800218 /* check for vht80 nss1/2 rate set */
219 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
220 vht_mcs_nss1[index].ht80_rate[0],
221 vht_mcs_nss1[index].ht80_rate[1],
222 vht_mcs_nss2[index].ht80_rate[0],
223 vht_mcs_nss2[index].ht80_rate[1]);
224 if (match_rate)
225 goto rate_found;
226 }
227 if ((rate_flags & eHAL_TX_RATE_VHT40) |
228 (rate_flags & eHAL_TX_RATE_VHT80)) {
229 /* check for vht40 nss1/2 rate set */
230 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
231 vht_mcs_nss1[index].ht40_rate[0],
232 vht_mcs_nss1[index].ht40_rate[1],
233 vht_mcs_nss2[index].ht40_rate[0],
234 vht_mcs_nss2[index].ht40_rate[1]);
235 if (match_rate) {
236 *mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
237 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800238 }
239 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800240 if ((rate_flags & eHAL_TX_RATE_VHT20) |
241 (rate_flags & eHAL_TX_RATE_VHT40) |
242 (rate_flags & eHAL_TX_RATE_VHT80)) {
243 /* check for vht20 nss1/2 rate set */
244 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
245 vht_mcs_nss1[index].ht20_rate[0],
246 vht_mcs_nss1[index].ht20_rate[1],
247 vht_mcs_nss2[index].ht20_rate[0],
248 vht_mcs_nss2[index].ht20_rate[1]);
249 if (match_rate) {
250 *mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 |
251 eHAL_TX_RATE_VHT40);
252 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 }
254 }
255 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800256 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800257 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800258 /* check for ht40 nss1/2 rate set */
259 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
260 mcs_nss1[index].ht40_rate[0],
261 mcs_nss1[index].ht40_rate[1],
262 mcs_nss2[index].ht40_rate[0],
263 mcs_nss2[index].ht40_rate[1]);
264 if (match_rate) {
265 *mcsRateFlag = eHAL_TX_RATE_HT40;
266 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 }
268 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800269 if (rate_flags & eHAL_TX_RATE_HT20) {
270 /* 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/**
295 * host_map_smps_mode() - map fw smps mode to tSmpsModeValue
296 * @fw_smps_mode: fw smps mode
297 *
298 * Return: return tSmpsModeValue
299 */
300tSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
301{
302 tSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
303 switch (fw_smps_mode) {
304 case WMI_SMPS_FORCED_MODE_STATIC:
305 smps_mode = STATIC_SMPS_MODE;
306 break;
307 case WMI_SMPS_FORCED_MODE_DYNAMIC:
308 smps_mode = DYNAMIC_SMPS_MODE;
309 break;
310 default:
311 smps_mode = SMPS_MODE_DISABLED;
312 }
313
314 return smps_mode;
315}
316
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800317/**
318 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
319 * mode commmand param
320 * @smps_mode: SMPS mode according to the protocol
321 *
322 * Return: int > 0 for success else failure
323 */
324int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
325{
326 int param = -EINVAL;
327
328 switch (smps_mode) {
329 case STATIC_SMPS_MODE:
330 param = WMI_SMPS_FORCED_MODE_STATIC;
331 break;
332 case DYNAMIC_SMPS_MODE:
333 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
334 break;
335 case SMPS_MODE_DISABLED:
336 param = WMI_SMPS_FORCED_MODE_DISABLED;
337 break;
338 default:
339 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
340 smps_mode);
341 }
342 return param;
343}
344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345#ifdef WLAN_FEATURE_STATS_EXT
346/**
347 * wma_stats_ext_event_handler() - extended stats event handler
348 * @handle: wma handle
349 * @event_buf: event buffer received from fw
350 * @len: length of data
351 *
352 * Return: 0 for success or error code
353 */
354int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
355 uint32_t len)
356{
357 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
358 tSirStatsExtEvent *stats_ext_event;
359 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530360 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361 cds_msg_t cds_msg;
362 uint8_t *buf_ptr;
363 uint32_t alloc_len;
364
365 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
366
367 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
368 if (!param_buf) {
369 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
370 return -EINVAL;
371 }
372
373 stats_ext_info = param_buf->fixed_param;
374 buf_ptr = (uint8_t *) stats_ext_info;
375
376 alloc_len = sizeof(tSirStatsExtEvent);
377 alloc_len += stats_ext_info->data_len;
378
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530379 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 if (NULL == stats_ext_event) {
381 WMA_LOGE("%s: Memory allocation failure", __func__);
382 return -ENOMEM;
383 }
384
385 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
386
387 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
388 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530389 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 buf_ptr, stats_ext_event->event_data_len);
391
392 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
393 cds_msg.bodyptr = (void *)stats_ext_event;
394 cds_msg.bodyval = 0;
395
396 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530397 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530399 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400 return -EFAULT;
401 }
402
403 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
404 return 0;
405}
406#endif /* WLAN_FEATURE_STATS_EXT */
407
Nirav Shah93e789e2016-04-14 19:47:43 +0530408
Govind Singha471e5e2015-10-12 17:11:14 +0530409/**
410 * wma_profile_data_report_event_handler() - fw profiling handler
411 * @handle: wma handle
412 * @event_buf: event buffer received from fw
413 * @len: length of data
414 *
415 * Return: 0 for success or error code
416 */
417int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
418 uint32_t len)
419{
420 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
421 wmi_wlan_profile_ctx_t *profile_ctx;
422 wmi_wlan_profile_t *profile_data;
423 uint32_t i = 0;
424 uint32_t entries;
425 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530426 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530427 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
428
429 if (!param_buf) {
430 WMA_LOGE("%s: Invalid profile data event buf", __func__);
431 return -EINVAL;
432 }
433 profile_ctx = param_buf->profile_ctx;
434 buf_ptr = (uint8_t *)profile_ctx;
435 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
436 profile_data = (wmi_wlan_profile_t *) buf_ptr;
437 entries = profile_ctx->bin_count;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530438 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530439 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530440 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530441 "TOT: %d\n"
442 "tx_msdu_cnt: %d\n"
443 "tx_mpdu_cnt: %d\n"
444 "tx_ppdu_cnt: %d\n"
445 "rx_msdu_cnt: %d\n"
446 "rx_mpdu_cnt: %d\n"
447 "bin_count: %d\n",
448 profile_ctx->tot,
449 profile_ctx->tx_msdu_cnt,
450 profile_ctx->tx_mpdu_cnt,
451 profile_ctx->tx_ppdu_cnt,
452 profile_ctx->rx_msdu_cnt,
453 profile_ctx->rx_mpdu_cnt,
454 profile_ctx->bin_count);
455
Nirav Shah93e789e2016-04-14 19:47:43 +0530456 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
457 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
458
Govind Singha471e5e2015-10-12 17:11:14 +0530459 for (i = 0; i < entries; i++) {
460 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
461 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530462 snprintf(temp_str, sizeof(temp_str),
463 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530464 profile_data[i].id,
465 profile_data[i].cnt,
466 profile_data[i].tot,
467 profile_data[i].min,
468 profile_data[i].max,
469 profile_data[i].hist_intvl,
470 profile_data[i].hist[0],
471 profile_data[i].hist[1],
472 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530473 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
474 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530475 }
476
477 return 0;
478}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800479
480#ifdef WLAN_FEATURE_LINK_LAYER_STATS
481
482/**
483 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
484 * @handle: wma handle
485 * @cmd_param_info: data received with event from fw
486 * @len: length of data
487 *
488 * Return: 0 for success or error code
489 */
490static int wma_unified_link_peer_stats_event_handler(void *handle,
491 uint8_t *cmd_param_info,
492 uint32_t len)
493{
494 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
495 wmi_peer_stats_event_fixed_param *fixed_param;
496 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
497 wmi_rate_stats *rate_stats;
498 tSirLLStatsResults *link_stats_results;
499 uint8_t *results, *t_peer_stats, *t_rate_stats;
500 uint32_t count, num_rates = 0;
501 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
502 size_t peer_info_size, peer_stats_size, rate_stats_size;
503 size_t link_stats_results_size;
504
Anurag Chouhan6d760662016-02-20 16:05:43 +0530505 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506
507 if (!pMac) {
508 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
509 return -EINVAL;
510 }
511
512 if (!pMac->sme.pLinkLayerStatsIndCallback) {
513 WMA_LOGD("%s: HDD callback is null", __func__);
514 return -EINVAL;
515 }
516
517 WMA_LOGD("%s: Posting Peer Stats event to HDD", __func__);
518 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
519 if (!param_tlvs) {
520 WMA_LOGA("%s: Invalid stats event", __func__);
521 return -EINVAL;
522 }
523 /*
524 * cmd_param_info contains
525 * wmi_peer_stats_event_fixed_param fixed_param;
526 * num_peers * size of(struct wmi_peer_link_stats)
527 * num_rates * size of(struct wmi_rate_stats)
528 * num_rates is the sum of the rates of all the peers.
529 */
530 fixed_param = param_tlvs->fixed_param;
531 peer_stats = param_tlvs->peer_stats;
532 rate_stats = param_tlvs->peer_rate_stats;
533
534 if (!fixed_param || !peer_stats ||
535 (peer_stats->num_rates && !rate_stats)) {
536 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
537 return -EINVAL;
538 }
539
540 /*
541 * num_rates - sum of the rates of all the peers
542 */
543 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
544 for (count = 0; count < fixed_param->num_peers; count++) {
545 num_rates += temp_peer_stats->num_rates;
546 temp_peer_stats++;
547 }
548
549 peer_stats_size = sizeof(tSirWifiPeerStat);
550 peer_info_size = sizeof(tSirWifiPeerInfo);
551 rate_stats_size = sizeof(tSirWifiRateStat);
552 link_stats_results_size =
553 sizeof(*link_stats_results) + peer_stats_size +
554 (fixed_param->num_peers * peer_info_size) +
555 (num_rates * rate_stats_size);
556
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530557 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 if (NULL == link_stats_results) {
559 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
560 __func__, link_stats_results_size);
561 return -ENOMEM;
562 }
563
564 WMA_LOGD("Peer stats from FW event buf");
565 WMA_LOGD("Fixed Param:");
566 WMA_LOGD("request_id %u num_peers %u peer_event_number %u more_data %u",
567 fixed_param->request_id, fixed_param->num_peers,
568 fixed_param->peer_event_number, fixed_param->more_data);
569
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530570 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571
572 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
573 link_stats_results->rspId = fixed_param->request_id;
574 link_stats_results->ifaceId = 0;
575 link_stats_results->num_peers = fixed_param->num_peers;
576 link_stats_results->peer_event_number = fixed_param->peer_event_number;
577 link_stats_results->moreResultToFollow = fixed_param->more_data;
578
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530579 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 &fixed_param->num_peers, peer_stats_size);
581
582 results = (uint8_t *) link_stats_results->results;
583 t_peer_stats = (uint8_t *) peer_stats;
584 t_rate_stats = (uint8_t *) rate_stats;
585 next_res_offset = peer_stats_size;
586 next_peer_offset = WMI_TLV_HDR_SIZE;
587 next_rate_offset = WMI_TLV_HDR_SIZE;
588 for (count = 0; count < fixed_param->num_peers; count++) {
589 WMA_LOGD("Peer Info:");
590 WMA_LOGD("peer_type %u capabilities %u num_rates %u",
591 peer_stats->peer_type, peer_stats->capabilities,
592 peer_stats->num_rates);
593
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530594 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 t_peer_stats + next_peer_offset, peer_info_size);
596 next_res_offset += peer_info_size;
597
598 /* Copy rate stats associated with this peer */
599 for (count = 0; count < peer_stats->num_rates; count++) {
600 WMA_LOGD("Rate Stats Info:");
601 WMA_LOGD("rate %u bitrate %u tx_mpdu %u rx_mpdu %u "
602 "mpdu_lost %u retries %u retries_short %u "
603 "retries_long %u", rate_stats->rate,
604 rate_stats->bitrate, rate_stats->tx_mpdu,
605 rate_stats->rx_mpdu, rate_stats->mpdu_lost,
606 rate_stats->retries, rate_stats->retries_short,
607 rate_stats->retries_long);
608 rate_stats++;
609
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530610 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800611 t_rate_stats + next_rate_offset,
612 rate_stats_size);
613 next_res_offset += rate_stats_size;
614 next_rate_offset += sizeof(*rate_stats);
615 }
616 next_peer_offset += sizeof(*peer_stats);
617 peer_stats++;
618 }
619
620 /* call hdd callback with Link Layer Statistics
621 * vdev_id/ifacId in link_stats_results will be
622 * used to retrieve the correct HDD context
623 */
624 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
625 WMA_LINK_LAYER_STATS_RESULTS_RSP,
626 link_stats_results);
627 WMA_LOGD("%s: Peer Stats event posted to HDD", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530628 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629
630 return 0;
631}
632
633
634/**
635 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
636 * @handle: wma handle
637 * @cmd_param_info: data received with event from fw
638 * @len: length of data
639 *
640 * Return: 0 for success or error code
641 */
642static int wma_unified_link_radio_stats_event_handler(void *handle,
643 uint8_t *cmd_param_info,
644 uint32_t len)
645{
646 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
647 wmi_radio_link_stats_event_fixed_param *fixed_param;
648 wmi_radio_link_stats *radio_stats;
649 wmi_channel_stats *channel_stats;
650 tSirLLStatsResults *link_stats_results;
651 uint8_t *results, *t_radio_stats, *t_channel_stats;
652 uint32_t next_res_offset, next_chan_offset, count;
653 size_t radio_stats_size, chan_stats_size;
654 size_t link_stats_results_size;
655
Anurag Chouhan6d760662016-02-20 16:05:43 +0530656 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657
658 if (!pMac) {
659 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
660 return -EINVAL;
661 }
662
663 if (!pMac->sme.pLinkLayerStatsIndCallback) {
664 WMA_LOGD("%s: HDD callback is null", __func__);
665 return -EINVAL;
666 }
667
668 WMA_LOGD("%s: Posting Radio Stats event to HDD", __func__);
669 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
670 if (!param_tlvs) {
671 WMA_LOGA("%s: Invalid stats event", __func__);
672 return -EINVAL;
673 }
674
675 /*
676 * cmd_param_info contains
677 * wmi_radio_link_stats_event_fixed_param fixed_param;
678 * size of(struct wmi_radio_link_stats);
679 * num_channels * size of(struct wmi_channel_stats)
680 */
681 fixed_param = param_tlvs->fixed_param;
682 radio_stats = param_tlvs->radio_stats;
683 channel_stats = param_tlvs->channel_stats;
684
685 if (!fixed_param || !radio_stats ||
686 (radio_stats->num_channels && !channel_stats)) {
687 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
688 return -EINVAL;
689 }
690
691 radio_stats_size = sizeof(tSirWifiRadioStat);
692 chan_stats_size = sizeof(tSirWifiChannelStats);
693 link_stats_results_size = sizeof(*link_stats_results) +
694 radio_stats_size + (radio_stats->num_channels * chan_stats_size);
695
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530696 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 if (NULL == link_stats_results) {
698 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
699 __func__, link_stats_results_size);
700 return -ENOMEM;
701 }
702
703 WMA_LOGD("Radio stats from FW event buf");
704 WMA_LOGD("Fixed Param:");
705 WMA_LOGD("request_id %u num_radio %u more_radio_events %u",
706 fixed_param->request_id, fixed_param->num_radio,
707 fixed_param->more_radio_events);
708
709 WMA_LOGD("Radio Info");
710 WMA_LOGD("radio_id %u on_time %u tx_time %u rx_time %u on_time_scan %u "
711 "on_time_nbd %u on_time_gscan %u on_time_roam_scan %u "
712 "on_time_pno_scan %u on_time_hs20 %u num_channels %u",
713 radio_stats->radio_id, radio_stats->on_time,
714 radio_stats->tx_time, radio_stats->rx_time,
715 radio_stats->on_time_scan, radio_stats->on_time_nbd,
716 radio_stats->on_time_gscan,
717 radio_stats->on_time_roam_scan,
718 radio_stats->on_time_pno_scan,
719 radio_stats->on_time_hs20, radio_stats->num_channels);
720
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530721 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722
723 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
724 link_stats_results->rspId = fixed_param->request_id;
725 link_stats_results->ifaceId = 0;
726 link_stats_results->num_radio = fixed_param->num_radio;
727 link_stats_results->peer_event_number = 0;
728 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
729
730 results = (uint8_t *) link_stats_results->results;
731 t_radio_stats = (uint8_t *) radio_stats;
732 t_channel_stats = (uint8_t *) channel_stats;
733
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530734 qdf_mem_copy(results, t_radio_stats + WMI_TLV_HDR_SIZE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800735 radio_stats_size);
736
737 next_res_offset = radio_stats_size;
738 next_chan_offset = WMI_TLV_HDR_SIZE;
739 WMA_LOGD("Channel Stats Info");
740 for (count = 0; count < radio_stats->num_channels; count++) {
741 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u "
742 "center_freq1 %u radio_awake_time %u cca_busy_time %u",
743 channel_stats->channel_width,
744 channel_stats->center_freq,
745 channel_stats->center_freq0,
746 channel_stats->center_freq1,
747 channel_stats->radio_awake_time,
748 channel_stats->cca_busy_time);
749 channel_stats++;
750
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530751 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800752 t_channel_stats + next_chan_offset,
753 chan_stats_size);
754 next_res_offset += chan_stats_size;
755 next_chan_offset += sizeof(*channel_stats);
756 }
757
758 /* call hdd callback with Link Layer Statistics
759 * vdev_id/ifacId in link_stats_results will be
760 * used to retrieve the correct HDD context
761 */
762 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
763 WMA_LINK_LAYER_STATS_RESULTS_RSP,
764 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530765 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766
767 return 0;
768}
769
770/**
771 * wma_register_ll_stats_event_handler() - register link layer stats related
772 * event handler
773 * @wma_handle: wma handle
774 *
775 * Return: none
776 */
777void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
778{
779 if (NULL == wma_handle) {
780 WMA_LOGE("%s: wma_handle is NULL", __func__);
781 return;
782 }
783
784 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +0530785 WMI_IFACE_LINK_STATS_EVENTID,
786 wma_unified_link_iface_stats_event_handler,
787 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +0530789 WMI_PEER_LINK_STATS_EVENTID,
790 wma_unified_link_peer_stats_event_handler,
791 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +0530793 WMI_RADIO_LINK_STATS_EVENTID,
794 wma_unified_link_radio_stats_event_handler,
795 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796
797 return;
798}
799
800
801/**
802 * wma_process_ll_stats_clear_req() - clear link layer stats
803 * @wma: wma handle
804 * @clearReq: ll stats clear request command params
805 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530806 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530808QDF_STATUS wma_process_ll_stats_clear_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800809 (tp_wma_handle wma, const tpSirLLStatsClearReq clearReq)
810{
Govind Singh4863da42016-03-08 11:45:00 +0530811 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812 int ret;
813
814 if (!clearReq || !wma) {
815 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530816 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817 }
818
Govind Singh4863da42016-03-08 11:45:00 +0530819 cmd.stop_req = clearReq->stopReq;
820 cmd.sta_id = clearReq->staId;
821 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822
Govind Singh4863da42016-03-08 11:45:00 +0530823 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
824 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 if (ret) {
826 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530827 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828 }
829
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530830 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800831}
832
833/**
834 * wma_process_ll_stats_set_req() - link layer stats set request
835 * @wma: wma handle
836 * @setReq: ll stats set request command params
837 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530838 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800839 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530840QDF_STATUS wma_process_ll_stats_set_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 (tp_wma_handle wma, const tpSirLLStatsSetReq setReq)
842{
Govind Singh4863da42016-03-08 11:45:00 +0530843 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844 int ret;
845
846 if (!setReq || !wma) {
847 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530848 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 }
850
Govind Singh4863da42016-03-08 11:45:00 +0530851 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
852 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853 setReq->aggressiveStatisticsGathering;
854
Govind Singh4863da42016-03-08 11:45:00 +0530855 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
856 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800857 if (ret) {
858 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530859 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860 }
861
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530862 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800863}
864
865/**
866 * wma_process_ll_stats_get_req() - link layer stats get request
867 * @wma:wma handle
868 * @getReq:ll stats get request command params
869 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530870 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530872QDF_STATUS wma_process_ll_stats_get_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 (tp_wma_handle wma, const tpSirLLStatsGetReq getReq)
874{
Govind Singh4863da42016-03-08 11:45:00 +0530875 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876 int ret;
877
878 if (!getReq || !wma) {
879 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530880 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800881 }
882
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +0530883 if (!wma->interfaces[getReq->staId].vdev_active) {
884 WMA_LOGE("%s: vdev not created yet", __func__);
885 return QDF_STATUS_E_FAILURE;
886 }
887
Govind Singh4863da42016-03-08 11:45:00 +0530888 cmd.req_id = getReq->reqId;
889 cmd.param_id_mask = getReq->paramIdMask;
890 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800891
Govind Singh4863da42016-03-08 11:45:00 +0530892 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
893 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 if (ret) {
895 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530896 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800897 }
898
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530899 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900}
901
902/**
903 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
904 * @wma:wma handle
905 * @cmd_param_info: data from event
906 * @len: length
907 *
908 * Return: 0 for success or error code
909 */
910int wma_unified_link_iface_stats_event_handler(void *handle,
911 uint8_t *cmd_param_info,
912 uint32_t len)
913{
914 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
915 wmi_iface_link_stats_event_fixed_param *fixed_param;
916 wmi_iface_link_stats *link_stats;
917 wmi_wmm_ac_stats *ac_stats;
918 tSirLLStatsResults *link_stats_results;
919 uint8_t *results, *t_link_stats, *t_ac_stats;
920 uint32_t next_res_offset, next_ac_offset, count;
921 uint32_t roaming_offset, roaming_size;
922 size_t link_stats_size, ac_stats_size, iface_info_size;
923 size_t link_stats_results_size;
924
Anurag Chouhan6d760662016-02-20 16:05:43 +0530925 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926
927 if (!pMac) {
928 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
929 return -EINVAL;
930 }
931
932 if (!pMac->sme.pLinkLayerStatsIndCallback) {
933 WMA_LOGD("%s: HDD callback is null", __func__);
934 return -EINVAL;
935 }
936
937 WMA_LOGD("%s: Posting Iface Stats event to HDD", __func__);
938 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
939 if (!param_tlvs) {
940 WMA_LOGA("%s: Invalid stats event", __func__);
941 return -EINVAL;
942 }
943
944 /*
945 * cmd_param_info contains
946 * wmi_iface_link_stats_event_fixed_param fixed_param;
947 * wmi_iface_link_stats iface_link_stats;
948 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
949 */
950 fixed_param = param_tlvs->fixed_param;
951 link_stats = param_tlvs->iface_link_stats;
952 ac_stats = param_tlvs->ac;
953
954 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats)) {
955 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
956 return -EINVAL;
957 }
958
959 link_stats_size = sizeof(tSirWifiIfaceStat);
960 iface_info_size = sizeof(tSirWifiInterfaceInfo);
961 ac_stats_size = sizeof(tSirWifiWmmAcStat);
962 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
963
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530964 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800965 if (!link_stats_results) {
966 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
967 __func__, link_stats_results_size);
968 return -ENOMEM;
969 }
970
971 WMA_LOGD("Interface stats from FW event buf");
972 WMA_LOGD("Fixed Param:");
973 WMA_LOGD("request_id %u vdev_id %u",
974 fixed_param->request_id, fixed_param->vdev_id);
975
976 WMA_LOGD("Iface Stats:");
977 WMA_LOGD("beacon_rx %u mgmt_rx %u mgmt_action_rx %u mgmt_action_tx %u "
978 "rssi_mgmt %u rssi_data %u rssi_ack %u num_peers %u "
979 "num_peer_events %u num_ac %u roam_state %u"
980 " avg_bcn_spread_offset_high %u"
981 " avg_bcn_spread_offset_low %u"
982 " is leaky_ap %u"
983 " avg_rx_frames_leaked %u"
984 " rx_leak_window %u",
985 link_stats->beacon_rx, link_stats->mgmt_rx,
986 link_stats->mgmt_action_rx, link_stats->mgmt_action_tx,
987 link_stats->rssi_mgmt, link_stats->rssi_data,
988 link_stats->rssi_ack, link_stats->num_peers,
989 link_stats->num_peer_events, link_stats->num_ac,
990 link_stats->roam_state,
991 link_stats->avg_bcn_spread_offset_high,
992 link_stats->avg_bcn_spread_offset_low,
993 link_stats->is_leaky_ap,
994 link_stats->avg_rx_frms_leaked,
995 link_stats->rx_leak_window);
996
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530997 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998
999 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
1000 link_stats_results->rspId = fixed_param->request_id;
1001 link_stats_results->ifaceId = fixed_param->vdev_id;
1002 link_stats_results->num_peers = link_stats->num_peers;
1003 link_stats_results->peer_event_number = 0;
1004 link_stats_results->moreResultToFollow = 0;
1005
1006 results = (uint8_t *) link_stats_results->results;
1007 t_link_stats = (uint8_t *) link_stats;
1008 t_ac_stats = (uint8_t *) ac_stats;
1009
1010 /* Copy roaming state */
1011 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
1012 roaming_size = member_size(tSirWifiInterfaceInfo, roaming);
1013
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301014 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015 roaming_size);
1016
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301017 qdf_mem_copy(results + iface_info_size,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001018 t_link_stats + WMI_TLV_HDR_SIZE,
1019 link_stats_size - iface_info_size -
1020 WIFI_AC_MAX * ac_stats_size);
1021
1022 next_res_offset = link_stats_size - WIFI_AC_MAX * ac_stats_size;
1023 next_ac_offset = WMI_TLV_HDR_SIZE;
1024
1025 WMA_LOGD("AC Stats:");
1026 for (count = 0; count < link_stats->num_ac; count++) {
1027 WMA_LOGD("ac_type %u tx_mpdu %u rx_mpdu %u tx_mcast %u "
1028 "rx_mcast %u rx_ampdu %u tx_ampdu %u mpdu_lost %u "
1029 "retries %u retries_short %u retries_long %u "
1030 "contention_time_min %u contention_time_max %u "
1031 "contention_time_avg %u contention_num_samples %u",
1032 ac_stats->ac_type, ac_stats->tx_mpdu,
1033 ac_stats->rx_mpdu, ac_stats->tx_mcast,
1034 ac_stats->rx_mcast, ac_stats->rx_ampdu,
1035 ac_stats->tx_ampdu, ac_stats->mpdu_lost,
1036 ac_stats->retries, ac_stats->retries_short,
1037 ac_stats->retries_long, ac_stats->contention_time_min,
1038 ac_stats->contention_time_max,
1039 ac_stats->contention_time_avg,
1040 ac_stats->contention_num_samples);
1041 ac_stats++;
1042
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301043 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001044 t_ac_stats + next_ac_offset, ac_stats_size);
1045 next_res_offset += ac_stats_size;
1046 next_ac_offset += sizeof(*ac_stats);
1047 }
1048
1049 /* call hdd callback with Link Layer Statistics
1050 * vdev_id/ifacId in link_stats_results will be
1051 * used to retrieve the correct HDD context
1052 */
1053 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1054 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1055 link_stats_results);
1056 WMA_LOGD("%s: Iface Stats event posted to HDD", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301057 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001058
1059 return 0;
1060}
1061
1062#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1063
1064/**
1065 * wma_update_pdev_stats() - update pdev stats
1066 * @wma: wma handle
1067 * @pdev_stats: pdev stats
1068 *
1069 * Return: none
1070 */
1071static void wma_update_pdev_stats(tp_wma_handle wma,
1072 wmi_pdev_stats *pdev_stats)
1073{
1074 tAniGetPEStatsRsp *stats_rsp_params;
1075 uint32_t temp_mask;
1076 uint8_t *stats_buf;
1077 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
1078 struct wma_txrx_node *node;
1079 uint8_t i;
1080
1081 for (i = 0; i < wma->max_bssid; i++) {
1082 node = &wma->interfaces[i];
1083 stats_rsp_params = node->stats_rsp;
1084 if (stats_rsp_params) {
1085 node->fw_stats_set |= FW_PDEV_STATS_SET;
1086 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
1087 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1088 temp_mask = stats_rsp_params->statsMask;
1089 if (temp_mask & (1 << eCsrSummaryStats))
1090 stats_buf += sizeof(tCsrSummaryStatsInfo);
1091
1092 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
1093 classa_stats =
1094 (tCsrGlobalClassAStatsInfo *) stats_buf;
1095 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
1096 }
1097 }
1098 }
1099}
1100
1101/**
1102 * wma_update_vdev_stats() - update vdev stats
1103 * @wma: wma handle
1104 * @vdev_stats: vdev stats
1105 *
1106 * Return: none
1107 */
1108static void wma_update_vdev_stats(tp_wma_handle wma,
1109 wmi_vdev_stats *vdev_stats)
1110{
1111 tAniGetPEStatsRsp *stats_rsp_params;
1112 tCsrSummaryStatsInfo *summary_stats = NULL;
1113 uint8_t *stats_buf;
1114 struct wma_txrx_node *node;
1115 uint8_t i;
1116 int8_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301117 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
1119 cds_msg_t sme_msg = { 0 };
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001120 int8_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121
1122 node = &wma->interfaces[vdev_stats->vdev_id];
1123 stats_rsp_params = node->stats_rsp;
1124 if (stats_rsp_params) {
1125 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1126 node->fw_stats_set |= FW_VDEV_STATS_SET;
1127 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
1128 vdev_stats->vdev_id);
1129 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
1130 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
1131 for (i = 0; i < 4; i++) {
1132 summary_stats->tx_frm_cnt[i] =
1133 vdev_stats->tx_frm_cnt[i];
1134 summary_stats->fail_cnt[i] =
1135 vdev_stats->fail_cnt[i];
1136 summary_stats->multiple_retry_cnt[i] =
1137 vdev_stats->multiple_retry_cnt[i];
1138 }
1139
1140 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
1141 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
1142 summary_stats->rx_discard_cnt =
1143 vdev_stats->rx_discard_cnt;
1144 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
1145 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
1146 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
1147 }
1148 }
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001149 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
1150 dat_snr = vdev_stats->vdev_snr.dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001152 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
1153 vdev_stats->vdev_id, bcn_snr, dat_snr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154
1155 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001156 if ((bcn_snr == WMA_TGT_INVALID_SNR) &&
1157 (dat_snr == WMA_TGT_INVALID_SNR)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158 /*
1159 * Firmware sends invalid snr till it sees
1160 * Beacon/Data after connection since after
1161 * vdev up fw resets the snr to invalid.
1162 * In this duartion Host will return the last know
1163 * rssi during connection.
1164 */
1165 WMA_LOGE("Invalid SNR from firmware");
1166
1167 } else {
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001168 if (bcn_snr != WMA_TGT_INVALID_SNR) {
1169 rssi = bcn_snr;
1170 } else if (dat_snr != WMA_TGT_INVALID_SNR) {
1171 rssi = dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001172 }
1173
1174 /*
1175 * Get the absolute rssi value from the current rssi value
1176 * the sinr value is hardcoded into 0 in the core stack
1177 */
1178 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
1179 }
1180
1181 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
1182 pGetRssiReq->sessionId);
1183
1184 /* update the average rssi value to UMAC layer */
1185 if (NULL != pGetRssiReq->rssiCallback) {
1186 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
1187 pGetRssiReq->staId,
1188 pGetRssiReq->pDevContext);
1189 }
1190
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301191 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 wma->pGetRssiReq = NULL;
1193 }
1194
1195 if (node->psnr_req) {
1196 tAniGetSnrReq *p_snr_req = node->psnr_req;
1197
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001198 if (bcn_snr != WMA_TGT_INVALID_SNR)
1199 p_snr_req->snr = bcn_snr;
1200 else if (dat_snr != WMA_TGT_INVALID_SNR)
1201 p_snr_req->snr = dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202 else
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07001203 p_snr_req->snr = (int8_t)WMA_TGT_INVALID_SNR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204
1205 sme_msg.type = eWNI_SME_SNR_IND;
1206 sme_msg.bodyptr = p_snr_req;
1207 sme_msg.bodyval = 0;
1208
Anurag Chouhan6d760662016-02-20 16:05:43 +05301209 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301210 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301212 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 }
1214
1215 node->psnr_req = NULL;
1216 }
1217}
1218
1219/**
1220 * wma_post_stats() - update stats to PE
1221 * @wma: wma handle
1222 * @node: txrx node
1223 *
1224 * Return: none
1225 */
1226static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
1227{
1228 tAniGetPEStatsRsp *stats_rsp_params;
1229
1230 stats_rsp_params = node->stats_rsp;
1231 /* send response to UMAC */
1232 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, (void *)stats_rsp_params, 0);
1233 node->stats_rsp = NULL;
1234 node->fw_stats_set = 0;
1235}
1236
1237/**
1238 * wma_update_peer_stats() - update peer stats
1239 * @wma: wma handle
1240 * @peer_stats: peer stats
1241 *
1242 * Return: none
1243 */
1244static void wma_update_peer_stats(tp_wma_handle wma,
1245 wmi_peer_stats *peer_stats)
1246{
1247 tAniGetPEStatsRsp *stats_rsp_params;
1248 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
1249 struct wma_txrx_node *node;
1250 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
1251 uint32_t temp_mask;
1252
1253 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
1254 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
1255 return;
1256
1257 node = &wma->interfaces[vdev_id];
1258 if (node->stats_rsp) {
1259 node->fw_stats_set |= FW_PEER_STATS_SET;
1260 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
1261 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
1262 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1263 temp_mask = stats_rsp_params->statsMask;
1264 if (temp_mask & (1 << eCsrSummaryStats))
1265 stats_buf += sizeof(tCsrSummaryStatsInfo);
1266
1267 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
1268 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
1269 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
1270 /*The linkspeed returned by fw is in kbps so convert
1271 *it in to units of 500kbps which is expected by UMAC*/
1272 if (peer_stats->peer_tx_rate) {
1273 classa_stats->tx_rate =
1274 peer_stats->peer_tx_rate / 500;
1275 }
1276
1277 classa_stats->tx_rate_flags = node->rate_flags;
1278 if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) {
1279 classa_stats->mcs_index =
1280 wma_get_mcs_idx((peer_stats->peer_tx_rate /
1281 100), node->rate_flags,
1282 node->nss, &mcsRateFlags);
1283 /* rx_frag_cnt and promiscuous_rx_frag_cnt
1284 * parameter is currently not used. lets use the
1285 * same parameter to hold the nss value and mcs
1286 * rate flags */
1287 classa_stats->rx_frag_cnt = node->nss;
1288 classa_stats->promiscuous_rx_frag_cnt =
1289 mcsRateFlags;
1290 WMA_LOGD("Computed mcs_idx:%d mcs_rate_flags:%d",
1291 classa_stats->mcs_index, mcsRateFlags);
1292 }
1293 /* FW returns tx power in intervals of 0.5 dBm
1294 Convert it back to intervals of 1 dBm */
1295 classa_stats->max_pwr =
1296 roundup(classa_stats->max_pwr, 2) >> 1;
1297 WMA_LOGD("peer tx rate flags:%d nss:%d max_txpwr:%d",
1298 node->rate_flags, node->nss,
1299 classa_stats->max_pwr);
1300 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 }
1302}
1303
1304/**
1305 * wma_post_link_status() - post link status to SME
1306 * @pGetLinkStatus: SME Link status
1307 * @link_status: Link status
1308 *
1309 * Return: none
1310 */
1311void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
1312 uint8_t link_status)
1313{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301314 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315 cds_msg_t sme_msg = { 0 };
1316
1317 pGetLinkStatus->linkStatus = link_status;
1318 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
1319 sme_msg.bodyptr = pGetLinkStatus;
1320 sme_msg.bodyval = 0;
1321
Anurag Chouhan6d760662016-02-20 16:05:43 +05301322 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301323 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301325 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 }
1327}
1328
1329/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301330 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
1331 * @wma: wma handle
1332 * @rssi_stats: rssi stats
1333 * @rssi_per_chain_stats: buffer where rssi stats to be stored
1334 *
1335 * This function stores per chain rssi stats received from fw for all vdevs for
1336 * which the stats were requested into a csr stats structure.
1337 *
1338 * Return: void
1339 */
1340static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
1341 wmi_rssi_stats *rssi_stats,
1342 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
1343{
1344 int i;
1345 int8_t bcn_snr, dat_snr;
1346
1347 for (i = 0; i < NUM_CHAINS_MAX; i++) {
1348 bcn_snr = rssi_stats->rssi_avg_beacon[i];
1349 dat_snr = rssi_stats->rssi_avg_data[i];
1350 WMA_LOGD("chain %d beacon snr %d data snr %d",
1351 i, bcn_snr, dat_snr);
1352 if (dat_snr != WMA_TGT_INVALID_SNR)
1353 rssi_per_chain_stats->rssi[i] = dat_snr;
1354 else if (bcn_snr != WMA_TGT_INVALID_SNR)
1355 rssi_per_chain_stats->rssi[i] = bcn_snr;
1356 else
1357 /*
1358 * Firmware sends invalid snr till it sees
1359 * Beacon/Data after connection since after
1360 * vdev up fw resets the snr to invalid.
1361 * In this duartion Host will return an invalid rssi
1362 * value.
1363 */
1364 rssi_per_chain_stats->rssi[i] = WMA_TGT_RSSI_INVALID;
1365
1366 /*
1367 * Get the absolute rssi value from the current rssi value the
1368 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
1369 */
1370 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
1371 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
1372 rssi_per_chain_stats->peer_mac_addr);
1373 }
1374}
1375
1376/**
1377 * wma_update_rssi_stats() - to update rssi stats for all vdevs
1378 * for which the stats were requested.
1379 * @wma: wma handle
1380 * @rssi_stats: rssi stats
1381 *
1382 * This function updates the rssi stats for all vdevs for which
1383 * the stats were requested.
1384 *
1385 * Return: void
1386 */
1387static void wma_update_rssi_stats(tp_wma_handle wma,
1388 wmi_rssi_stats *rssi_stats)
1389{
1390 tAniGetPEStatsRsp *stats_rsp_params;
1391 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
1392 struct wma_txrx_node *node;
1393 uint8_t *stats_buf;
1394 uint32_t temp_mask;
1395 uint8_t vdev_id;
1396
1397 vdev_id = rssi_stats->vdev_id;
1398 node = &wma->interfaces[vdev_id];
1399 if (node->stats_rsp) {
1400 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
1401 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
1402 vdev_id);
1403 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
1404 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1405 temp_mask = stats_rsp_params->statsMask;
1406
1407 if (temp_mask & (1 << eCsrSummaryStats))
1408 stats_buf += sizeof(tCsrSummaryStatsInfo);
1409 if (temp_mask & (1 << eCsrGlobalClassAStats))
1410 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
1411 if (temp_mask & (1 << eCsrGlobalClassBStats))
1412 stats_buf += sizeof(tCsrGlobalClassBStatsInfo);
1413 if (temp_mask & (1 << eCsrGlobalClassCStats))
1414 stats_buf += sizeof(tCsrGlobalClassCStatsInfo);
1415 if (temp_mask & (1 << eCsrGlobalClassDStats))
1416 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
1417 if (temp_mask & (1 << eCsrPerStaStats))
1418 stats_buf += sizeof(tCsrPerStaStatsInfo);
1419
1420 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
1421 rssi_per_chain_stats =
1422 (struct csr_per_chain_rssi_stats_info *)stats_buf;
1423 wma_update_per_chain_rssi_stats(wma, rssi_stats,
1424 rssi_per_chain_stats);
1425 }
1426 }
1427}
1428
1429
1430/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001431 * wma_link_status_event_handler() - link status event handler
1432 * @handle: wma handle
1433 * @cmd_param_info: data from event
1434 * @len: length
1435 *
1436 * Return: 0 for success or error code
1437 */
1438int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
1439 uint32_t len)
1440{
1441 tp_wma_handle wma = (tp_wma_handle) handle;
1442 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
1443 wmi_vdev_rate_stats_event_fixed_param *event;
1444 wmi_vdev_rate_ht_info *ht_info;
1445 struct wma_txrx_node *intr = wma->interfaces;
1446 uint8_t link_status = LINK_STATUS_LEGACY;
1447 int i;
1448
1449 param_buf =
1450 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
1451 if (!param_buf) {
1452 WMA_LOGA("%s: Invalid stats event", __func__);
1453 return -EINVAL;
1454 }
1455
1456 event = (wmi_vdev_rate_stats_event_fixed_param *) param_buf->fixed_param;
1457 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
1458
1459 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
1460 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
1461 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
1462 __func__, ht_info->vdevid, ht_info->tx_nss,
1463 ht_info->rx_nss, ht_info->tx_preamble,
1464 ht_info->rx_preamble);
1465 if (ht_info->vdevid < wma->max_bssid
1466 && intr[ht_info->vdevid].plink_status_req) {
1467 if (ht_info->tx_nss || ht_info->rx_nss)
1468 link_status = LINK_STATUS_MIMO;
1469
1470 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
1471 (ht_info->rx_preamble == LINK_RATE_VHT))
1472 link_status |= LINK_STATUS_VHT;
1473
1474 if (intr[ht_info->vdevid].nss == 2)
1475 link_status |= LINK_SUPPORT_MIMO;
1476
1477 if (intr[ht_info->vdevid].rate_flags &
1478 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
1479 eHAL_TX_RATE_VHT80))
1480 link_status |= LINK_SUPPORT_VHT;
1481
1482 wma_post_link_status(intr[ht_info->vdevid].plink_status_req,
1483 link_status);
1484 intr[ht_info->vdevid].plink_status_req = NULL;
1485 link_status = LINK_STATUS_LEGACY;
1486 }
1487
1488 ht_info++;
1489 }
1490
1491 return 0;
1492}
1493
1494/**
1495 * wma_stats_event_handler() - stats event handler
1496 * @handle: wma handle
1497 * @cmd_param_info: data from event
1498 * @len: length
1499 *
1500 * Return: 0 for success or error code
1501 */
1502int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
1503 uint32_t len)
1504{
1505 tp_wma_handle wma = (tp_wma_handle) handle;
1506 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
1507 wmi_stats_event_fixed_param *event;
1508 wmi_pdev_stats *pdev_stats;
1509 wmi_vdev_stats *vdev_stats;
1510 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301511 wmi_rssi_stats *rssi_stats;
1512 wmi_per_chain_rssi_stats *rssi_event;
1513 struct wma_txrx_node *node;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001514 uint8_t i, *temp;
1515
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
1517 if (!param_buf) {
1518 WMA_LOGA("%s: Invalid stats event", __func__);
1519 return -EINVAL;
1520 }
1521 event = param_buf->fixed_param;
1522 temp = (uint8_t *) param_buf->data;
1523
1524 WMA_LOGD("%s: num_stats: pdev: %u vdev: %u peer %u",
1525 __func__, event->num_pdev_stats, event->num_vdev_stats,
1526 event->num_peer_stats);
1527 if (event->num_pdev_stats > 0) {
1528 for (i = 0; i < event->num_pdev_stats; i++) {
1529 pdev_stats = (wmi_pdev_stats *) temp;
1530 wma_update_pdev_stats(wma, pdev_stats);
1531 temp += sizeof(wmi_pdev_stats);
1532 }
1533 }
1534
1535 if (event->num_vdev_stats > 0) {
1536 for (i = 0; i < event->num_vdev_stats; i++) {
1537 vdev_stats = (wmi_vdev_stats *) temp;
1538 wma_update_vdev_stats(wma, vdev_stats);
1539 temp += sizeof(wmi_vdev_stats);
1540 }
1541 }
1542
1543 if (event->num_peer_stats > 0) {
1544 for (i = 0; i < event->num_peer_stats; i++) {
1545 peer_stats = (wmi_peer_stats *) temp;
1546 wma_update_peer_stats(wma, peer_stats);
1547 temp += sizeof(wmi_peer_stats);
1548 }
1549 }
1550
Himanshu Agarwal37e42412016-07-21 14:35:09 +05301551 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
1552 if (rssi_event) {
1553 if ((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
1554 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) {
1555 WMA_LOGD("%s: num_rssi_stats %u", __func__,
1556 rssi_event->num_per_chain_rssi_stats);
1557 if (rssi_event->num_per_chain_rssi_stats > 0) {
1558 temp = (uint8_t *) rssi_event;
1559 temp += sizeof(*rssi_event);
1560 for (i = 0;
1561 i < rssi_event->num_per_chain_rssi_stats;
1562 i++) {
1563 rssi_stats = (wmi_rssi_stats *)temp;
1564 wma_update_rssi_stats(wma, rssi_stats);
1565 temp += sizeof(wmi_rssi_stats);
1566 }
1567 }
1568 }
1569 }
1570
1571 for (i = 0; i < wma->max_bssid; i++) {
1572 node = &wma->interfaces[i];
1573 if (node->fw_stats_set & FW_PEER_STATS_SET) {
1574 WMA_LOGD("<--STATS RSP VDEV_ID:%d", i);
1575 wma_post_stats(wma, node);
1576 }
1577 }
1578
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 WMA_LOGI("%s: Exit", __func__);
1580 return 0;
1581}
1582
1583/**
1584 * wma_send_link_speed() - send link speed to SME
1585 * @link_speed: link speed
1586 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301587 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001588 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301589QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001590{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301591 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001592 cds_msg_t sme_msg = { 0 };
1593 tSirLinkSpeedInfo *ls_ind =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301594 (tSirLinkSpeedInfo *) qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001595 if (!ls_ind) {
1596 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301597 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598 } else {
1599 ls_ind->estLinkSpeed = link_speed;
1600 sme_msg.type = eWNI_SME_LINK_SPEED_IND;
1601 sme_msg.bodyptr = ls_ind;
1602 sme_msg.bodyval = 0;
1603
Anurag Chouhan6d760662016-02-20 16:05:43 +05301604 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301605 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606 WMA_LOGE("%s: Fail to post linkspeed ind msg",
1607 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301608 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609 }
1610 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301611 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612}
1613
1614/**
1615 * wma_link_speed_event_handler() - link speed event handler
1616 * @handle: wma handle
1617 * @cmd_param_info: event data
1618 * @len: length
1619 *
1620 * Return: 0 for success or error code
1621 */
1622int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
1623 uint32_t len)
1624{
1625 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
1626 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301627 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001628
1629 param_buf =
1630 (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *) cmd_param_info;
1631 if (!param_buf) {
1632 WMA_LOGE("%s: Invalid linkspeed event", __func__);
1633 return -EINVAL;
1634 }
1635 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301636 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
1637 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638 return -EINVAL;
1639 }
1640 return 0;
1641}
1642
1643/**
1644 * wma_wni_cfg_dnld() - cfg download request
1645 * @handle: wma handle
1646 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301647 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301649QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301651 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301652 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001653
1654 WMA_LOGD("%s: Enter", __func__);
1655
1656 if (NULL == mac) {
1657 WMA_LOGP("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301658 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301659 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001660 }
1661
1662 process_cfg_download_req(mac);
1663
1664 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301665 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666}
1667
1668/**
1669 * wma_unified_debug_print_event_handler() - debug print event handler
1670 * @handle: wma handle
1671 * @datap: data pointer
1672 * @len: length
1673 *
1674 * Return: 0 for success or error code
1675 */
1676int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
1677 uint32_t len)
1678{
1679 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
1680 uint8_t *data;
1681 uint32_t datalen;
1682
1683 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
1684 if (!param_buf) {
1685 WMA_LOGE("Get NULL point message from FW");
1686 return -ENOMEM;
1687 }
1688 data = param_buf->data;
1689 datalen = param_buf->num_data;
1690
1691#ifdef BIG_ENDIAN_HOST
1692 {
1693 char dbgbuf[500] = { 0 };
1694 memcpy(dbgbuf, data, datalen);
1695 SWAPME(dbgbuf, datalen);
1696 WMA_LOGD("FIRMWARE:%s", dbgbuf);
1697 return 0;
1698 }
1699#else
1700 WMA_LOGD("FIRMWARE:%s", data);
1701 return 0;
1702#endif /* BIG_ENDIAN_HOST */
1703}
1704
1705/**
1706 * wma_check_scan_in_progress() - check scan is progress or not
1707 * @handle: wma handle
1708 *
1709 * Return: true/false
1710 */
1711bool wma_check_scan_in_progress(WMA_HANDLE handle)
1712{
1713 tp_wma_handle wma_handle = handle;
1714 int i;
1715
1716 for (i = 0; i < wma_handle->max_bssid; i++) {
1717 if (wma_handle->interfaces[i].scan_info.scan_id) {
1718
1719 WMA_LOGE("%s: scan in progress on interface[%d],scanid = %d",
1720 __func__, i,
1721 wma_handle->interfaces[i].scan_info.scan_id);
1722 return true;
1723 }
1724 }
1725 return false;
1726}
1727
1728/**
1729 * wma_is_sap_active() - check sap is active or not
1730 * @handle: wma handle
1731 *
1732 * Return: true/false
1733 */
1734bool wma_is_sap_active(tp_wma_handle wma_handle)
1735{
1736 int i;
1737
1738 for (i = 0; i < wma_handle->max_bssid; i++) {
1739 if (!wma_handle->interfaces[i].vdev_up)
1740 continue;
1741 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
1742 wma_handle->interfaces[i].sub_type == 0)
1743 return true;
1744 }
1745 return false;
1746}
1747
1748/**
1749 * wma_is_p2p_go_active() - check p2p go is active or not
1750 * @handle: wma handle
1751 *
1752 * Return: true/false
1753 */
1754bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
1755{
1756 int i;
1757
1758 for (i = 0; i < wma_handle->max_bssid; i++) {
1759 if (!wma_handle->interfaces[i].vdev_up)
1760 continue;
1761 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
1762 wma_handle->interfaces[i].sub_type ==
1763 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
1764 return true;
1765 }
1766 return false;
1767}
1768
1769/**
1770 * wma_is_p2p_cli_active() - check p2p cli is active or not
1771 * @handle: wma handle
1772 *
1773 * Return: true/false
1774 */
1775bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
1776{
1777 int i;
1778
1779 for (i = 0; i < wma_handle->max_bssid; i++) {
1780 if (!wma_handle->interfaces[i].vdev_up)
1781 continue;
1782 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
1783 wma_handle->interfaces[i].sub_type ==
1784 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
1785 return true;
1786 }
1787 return false;
1788}
1789
1790/**
1791 * wma_is_sta_active() - check sta is active or not
1792 * @handle: wma handle
1793 *
1794 * Return: true/false
1795 */
1796bool wma_is_sta_active(tp_wma_handle wma_handle)
1797{
1798 int i;
1799
1800 for (i = 0; i < wma_handle->max_bssid; i++) {
1801 if (!wma_handle->interfaces[i].vdev_up)
1802 continue;
1803 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
1804 wma_handle->interfaces[i].sub_type == 0)
1805 return true;
1806 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
1807 return true;
1808 }
1809 return false;
1810}
1811
1812/**
1813 * wma_peer_phymode() - get phymode
1814 * @nw_type: nw type
1815 * @sta_type: sta type
1816 * @is_ht: is ht supported
1817 * @is_cw40: is channel width 40 supported
1818 * @is_vht: is vht supported
1819 * @is_cw_vht: is channel width 80 supported
1820 *
1821 * Return: WLAN_PHY_MODE
1822 */
1823WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
1824 uint8_t is_ht, uint8_t ch_width,
1825 uint8_t is_vht)
1826{
1827 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
1828
1829 switch (nw_type) {
1830 case eSIR_11B_NW_TYPE:
1831 phymode = MODE_11B;
1832 if (is_ht || is_vht)
1833 WMA_LOGE("HT/VHT is enabled with 11B NW type");
1834 break;
1835 case eSIR_11G_NW_TYPE:
1836 if (!(is_ht || is_vht)) {
1837 phymode = MODE_11G;
1838 break;
1839 }
1840 if (CH_WIDTH_40MHZ < ch_width)
1841 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
1842 if (ch_width)
1843 phymode = (is_vht) ?
Krishna Kumaar Natarajan294da812016-04-28 14:39:30 -07001844 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001845 else
1846 phymode = (is_vht) ?
Krishna Kumaar Natarajan294da812016-04-28 14:39:30 -07001847 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848 break;
1849 case eSIR_11A_NW_TYPE:
1850 if (!(is_ht || is_vht)) {
1851 phymode = MODE_11A;
1852 break;
1853 }
1854 if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001855 if (ch_width == CH_WIDTH_160MHZ)
1856 phymode = MODE_11AC_VHT160;
1857 else if (ch_width == CH_WIDTH_80P80MHZ)
1858 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07001859 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860 phymode = MODE_11AC_VHT80;
1861 else
1862 phymode = (ch_width) ?
1863 MODE_11AC_VHT40 : MODE_11AC_VHT20;
1864 } else
1865 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
1866 break;
1867 default:
1868 WMA_LOGP("%s: Invalid nw type %d", __func__, nw_type);
1869 break;
1870 }
1871 WMA_LOGD("%s: nw_type %d is_ht %d ch_width %d is_vht %d phymode %d",
1872 __func__, nw_type, is_ht, ch_width, is_vht, phymode);
1873
1874 return phymode;
1875}
1876
1877/**
1878 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
1879 * @wma_handle: wma handle
1880 * @vdev_id: vdev id
1881 * @value: value
1882 *
1883 * Return: 0 for success or return error
1884 */
1885int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
1886 uint8_t vdev_id, uint32_t value)
1887{
1888 struct ol_txrx_stats_req req;
1889 ol_txrx_vdev_handle vdev;
1890
1891 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
1892 if (!vdev) {
1893 WMA_LOGE("%s:Invalid vdev handle", __func__);
1894 return -EINVAL;
1895 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301896 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 req.stats_type_reset_mask = value;
Nirav Shahd2310422016-01-21 18:58:06 +05301898 ol_txrx_fw_stats_get(vdev, &req, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899
1900 return 0;
1901}
1902
1903#ifdef HELIUMPLUS
1904#define SET_UPLOAD_MASK(_mask, _rate_info) \
1905 ((_mask) = 1 << (_rate_info ## _V2))
1906#else /* !HELIUMPLUS */
1907#define SET_UPLOAD_MASK(_mask, _rate_info) \
1908 ((_mask) = 1 << (_rate_info))
1909#endif
1910
Nirav Shah93e789e2016-04-14 19:47:43 +05301911#ifdef HELIUMPLUS
1912bool wma_is_valid_fw_stats_cmd(uint32_t value)
1913{
1914 if (value > (HTT_DBG_NUM_STATS + 1) ||
1915 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
1916 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
1917 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
1918 WMA_LOGE("%s: Not supported", __func__);
1919 return false;
1920 }
1921 return true;
1922}
1923#else
1924bool wma_is_valid_fw_stats_cmd(uint32_t value)
1925{
1926 if (value > (HTT_DBG_NUM_STATS + 1) ||
1927 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
1928 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
1929 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
1930 WMA_LOGE("%s: Not supported", __func__);
1931 return false;
1932 }
1933 return true;
1934}
1935#endif
1936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937/**
1938 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
1939 * @wma_handle: wma handle
1940 * @vdev_id: vdev id
1941 * @value: value
1942 *
1943 * Return: 0 for success or return error
1944 */
1945int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
1946 uint8_t vdev_id, uint32_t value)
1947{
1948 struct ol_txrx_stats_req req;
1949 ol_txrx_vdev_handle vdev;
1950 uint32_t l_up_mask;
1951
1952 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
1953 if (!vdev) {
1954 WMA_LOGE("%s:Invalid vdev handle", __func__);
1955 return -EINVAL;
1956 }
Nirav Shah93e789e2016-04-14 19:47:43 +05301957
1958 if (wma_is_valid_fw_stats_cmd(value) == false)
1959 return -EINVAL;
1960
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301961 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 req.print.verbose = 1;
1963
Nirav Shah93e789e2016-04-14 19:47:43 +05301964 /* TODO: Need to check how to avoid mem leak*/
1965 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 req.stats_type_upload_mask = l_up_mask;
1967
Nirav Shahd2310422016-01-21 18:58:06 +05301968 ol_txrx_fw_stats_get(vdev, &req, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969
1970 return 0;
1971}
1972
1973/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 * wma_get_stats_rsp_buf() - fill get stats response buffer
1975 * @get_stats_param: get stats parameters
1976 *
1977 * Return: stats response buffer
1978 */
1979static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
1980 (tAniGetPEStatsReq *get_stats_param)
1981{
1982 tAniGetPEStatsRsp *stats_rsp_params;
1983 uint32_t len, temp_mask, counter = 0;
1984
1985 len = sizeof(tAniGetPEStatsRsp);
1986 temp_mask = get_stats_param->statsMask;
1987
1988 while (temp_mask) {
1989 if (temp_mask & 1) {
1990 switch (counter) {
1991 case eCsrSummaryStats:
1992 len += sizeof(tCsrSummaryStatsInfo);
1993 break;
1994 case eCsrGlobalClassAStats:
1995 len += sizeof(tCsrGlobalClassAStatsInfo);
1996 break;
1997 case eCsrGlobalClassBStats:
1998 len += sizeof(tCsrGlobalClassBStatsInfo);
1999 break;
2000 case eCsrGlobalClassCStats:
2001 len += sizeof(tCsrGlobalClassCStatsInfo);
2002 break;
2003 case eCsrGlobalClassDStats:
2004 len += sizeof(tCsrGlobalClassDStatsInfo);
2005 break;
2006 case eCsrPerStaStats:
2007 len += sizeof(tCsrPerStaStatsInfo);
2008 break;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302009 case csr_per_chain_rssi_stats:
2010 len +=
2011 sizeof(struct csr_per_chain_rssi_stats_info);
2012 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013 }
2014 }
2015
2016 counter++;
2017 temp_mask >>= 1;
2018 }
2019
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302020 stats_rsp_params = (tAniGetPEStatsRsp *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 if (!stats_rsp_params) {
2022 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302023 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 return NULL;
2025 }
2026
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302027 qdf_mem_zero(stats_rsp_params, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 stats_rsp_params->staId = get_stats_param->staId;
2029 stats_rsp_params->statsMask = get_stats_param->statsMask;
2030 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
2031 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302032 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033 return stats_rsp_params;
2034}
2035
2036/**
2037 * wma_get_stats_req() - get stats request
2038 * @handle: wma handle
2039 * @get_stats_param: stats params
2040 *
2041 * Return: none
2042 */
2043void wma_get_stats_req(WMA_HANDLE handle,
2044 tAniGetPEStatsReq *get_stats_param)
2045{
2046 tp_wma_handle wma_handle = (tp_wma_handle) handle;
2047 struct wma_txrx_node *node;
Govind Singh4863da42016-03-08 11:45:00 +05302048 struct pe_stats_req cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05302050
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051
2052 WMA_LOGD("%s: Enter", __func__);
2053 node = &wma_handle->interfaces[get_stats_param->sessionId];
2054 if (node->stats_rsp) {
2055 pGetPEStatsRspParams = node->stats_rsp;
2056 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
2057 pGetPEStatsRspParams->statsMask ==
2058 get_stats_param->statsMask) {
2059 WMA_LOGI("Stats for staId %d with stats mask %d "
2060 "is pending.... ignore new request",
2061 get_stats_param->staId,
2062 get_stats_param->statsMask);
2063 goto end;
2064 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302065 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 node->stats_rsp = NULL;
2067 node->fw_stats_set = 0;
2068 }
2069 }
2070
2071 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
2072 if (!pGetPEStatsRspParams)
2073 goto end;
2074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 node->fw_stats_set = 0;
2076 node->stats_rsp = pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05302077
2078 cmd.session_id = get_stats_param->sessionId;
2079 if (wmi_unified_get_stats_cmd(wma_handle->wmi_handle, &cmd,
2080 node->bssid)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002081
2082 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
2083 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 goto failed;
2085 }
2086
2087 goto end;
2088failed:
2089
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302090 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002091 node->stats_rsp = NULL;
2092 /* send response to UMAC */
2093 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
2094 0);
2095end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302096 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002097 WMA_LOGD("%s: Exit", __func__);
2098 return;
2099}
2100
2101/**
2102 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
2103 * @vdev_id: vdev id
2104 * @buffer_size: size of buffer
2105 *
2106 * Return: none
2107 */
2108void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
2109{
2110 tp_wma_handle wma;
2111 struct beacon_info *beacon;
2112 uint8_t *buf;
2113 uint32_t buf_size;
2114
Anurag Chouhan6d760662016-02-20 16:05:43 +05302115 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 if (!wma) {
2117 WMA_LOGE("%s: Invalid WMA handle", __func__);
2118 return NULL;
2119 }
2120
2121 if (vdev_id >= wma->max_bssid) {
2122 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2123 return NULL;
2124 }
2125
2126 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
2127 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
2128 return NULL;
2129 }
2130
2131 beacon = wma->interfaces[vdev_id].beacon;
2132
2133 if (!beacon) {
2134 WMA_LOGE("%s: beacon invalid", __func__);
2135 return NULL;
2136 }
2137
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302138 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139
Nirav Shahcbc6d722016-03-01 16:24:53 +05302140 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302141 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142
2143 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302144 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
2146 return NULL;
2147 }
2148
Nirav Shahcbc6d722016-03-01 16:24:53 +05302149 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002150
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302151 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002152
2153 if (buffer_size)
2154 *buffer_size = buf_size;
2155
2156 return buf;
2157}
2158
2159/**
2160 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
2161 * @vdev_id: vdev id
2162 *
2163 * Return: mac address
2164 */
2165uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
2166{
2167 tp_wma_handle wma;
2168
Anurag Chouhan6d760662016-02-20 16:05:43 +05302169 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 if (!wma) {
2171 WMA_LOGE("%s: Invalid WMA handle", __func__);
2172 return NULL;
2173 }
2174
2175 if (vdev_id >= wma->max_bssid) {
2176 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2177 return NULL;
2178 }
2179
2180 return wma->interfaces[vdev_id].addr;
2181}
2182
2183/**
2184 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
2185 * @vdev_id: vdev id
2186 *
2187 * Return: entry from vdev table
2188 */
2189struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
2190{
2191 tp_wma_handle wma;
2192
Anurag Chouhan6d760662016-02-20 16:05:43 +05302193 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 if (!wma) {
2195 WMA_LOGE("%s: Invalid WMA handle", __func__);
2196 return NULL;
2197 }
2198
2199 if (vdev_id >= wma->max_bssid) {
2200 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2201 return NULL;
2202 }
2203
2204 return &wma->interfaces[vdev_id];
2205}
2206
2207/**
2208 * wma_is_vdev_up() - return whether a vdev is up
2209 * @vdev_id: vdev id
2210 *
2211 * Return: true if the vdev is up, false otherwise
2212 */
2213bool wma_is_vdev_up(uint8_t vdev_id)
2214{
2215 struct wma_txrx_node *vdev = wma_get_interface_by_vdev_id(vdev_id);
2216 if (vdev)
2217 return vdev->vdev_up;
2218 else
2219 return false;
2220}
2221
2222#if defined(QCA_WIFI_FTM)
2223/**
2224 * wma_utf_rsp() - utf response
2225 * @wma_handle: wma handle
2226 * @payload: payload
2227 * @len: length of payload
2228 *
2229 * Return: 0 for success or error code
2230 */
2231int wma_utf_rsp(tp_wma_handle wma_handle, uint8_t **payload, uint32_t *len)
2232{
2233 int ret = -1;
2234 uint32_t payload_len;
2235
2236 payload_len = wma_handle->utf_event_info.length;
2237 if (payload_len) {
2238 ret = 0;
2239
2240 /*
2241 * The first 4 bytes holds the payload size
2242 * and the actual payload sits next to it
2243 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302244 *payload = (uint8_t *) qdf_mem_malloc((uint32_t) payload_len
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002245 + sizeof(A_UINT32));
2246 *(A_UINT32 *) &(*payload[0]) =
2247 wma_handle->utf_event_info.length;
2248 memcpy(*payload + sizeof(A_UINT32),
2249 wma_handle->utf_event_info.data, payload_len);
2250 wma_handle->utf_event_info.length = 0;
2251 *len = payload_len;
2252 }
2253
2254 return ret;
2255}
2256
2257/**
2258 * wma_post_ftm_response() - post ftm response to upper layer
2259 * @wma_handle: wma handle
2260 *
2261 * Return: none
2262 */
2263static void wma_post_ftm_response(tp_wma_handle wma_handle)
2264{
2265 int ret;
2266 uint8_t *payload;
2267 uint32_t data_len;
2268 cds_msg_t msg = { 0 };
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302269 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270
2271 ret = wma_utf_rsp(wma_handle, &payload, &data_len);
2272
2273 if (ret) {
2274 return;
2275 }
2276
2277 sys_build_message_header(SYS_MSG_ID_FTM_RSP, &msg);
2278 msg.bodyptr = payload;
2279 msg.bodyval = 0;
2280
2281 status = cds_mq_post_message(CDS_MQ_ID_SYS, &msg);
2282
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302283 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284 WMA_LOGE("failed to post ftm response to SYS");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302285 qdf_mem_free(payload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 }
2287}
2288
2289/**
2290 * wma_process_utf_event() - process utf event
2291 * @handle: wma handle
2292 * @datap: data buffer
2293 * @dataplen: data length
2294 *
2295 * Return: 0 for success or error code
2296 */
2297static int
2298wma_process_utf_event(WMA_HANDLE handle, uint8_t *datap, uint32_t dataplen)
2299{
2300 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05302301 struct seg_hdr_info segHdrInfo;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 uint8_t totalNumOfSegments, currentSeq;
2303 WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf;
2304 uint8_t *data;
2305 uint32_t datalen;
2306
2307 param_buf = (WMI_PDEV_UTF_EVENTID_param_tlvs *) datap;
2308 if (!param_buf) {
2309 WMA_LOGE("Get NULL point message from FW");
2310 return -EINVAL;
2311 }
2312 data = param_buf->data;
2313 datalen = param_buf->num_data;
2314
Govind Singhd76a5b02016-03-08 15:12:14 +05302315 segHdrInfo = *(struct seg_hdr_info *) &(data[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316
2317 wma_handle->utf_event_info.currentSeq = (segHdrInfo.segmentInfo & 0xF);
2318
2319 currentSeq = (segHdrInfo.segmentInfo & 0xF);
2320 totalNumOfSegments = (segHdrInfo.segmentInfo >> 4) & 0xF;
2321
2322 datalen = datalen - sizeof(segHdrInfo);
2323
2324 if (currentSeq == 0) {
2325 wma_handle->utf_event_info.expectedSeq = 0;
2326 wma_handle->utf_event_info.offset = 0;
2327 } else {
2328 if (wma_handle->utf_event_info.expectedSeq != currentSeq)
2329 WMA_LOGE("Mismatch in expecting seq expected"
2330 " Seq %d got seq %d",
2331 wma_handle->utf_event_info.expectedSeq,
2332 currentSeq);
2333 }
2334
2335 memcpy(&wma_handle->utf_event_info.
2336 data[wma_handle->utf_event_info.offset],
2337 &data[sizeof(segHdrInfo)], datalen);
2338 wma_handle->utf_event_info.offset =
2339 wma_handle->utf_event_info.offset + datalen;
2340 wma_handle->utf_event_info.expectedSeq++;
2341
2342 if (wma_handle->utf_event_info.expectedSeq == totalNumOfSegments) {
2343 if (wma_handle->utf_event_info.offset != segHdrInfo.len)
2344 WMA_LOGE("All segs received total len mismatch.."
2345 " len %zu total len %d",
2346 wma_handle->utf_event_info.offset,
2347 segHdrInfo.len);
2348
2349 wma_handle->utf_event_info.length =
2350 wma_handle->utf_event_info.offset;
2351 }
2352
2353 wma_post_ftm_response(wma_handle);
2354
2355 return 0;
2356}
2357
2358/**
2359 * wma_utf_detach() - utf detach
2360 * @wma_handle: wma handle
2361 *
2362 * Return: none
2363 */
2364void wma_utf_detach(tp_wma_handle wma_handle)
2365{
2366 if (wma_handle->utf_event_info.data) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302367 qdf_mem_free(wma_handle->utf_event_info.data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 wma_handle->utf_event_info.data = NULL;
2369 wma_handle->utf_event_info.length = 0;
2370 wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
2371 WMI_PDEV_UTF_EVENTID);
2372 }
2373}
2374
2375/**
2376 * wma_utf_attach() - utf attach
2377 * @wma_handle: wma handle
2378 *
2379 * Return: none
2380 */
2381void wma_utf_attach(tp_wma_handle wma_handle)
2382{
2383 int ret;
2384
2385 wma_handle->utf_event_info.data = (unsigned char *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302386 qdf_mem_malloc(MAX_UTF_EVENT_LENGTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387 wma_handle->utf_event_info.length = 0;
2388
2389 ret = wmi_unified_register_event_handler(wma_handle->wmi_handle,
2390 WMI_PDEV_UTF_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05302391 wma_process_utf_event,
2392 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393
2394 if (ret)
2395 WMA_LOGP("%s: Failed to register UTF event callback", __func__);
2396}
2397
2398/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002399 * wma_utf_cmd() - utf command
2400 * @wma_handle: wma handle
2401 * @data: data
2402 * @len: length
2403 *
Govind Singhd76a5b02016-03-08 15:12:14 +05302404 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 */
Govind Singhd76a5b02016-03-08 15:12:14 +05302406QDF_STATUS wma_utf_cmd(tp_wma_handle wma_handle, uint8_t *data, uint16_t len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002407{
Govind Singhd76a5b02016-03-08 15:12:14 +05302408 struct pdev_utf_params param = {0};
2409
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410 wma_handle->utf_event_info.length = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05302411 param.utf_payload = data;
2412 param.len = len;
2413
2414 return wmi_unified_pdev_utf_cmd_send(wma_handle->wmi_handle, &param,
2415 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416}
2417
2418/**
2419 * wma_process_ftm_command() - process ftm command
2420 * @wma_handle: wma handle
2421 * @msg_buffer: message buffer
2422 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302423 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302425QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426wma_process_ftm_command(tp_wma_handle wma_handle,
2427 struct ar6k_testmode_cmd_data *msg_buffer)
2428{
2429 uint8_t *data = NULL;
2430 uint16_t len = 0;
2431 int ret;
2432
2433 if (!msg_buffer)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302434 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435
Anurag Chouhan6d760662016-02-20 16:05:43 +05302436 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 WMA_LOGE("FTM command issued in non-FTM mode");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302438 qdf_mem_free(msg_buffer->data);
2439 qdf_mem_free(msg_buffer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302440 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 }
2442
2443 data = msg_buffer->data;
2444 len = msg_buffer->len;
2445
2446 ret = wma_utf_cmd(wma_handle, data, len);
2447
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302448 qdf_mem_free(msg_buffer->data);
2449 qdf_mem_free(msg_buffer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450
2451 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302452 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302454 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455}
2456#endif /* QCA_WIFI_FTM */
2457
2458/**
2459 * wma_get_wcnss_software_version() - get wcnss software version
2460 * @p_cds_gctx: cds context
2461 * @pVersion: version pointer
2462 * @versionBufferSize: buffer size
2463 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302464 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302466QDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 uint8_t *pVersion,
2468 uint32_t versionBufferSize)
2469{
2470 tp_wma_handle wma_handle;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302471 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472
2473 if (NULL == wma_handle) {
2474 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302475 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 }
2477
2478 snprintf(pVersion, versionBufferSize, "%x",
2479 (unsigned int)wma_handle->target_fw_version);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302480 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481}
2482
2483/**
2484 * wma_get_tx_rx_ss_from_config() - Get Tx/Rx spatial stream from HW mode config
2485 * @mac_ss: Config which indicates the HW mode as per 'hw_mode_ss_config'
2486 * @tx_ss: Contains the Tx spatial stream
2487 * @rx_ss: Contains the Rx spatial stream
2488 *
2489 * Returns the number of spatial streams of Tx and Rx
2490 *
2491 * Return: None
2492 */
2493void wma_get_tx_rx_ss_from_config(enum hw_mode_ss_config mac_ss,
2494 uint32_t *tx_ss,
2495 uint32_t *rx_ss)
2496{
2497 switch (mac_ss) {
2498 case HW_MODE_SS_0x0:
2499 *tx_ss = 0;
2500 *rx_ss = 0;
2501 break;
2502 case HW_MODE_SS_1x1:
2503 *tx_ss = 1;
2504 *rx_ss = 1;
2505 break;
2506 case HW_MODE_SS_2x2:
2507 *tx_ss = 2;
2508 *rx_ss = 2;
2509 break;
2510 case HW_MODE_SS_3x3:
2511 *tx_ss = 3;
2512 *rx_ss = 3;
2513 break;
2514 case HW_MODE_SS_4x4:
2515 *tx_ss = 4;
2516 *rx_ss = 4;
2517 break;
2518 default:
2519 *tx_ss = 0;
2520 *rx_ss = 0;
2521 }
2522}
2523
2524/**
2525 * wma_get_matching_hw_mode_index() - Get matching HW mode index
2526 * @wma: WMA handle
2527 * @mac0_tx_ss: Number of tx spatial streams of MAC0
2528 * @mac0_rx_ss: Number of rx spatial streams of MAC0
2529 * @mac0_bw: Bandwidth of MAC0 of type 'hw_mode_bandwidth'
2530 * @mac1_tx_ss: Number of tx spatial streams of MAC1
2531 * @mac1_rx_ss: Number of rx spatial streams of MAC1
2532 * @mac1_bw: Bandwidth of MAC1 of type 'hw_mode_bandwidth'
2533 * @dbs: DBS capability of type 'hw_mode_dbs_capab'
2534 * @dfs: Agile DFS capability of type 'hw_mode_agile_dfs_capab'
2535 *
2536 * Fetches the HW mode index corresponding to the HW mode provided
2537 *
2538 * Return: Positive hw mode index in case a match is found or a negative
2539 * value, otherwise
2540 */
2541static int8_t wma_get_matching_hw_mode_index(tp_wma_handle wma,
2542 uint32_t mac0_tx_ss, uint32_t mac0_rx_ss,
2543 enum hw_mode_bandwidth mac0_bw,
2544 uint32_t mac1_tx_ss, uint32_t mac1_rx_ss,
2545 enum hw_mode_bandwidth mac1_bw,
2546 enum hw_mode_dbs_capab dbs,
2547 enum hw_mode_agile_dfs_capab dfs)
2548{
2549 uint32_t i;
2550 uint32_t t_mac0_tx_ss, t_mac0_rx_ss, t_mac0_bw;
2551 uint32_t t_mac1_tx_ss, t_mac1_rx_ss, t_mac1_bw;
2552 uint32_t dbs_mode, agile_dfs_mode;
2553 int8_t found = -EINVAL;
2554
2555 if (!wma) {
2556 WMA_LOGE("%s: Invalid WMA handle", __func__);
2557 return found;
2558 }
2559
2560 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2561 t_mac0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(
2562 wma->hw_mode.hw_mode_list[i]);
2563 if (t_mac0_tx_ss != mac0_tx_ss)
2564 continue;
2565
2566 t_mac0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(
2567 wma->hw_mode.hw_mode_list[i]);
2568 if (t_mac0_rx_ss != mac0_rx_ss)
2569 continue;
2570
2571 t_mac0_bw = WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET(
2572 wma->hw_mode.hw_mode_list[i]);
2573 if (t_mac0_bw != mac0_bw)
2574 continue;
2575
2576 t_mac1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(
2577 wma->hw_mode.hw_mode_list[i]);
2578 if (t_mac1_tx_ss != mac1_tx_ss)
2579 continue;
2580
2581 t_mac1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(
2582 wma->hw_mode.hw_mode_list[i]);
2583 if (t_mac1_rx_ss != mac1_rx_ss)
2584 continue;
2585
2586 t_mac1_bw = WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET(
2587 wma->hw_mode.hw_mode_list[i]);
2588 if (t_mac1_bw != mac1_bw)
2589 continue;
2590
2591 dbs_mode = WMI_DBS_HW_MODE_DBS_MODE_GET(
2592 wma->hw_mode.hw_mode_list[i]);
2593 if (dbs_mode != dbs)
2594 continue;
2595
2596 agile_dfs_mode = WMI_DBS_HW_MODE_AGILE_DFS_GET(
2597 wma->hw_mode.hw_mode_list[i]);
2598 if (agile_dfs_mode != dfs)
2599 continue;
2600
2601 found = i;
2602 WMA_LOGI("%s: hw_mode index %d found",
2603 __func__, i);
2604 break;
2605 }
2606 return found;
2607}
2608
2609/**
2610 * wma_get_hw_mode_from_dbs_hw_list() - Get hw_mode index
2611 * @mac0_ss: MAC0 spatial stream configuration
2612 * @mac0_bw: MAC0 bandwidth configuration
2613 * @mac1_ss: MAC1 spatial stream configuration
2614 * @mac1_bw: MAC1 bandwidth configuration
2615 * @dbs: HW DBS capability
2616 * @dfs: HW Agile DFS capability
2617 *
2618 * Get the HW mode index corresponding to the HW modes spatial stream,
2619 * bandwidth, DBS and Agile DFS capability
2620 *
2621 * Return: Index number if a match is found or -negative value if not found
2622 */
2623int8_t wma_get_hw_mode_idx_from_dbs_hw_list(enum hw_mode_ss_config mac0_ss,
2624 enum hw_mode_bandwidth mac0_bw,
2625 enum hw_mode_ss_config mac1_ss,
2626 enum hw_mode_bandwidth mac1_bw,
2627 enum hw_mode_dbs_capab dbs,
2628 enum hw_mode_agile_dfs_capab dfs)
2629{
2630 tp_wma_handle wma;
2631 uint32_t mac0_tx_ss, mac0_rx_ss;
2632 uint32_t mac1_tx_ss, mac1_rx_ss;
2633
Anurag Chouhan6d760662016-02-20 16:05:43 +05302634 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002635 if (!wma) {
2636 WMA_LOGE("%s: Invalid WMA handle", __func__);
2637 return -EINVAL;
2638 }
2639
2640 wma_get_tx_rx_ss_from_config(mac0_ss, &mac0_tx_ss, &mac0_rx_ss);
2641 wma_get_tx_rx_ss_from_config(mac1_ss, &mac1_tx_ss, &mac1_rx_ss);
2642
2643 WMA_LOGI("%s: MAC0: TxSS=%d, RxSS=%d, BW=%d",
2644 __func__, mac0_tx_ss, mac0_rx_ss, mac0_bw);
2645 WMA_LOGI("%s: MAC1: TxSS=%d, RxSS=%d, BW=%d",
2646 __func__, mac1_tx_ss, mac1_rx_ss, mac1_bw);
2647 WMA_LOGI("%s: DBS capab=%d, Agile DFS capab=%d",
2648 __func__, dbs, dfs);
2649
2650 return wma_get_matching_hw_mode_index(wma, mac0_tx_ss, mac0_rx_ss,
2651 mac0_bw,
2652 mac1_tx_ss, mac1_rx_ss,
2653 mac1_bw,
2654 dbs, dfs);
2655}
2656
2657/**
2658 * wma_get_hw_mode_from_idx() - Get HW mode based on index
2659 * @idx: HW mode index
2660 * @hw_mode: HW mode params
2661 *
2662 * Fetches the HW mode parameters
2663 *
2664 * Return: Success if hw mode is obtained and the hw mode params
2665 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302666QDF_STATUS wma_get_hw_mode_from_idx(uint32_t idx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667 struct sir_hw_mode_params *hw_mode)
2668{
2669 tp_wma_handle wma;
2670 uint32_t param;
2671
Anurag Chouhan6d760662016-02-20 16:05:43 +05302672 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 if (!wma) {
2674 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302675 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 }
2677
2678 if (idx > wma->num_dbs_hw_modes) {
2679 WMA_LOGE("%s: Invalid index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302680 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 }
2682
Mahesh Kumar Kalikot Veetild43e1652015-11-02 15:35:10 -08002683 if (!wma->num_dbs_hw_modes) {
2684 WMA_LOGE("%s: No dbs hw modes available", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302685 return QDF_STATUS_E_FAILURE;
Mahesh Kumar Kalikot Veetild43e1652015-11-02 15:35:10 -08002686 }
2687
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 param = wma->hw_mode.hw_mode_list[idx];
2689
2690 hw_mode->mac0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param);
2691 hw_mode->mac0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(param);
2692 hw_mode->mac0_bw = WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET(param);
2693 hw_mode->mac1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(param);
2694 hw_mode->mac1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(param);
2695 hw_mode->mac1_bw = WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET(param);
2696 hw_mode->dbs_cap = WMI_DBS_HW_MODE_DBS_MODE_GET(param);
2697 hw_mode->agile_dfs_cap = WMI_DBS_HW_MODE_AGILE_DFS_GET(param);
2698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302699 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700}
2701
2702/**
2703 * wma_get_num_dbs_hw_modes() - Get number of HW mode
2704 *
2705 * Fetches the number of DBS HW modes returned by the FW
2706 *
2707 * Return: Negative value on error or returns the number of DBS HW modes
2708 */
2709int8_t wma_get_num_dbs_hw_modes(void)
2710{
2711 tp_wma_handle wma;
2712
Anurag Chouhan6d760662016-02-20 16:05:43 +05302713 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 if (!wma) {
2715 WMA_LOGE("%s: Invalid WMA handle", __func__);
2716 return -EINVAL;
2717 }
2718 return wma->num_dbs_hw_modes;
2719}
2720
2721/**
2722 * wma_is_hw_dbs_capable() - Check if HW is DBS capable
2723 *
2724 * Checks if the HW is DBS capable
2725 *
2726 * Return: true if the HW is DBS capable
2727 */
2728bool wma_is_hw_dbs_capable(void)
2729{
2730 tp_wma_handle wma;
2731 uint32_t param, i, found = 0;
2732
Anurag Chouhan6d760662016-02-20 16:05:43 +05302733 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002734 if (!wma) {
2735 WMA_LOGE("%s: Invalid WMA handle", __func__);
2736 return false;
2737 }
2738
2739 if (!wma_is_dbs_enable()) {
2740 WMA_LOGI("%s: DBS is disabled", __func__);
2741 return false;
2742 }
2743
2744 WMA_LOGI("%s: DBS service bit map: %d", __func__,
2745 WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2746 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT));
2747
2748 /* The agreement with FW is that: To know if the target is DBS
2749 * capable, DBS needs to be supported both in the HW mode list
2750 * and in the service ready event
2751 */
2752 if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2753 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT)))
2754 return false;
2755
2756 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2757 param = wma->hw_mode.hw_mode_list[i];
2758 WMA_LOGI("%s: HW param: %x", __func__, param);
2759 if (WMI_DBS_HW_MODE_DBS_MODE_GET(param)) {
2760 WMA_LOGI("%s: HW (%d) is DBS capable", __func__, i);
2761 found = 1;
2762 break;
2763 }
2764 }
2765
2766 if (found)
2767 return true;
2768
2769 return false;
2770}
2771
2772/**
2773 * wma_is_hw_agile_dfs_capable() - Check if HW is agile DFS capable
2774 *
2775 * Checks if the HW is agile DFS capable
2776 *
2777 * Return: true if the HW is agile DFS capable
2778 */
2779bool wma_is_hw_agile_dfs_capable(void)
2780{
2781 tp_wma_handle wma;
2782 uint32_t param, i, found = 0;
2783
Anurag Chouhan6d760662016-02-20 16:05:43 +05302784 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785 if (!wma) {
2786 WMA_LOGE("%s: Invalid WMA handle", __func__);
2787 return false;
2788 }
2789
2790 if (!wma_is_agile_dfs_enable()) {
2791 WMA_LOGI("%s: Agile DFS is disabled", __func__);
2792 return false;
2793 }
2794
2795 WMA_LOGI("%s: DBS service bit map: %d", __func__,
2796 WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2797 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT));
2798
2799 /* The agreement with FW is that to know if the target is Agile DFS
2800 * capable, DBS needs to be supported in the service bit map and
2801 * Agile DFS needs to be supported in the HW mode list
2802 */
2803 if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2804 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT)))
2805 return false;
2806
2807 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2808 param = wma->hw_mode.hw_mode_list[i];
2809 WMA_LOGI("%s: HW param: %x", __func__, param);
2810 if (WMI_DBS_HW_MODE_AGILE_DFS_GET(param)) {
2811 WMA_LOGI("%s: HW %d is agile DFS capable",
2812 __func__, i);
2813 found = 1;
2814 break;
2815 }
2816 }
2817
2818 if (found)
2819 return true;
2820
2821 return false;
2822}
2823
2824/**
2825 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
2826 * @vdev_id: VDEV whose MAC ID is required
2827 *
2828 * Get MAC id corresponding to a vdev id from the WMA structure
2829 *
2830 * Return: Negative value on failure and MAC id on success
2831 */
2832int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
2833{
2834 tp_wma_handle wma;
2835
Anurag Chouhan6d760662016-02-20 16:05:43 +05302836 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837 if (!wma) {
2838 WMA_LOGE("%s: Invalid WMA handle", __func__);
2839 return -EINVAL;
2840 }
2841
2842 if (wma->interfaces)
2843 return wma->interfaces[vdev_id].mac_id;
2844
2845 return -EINVAL;
2846}
2847
2848/**
2849 * wma_get_old_and_new_hw_index() - Get the old and new HW index
2850 * @old_hw_mode_index: Value at this pointer contains the old HW mode index
2851 * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX
2852 * @new_hw_mode_index: Value at this pointer contains the new HW mode index
2853 * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX
2854 *
2855 * Get the old and new HW index configured in the driver
2856 *
2857 * Return: Failure in case the HW mode indices cannot be fetched and Success
2858 * otherwise. When no HW mode transition has happened the values of
2859 * old_hw_mode_index and new_hw_mode_index will be the same.
2860 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302861QDF_STATUS wma_get_old_and_new_hw_index(uint32_t *old_hw_mode_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 uint32_t *new_hw_mode_index)
2863{
2864 tp_wma_handle wma;
2865
Anurag Chouhan6d760662016-02-20 16:05:43 +05302866 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867 if (!wma) {
2868 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302869 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 }
2871
2872 *old_hw_mode_index = wma->old_hw_mode_index;
2873 *new_hw_mode_index = wma->new_hw_mode_index;
2874
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302875 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876}
2877
2878/**
2879 * wma_update_intf_hw_mode_params() - Update WMA params
2880 * @vdev_id: VDEV id whose params needs to be updated
2881 * @mac_id: MAC id to be updated
2882 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
2883 *
2884 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
2885 *
2886 * Return: None
2887 */
2888void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
2889 uint32_t cfgd_hw_mode_index)
2890{
2891 tp_wma_handle wma;
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002892 uint32_t param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893
Anurag Chouhan6d760662016-02-20 16:05:43 +05302894 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 if (!wma) {
2896 WMA_LOGE("%s: Invalid WMA handle", __func__);
2897 return;
2898 }
2899
2900 if (!wma->interfaces) {
2901 WMA_LOGE("%s: Interface is NULL", __func__);
2902 return;
2903 }
2904
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002905 if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) {
2906 WMA_LOGE("%s: Invalid index", __func__);
2907 return;
2908 }
2909
2910 param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 wma->interfaces[vdev_id].mac_id = mac_id;
2912 if (mac_id == 0) {
2913 wma->interfaces[vdev_id].tx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002914 WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 wma->interfaces[vdev_id].rx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002916 WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 } else {
2918 wma->interfaces[vdev_id].tx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002919 WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 wma->interfaces[vdev_id].rx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002921 WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 }
2923}
2924
2925/**
2926 * wma_get_dbs_hw_modes() - Get the DBS HW modes for userspace
2927 * @one_by_one_dbs: 1x1 DBS capability of HW
2928 * @two_by_two_dbs: 2x2 DBS capability of HW
2929 *
2930 * Provides the DBS HW mode capability such as whether
2931 * 1x1 DBS, 2x2 DBS is supported by the HW or not.
2932 *
2933 * Return: Failure in case of error and 0 on success
2934 * one_by_one_dbs/two_by_two_dbs will be false,
2935 * if they are not supported.
2936 * one_by_one_dbs/two_by_two_dbs will be true,
2937 * if they are supported.
2938 * false values of one_by_one_dbs/two_by_two_dbs,
2939 * indicate DBS is disabled
2940 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302941QDF_STATUS wma_get_dbs_hw_modes(bool *one_by_one_dbs, bool *two_by_two_dbs)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942{
2943 tp_wma_handle wma;
2944 uint32_t i;
2945 int8_t found_one_by_one = -EINVAL, found_two_by_two = -EINVAL;
2946 uint32_t conf1_tx_ss, conf1_rx_ss;
2947 uint32_t conf2_tx_ss, conf2_rx_ss;
2948
2949 *one_by_one_dbs = false;
2950 *two_by_two_dbs = false;
2951
2952 if (wma_is_hw_dbs_capable() == false) {
2953 WMA_LOGE("%s: HW is not DBS capable", __func__);
2954 /* Caller will understand that DBS is disabled */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302955 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002956
2957 }
2958
Anurag Chouhan6d760662016-02-20 16:05:43 +05302959 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 if (!wma) {
2961 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302962 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 }
2964
2965 /* To check 1x1 capability */
2966 wma_get_tx_rx_ss_from_config(HW_MODE_SS_1x1,
2967 &conf1_tx_ss, &conf1_rx_ss);
2968 /* To check 2x2 capability */
2969 wma_get_tx_rx_ss_from_config(HW_MODE_SS_2x2,
2970 &conf2_tx_ss, &conf2_rx_ss);
2971
2972 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2973 uint32_t t_conf0_tx_ss, t_conf0_rx_ss;
2974 uint32_t t_conf1_tx_ss, t_conf1_rx_ss;
2975 uint32_t dbs_mode;
2976
2977 t_conf0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(
2978 wma->hw_mode.hw_mode_list[i]);
2979 t_conf0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(
2980 wma->hw_mode.hw_mode_list[i]);
2981 t_conf1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(
2982 wma->hw_mode.hw_mode_list[i]);
2983 t_conf1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(
2984 wma->hw_mode.hw_mode_list[i]);
2985 dbs_mode = WMI_DBS_HW_MODE_DBS_MODE_GET(
2986 wma->hw_mode.hw_mode_list[i]);
2987
2988 if (((((t_conf0_tx_ss == conf1_tx_ss) &&
2989 (t_conf0_rx_ss == conf1_rx_ss)) ||
2990 ((t_conf1_tx_ss == conf1_tx_ss) &&
2991 (t_conf1_rx_ss == conf1_rx_ss))) &&
2992 (dbs_mode == HW_MODE_DBS)) &&
2993 (found_one_by_one < 0)) {
2994 found_one_by_one = i;
2995 WMA_LOGI("%s: 1x1 hw_mode index %d found",
2996 __func__, i);
2997 /* Once an entry is found, need not check for 1x1
2998 * again
2999 */
3000 continue;
3001 }
3002
3003 if (((((t_conf0_tx_ss == conf2_tx_ss) &&
3004 (t_conf0_rx_ss == conf2_rx_ss)) ||
3005 ((t_conf1_tx_ss == conf2_tx_ss) &&
3006 (t_conf1_rx_ss == conf2_rx_ss))) &&
3007 (dbs_mode == HW_MODE_DBS)) &&
3008 (found_two_by_two < 0)) {
3009 found_two_by_two = i;
3010 WMA_LOGI("%s: 2x2 hw_mode index %d found",
3011 __func__, i);
3012 /* Once an entry is found, need not check for 2x2
3013 * again
3014 */
3015 continue;
3016 }
3017 }
3018
3019 if (found_one_by_one >= 0)
3020 *one_by_one_dbs = true;
3021 if (found_two_by_two >= 0)
3022 *two_by_two_dbs = true;
3023
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303024 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025}
3026
3027/**
3028 * wma_get_current_hw_mode() - Get current HW mode params
3029 * @hw_mode: HW mode parameters
3030 *
3031 * Provides the current HW mode parameters if the HW mode is initialized
3032 * in the driver
3033 *
3034 * Return: Success if the current HW mode params are successfully populated
3035 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303036QDF_STATUS wma_get_current_hw_mode(struct sir_hw_mode_params *hw_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303038 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 uint32_t old_hw_index = 0, new_hw_index = 0;
3040
3041 WMA_LOGI("%s: Get the current hw mode", __func__);
3042
3043 status = wma_get_old_and_new_hw_index(&old_hw_index,
3044 &new_hw_index);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303045 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046 WMA_LOGE("%s: Failed to get HW mode index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303047 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 }
3049
3050 if (new_hw_index == WMA_DEFAULT_HW_MODE_INDEX) {
3051 WMA_LOGE("%s: HW mode is not yet initialized", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303052 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053 }
3054
3055 status = wma_get_hw_mode_from_idx(new_hw_index, hw_mode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303056 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 WMA_LOGE("%s: Failed to get HW mode index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303058 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303060 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061}
3062
3063/**
3064 * wma_is_dbs_enable() - Check if master DBS control is enabled
3065 *
3066 * Checks if the master DBS control is enabled. This will be used
3067 * to override any other DBS capability
3068 *
3069 * Return: True if master DBS control is enabled
3070 */
3071bool wma_is_dbs_enable(void)
3072{
3073 tp_wma_handle wma;
3074
3075 if (wma_is_dual_mac_disabled_in_ini())
3076 return false;
3077
Anurag Chouhan6d760662016-02-20 16:05:43 +05303078 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003079 if (!wma) {
3080 WMA_LOGE("%s: Invalid WMA handle", __func__);
3081 return false;
3082 }
3083
3084 WMA_LOGD("%s: DBS=%d", __func__,
3085 WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config));
3086
3087 if (WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config))
3088 return true;
3089
3090 return false;
3091}
3092
3093/**
3094 * wma_is_agile_dfs_enable() - Check if master Agile DFS control is enabled
3095 *
3096 * Checks if the master Agile DFS control is enabled. This will be used
3097 * to override any other Agile DFS capability
3098 *
3099 * Return: True if master Agile DFS control is enabled
3100 */
3101bool wma_is_agile_dfs_enable(void)
3102{
3103 tp_wma_handle wma;
3104
3105 if (wma_is_dual_mac_disabled_in_ini())
3106 return false;
3107
Anurag Chouhan6d760662016-02-20 16:05:43 +05303108 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 if (!wma) {
3110 WMA_LOGE("%s: Invalid WMA handle", __func__);
3111 return false;
3112 }
3113
3114 WMA_LOGD("%s: DFS=%d Single mac with DFS=%d", __func__,
3115 WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(
3116 wma->dual_mac_cfg.cur_fw_mode_config),
3117 WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(
3118 wma->dual_mac_cfg.cur_scan_config));
3119
3120 if ((WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(
3121 wma->dual_mac_cfg.cur_fw_mode_config)) &&
3122 (WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(
3123 wma->dual_mac_cfg.cur_scan_config)))
3124 return true;
3125
3126 return false;
3127}
3128
3129/**
3130 * wma_get_updated_scan_config() - Get the updated scan configuration
3131 * @scan_config: Pointer containing the updated scan config
3132 * @dbs_scan: 0 or 1 indicating if DBS scan needs to be enabled/disabled
3133 * @dbs_plus_agile_scan: 0 or 1 indicating if DBS plus agile scan needs to be
3134 * enabled/disabled
3135 * @single_mac_scan_with_dfs: 0 or 1 indicating if single MAC scan with DFS
3136 * needs to be enabled/disabled
3137 *
3138 * Takes the current scan configuration and set the necessary scan config
3139 * bits to either 0/1 and provides the updated value to the caller who
3140 * can use this to pass it on to the FW
3141 *
3142 * Return: 0 on success
3143 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303144QDF_STATUS wma_get_updated_scan_config(uint32_t *scan_config,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145 bool dbs_scan,
3146 bool dbs_plus_agile_scan,
3147 bool single_mac_scan_with_dfs)
3148{
3149 tp_wma_handle wma;
3150
Anurag Chouhan6d760662016-02-20 16:05:43 +05303151 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152 if (!wma) {
3153 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303154 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155 }
3156 *scan_config = wma->dual_mac_cfg.cur_scan_config;
3157
3158 WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_SET(*scan_config, dbs_scan);
3159 WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_SET(*scan_config,
3160 dbs_plus_agile_scan);
3161 WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_SET(*scan_config,
3162 single_mac_scan_with_dfs);
3163
3164 WMA_LOGD("%s: *scan_config:%x ", __func__, *scan_config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166}
3167
3168/**
3169 * wma_get_updated_fw_mode_config() - Get the updated fw mode configuration
3170 * @fw_mode_config: Pointer containing the updated fw mode config
3171 * @dbs: 0 or 1 indicating if DBS needs to be enabled/disabled
3172 * @agile_dfs: 0 or 1 indicating if agile DFS needs to be enabled/disabled
3173 *
3174 * Takes the current fw mode configuration and set the necessary fw mode config
3175 * bits to either 0/1 and provides the updated value to the caller who
3176 * can use this to pass it on to the FW
3177 *
3178 * Return: 0 on success
3179 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303180QDF_STATUS wma_get_updated_fw_mode_config(uint32_t *fw_mode_config,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003181 bool dbs,
3182 bool agile_dfs)
3183{
3184 tp_wma_handle wma;
3185
Anurag Chouhan6d760662016-02-20 16:05:43 +05303186 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187 if (!wma) {
3188 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303189 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 }
3191 *fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3192
3193 WMI_DBS_FW_MODE_CFG_DBS_SET(*fw_mode_config, dbs);
3194 WMI_DBS_FW_MODE_CFG_AGILE_DFS_SET(*fw_mode_config, agile_dfs);
3195
3196 WMA_LOGD("%s: *fw_mode_config:%x ", __func__, *fw_mode_config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303197 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198}
3199
3200/**
3201 * wma_get_dbs_config() - Get DBS bit
3202 *
3203 * Gets the DBS bit of fw_mode_config_bits
3204 *
3205 * Return: 0 or 1 to indicate the DBS bit
3206 */
3207bool wma_get_dbs_config(void)
3208{
3209 tp_wma_handle wma;
3210 uint32_t fw_mode_config;
3211
3212 if (wma_is_dual_mac_disabled_in_ini())
3213 return false;
3214
Anurag Chouhan6d760662016-02-20 16:05:43 +05303215 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 if (!wma) {
3217 WMA_LOGE("%s: Invalid WMA handle", __func__);
3218 /* We take that it is disabled and proceed */
3219 return false;
3220 }
3221 fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3222
3223 return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config);
3224}
3225
3226/**
3227 * wma_get_agile_dfs_config() - Get Agile DFS bit
3228 *
3229 * Gets the Agile DFS bit of fw_mode_config_bits
3230 *
3231 * Return: 0 or 1 to indicate the Agile DFS bit
3232 */
3233bool wma_get_agile_dfs_config(void)
3234{
3235 tp_wma_handle wma;
3236 uint32_t fw_mode_config;
3237
3238 if (wma_is_dual_mac_disabled_in_ini())
3239 return false;
3240
Anurag Chouhan6d760662016-02-20 16:05:43 +05303241 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242 if (!wma) {
3243 WMA_LOGE("%s: Invalid WMA handle", __func__);
3244 /* We take that it is disabled and proceed */
3245 return false;
3246 }
3247 fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3248
3249 return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config);
3250}
3251
3252/**
3253 * wma_get_dbs_scan_config() - Get DBS scan bit
3254 *
3255 * Gets the DBS scan bit of concurrent_scan_config_bits
3256 *
3257 * Return: 0 or 1 to indicate the DBS scan bit
3258 */
3259bool wma_get_dbs_scan_config(void)
3260{
3261 tp_wma_handle wma;
3262 uint32_t scan_config;
3263
3264 if (wma_is_dual_mac_disabled_in_ini())
3265 return false;
3266
Anurag Chouhan6d760662016-02-20 16:05:43 +05303267 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003268 if (!wma) {
3269 WMA_LOGE("%s: Invalid WMA handle", __func__);
3270 /* We take that it is disabled and proceed */
3271 return false;
3272 }
3273 scan_config = wma->dual_mac_cfg.cur_scan_config;
3274
3275 return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config);
3276}
3277
3278/**
3279 * wma_get_dbs_plus_agile_scan_config() - Get DBS plus agile scan bit
3280 *
3281 * Gets the DBS plus agile scan bit of concurrent_scan_config_bits
3282 *
3283 * Return: 0 or 1 to indicate the DBS plus agile scan bit
3284 */
3285bool wma_get_dbs_plus_agile_scan_config(void)
3286{
3287 tp_wma_handle wma;
3288 uint32_t scan_config;
3289
3290 if (wma_is_dual_mac_disabled_in_ini())
3291 return false;
3292
Anurag Chouhan6d760662016-02-20 16:05:43 +05303293 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294 if (!wma) {
3295 WMA_LOGE("%s: Invalid WMA handle", __func__);
3296 /* We take that it is disabled and proceed */
3297 return false;
3298 }
3299 scan_config = wma->dual_mac_cfg.cur_scan_config;
3300
3301 return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config);
3302}
3303
3304/**
3305 * wma_get_single_mac_scan_with_dfs_config() - Get Single MAC scan with DFS bit
3306 *
3307 * Gets the Single MAC scan with DFS bit of concurrent_scan_config_bits
3308 *
3309 * Return: 0 or 1 to indicate the Single MAC scan with DFS bit
3310 */
3311bool wma_get_single_mac_scan_with_dfs_config(void)
3312{
3313 tp_wma_handle wma;
3314 uint32_t scan_config;
3315
3316 if (wma_is_dual_mac_disabled_in_ini())
3317 return false;
3318
Anurag Chouhan6d760662016-02-20 16:05:43 +05303319 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003320 if (!wma) {
3321 WMA_LOGE("%s: Invalid WMA handle", __func__);
3322 /* We take that it is disabled and proceed */
3323 return false;
3324 }
3325 scan_config = wma->dual_mac_cfg.cur_scan_config;
3326
3327 return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config);
3328}
3329
3330/**
3331 * wma_is_dual_mac_disabled_in_ini() - Check if dual mac is disabled in INI
3332 *
3333 * Checks if the dual mac feature is disabled in INI
3334 *
3335 * Return: true if the dual mac feature is disabled from INI
3336 */
3337bool wma_is_dual_mac_disabled_in_ini(void)
3338{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303339 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340
3341 if (!mac) {
3342 WMA_LOGE("%s: Invalid mac pointer", __func__);
3343 return true;
3344 }
3345
3346 if (mac->dual_mac_feature_disable)
3347 return true;
3348
3349 return false;
3350}
3351
3352/**
3353 * wma_get_prev_dbs_config() - Get prev DBS bit
3354 *
3355 * Gets the previous DBS bit of fw_mode_config_bits
3356 *
3357 * Return: 0 or 1 to indicate the DBS bit
3358 */
3359bool wma_get_prev_dbs_config(void)
3360{
3361 tp_wma_handle wma;
3362 uint32_t fw_mode_config;
3363
3364 if (wma_is_dual_mac_disabled_in_ini())
3365 return false;
3366
Anurag Chouhan6d760662016-02-20 16:05:43 +05303367 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003368 if (!wma) {
3369 WMA_LOGE("%s: Invalid WMA handle", __func__);
3370 /* We take that it is disabled and proceed */
3371 return false;
3372 }
3373 fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config;
3374
3375 return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config);
3376}
3377
3378/**
3379 * wma_get_prev_agile_dfs_config() - Get prev Agile DFS bit
3380 *
3381 * Gets the previous Agile DFS bit of fw_mode_config_bits
3382 *
3383 * Return: 0 or 1 to indicate the Agile DFS bit
3384 */
3385bool wma_get_prev_agile_dfs_config(void)
3386{
3387 tp_wma_handle wma;
3388 uint32_t fw_mode_config;
3389
3390 if (wma_is_dual_mac_disabled_in_ini())
3391 return false;
3392
Anurag Chouhan6d760662016-02-20 16:05:43 +05303393 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394 if (!wma) {
3395 WMA_LOGE("%s: Invalid WMA handle", __func__);
3396 /* We take that it is disabled and proceed */
3397 return false;
3398 }
3399 fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config;
3400
3401 return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config);
3402}
3403
3404/**
3405 * wma_get_prev_dbs_scan_config() - Get prev DBS scan bit
3406 *
3407 * Gets the previous DBS scan bit of concurrent_scan_config_bits
3408 *
3409 * Return: 0 or 1 to indicate the DBS scan bit
3410 */
3411bool wma_get_prev_dbs_scan_config(void)
3412{
3413 tp_wma_handle wma;
3414 uint32_t scan_config;
3415
3416 if (wma_is_dual_mac_disabled_in_ini())
3417 return false;
3418
Anurag Chouhan6d760662016-02-20 16:05:43 +05303419 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 if (!wma) {
3421 WMA_LOGE("%s: Invalid WMA handle", __func__);
3422 /* We take that it is disabled and proceed */
3423 return false;
3424 }
3425 scan_config = wma->dual_mac_cfg.prev_scan_config;
3426
3427 return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config);
3428}
3429
3430/**
3431 * wma_get_prev_dbs_plus_agile_scan_config() - Get prev DBS plus agile scan bit
3432 *
3433 * Gets the previous DBS plus agile scan bit of concurrent_scan_config_bits
3434 *
3435 * Return: 0 or 1 to indicate the DBS plus agile scan bit
3436 */
3437bool wma_get_prev_dbs_plus_agile_scan_config(void)
3438{
3439 tp_wma_handle wma;
3440 uint32_t scan_config;
3441
3442 if (wma_is_dual_mac_disabled_in_ini())
3443 return false;
3444
Anurag Chouhan6d760662016-02-20 16:05:43 +05303445 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003446 if (!wma) {
3447 WMA_LOGE("%s: Invalid WMA handle", __func__);
3448 /* We take that it is disabled and proceed */
3449 return false;
3450 }
3451 scan_config = wma->dual_mac_cfg.prev_scan_config;
3452
3453 return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config);
3454}
3455
3456/**
3457 * wma_get_prev_single_mac_scan_with_dfs_config() - Get prev Single MAC scan
3458 * with DFS bit
3459 *
3460 * Gets the previous Single MAC scan with DFS bit of concurrent_scan_config_bits
3461 *
3462 * Return: 0 or 1 to indicate the Single MAC scan with DFS bit
3463 */
3464bool wma_get_prev_single_mac_scan_with_dfs_config(void)
3465{
3466 tp_wma_handle wma;
3467 uint32_t scan_config;
3468
3469 if (wma_is_dual_mac_disabled_in_ini())
3470 return false;
3471
Anurag Chouhan6d760662016-02-20 16:05:43 +05303472 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 if (!wma) {
3474 WMA_LOGE("%s: Invalid WMA handle", __func__);
3475 /* We take that it is disabled and proceed */
3476 return false;
3477 }
3478 scan_config = wma->dual_mac_cfg.prev_scan_config;
3479
3480 return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config);
3481}
3482
3483/**
3484 * wma_is_scan_simultaneous_capable() - Check if scan parallelization is
3485 * supported or not
3486 *
3487 * currently scan parallelization feature support is dependent on DBS but
3488 * it can be independent in future.
3489 *
3490 * Return: True if master DBS control is enabled
3491 */
3492bool wma_is_scan_simultaneous_capable(void)
3493{
3494 if (wma_is_hw_dbs_capable())
3495 return true;
3496
3497 return false;
3498}
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003499
3500/**
3501 * wma_get_vht_ch_width - return vht channel width
3502 *
3503 * Return: return vht channel width
3504 */
3505uint32_t wma_get_vht_ch_width(void)
3506{
3507 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303508 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003509
3510 if (NULL == wm_hdl)
3511 return fw_ch_wd;
3512
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07003513 if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003514 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07003515 else if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
3516 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003517
3518 return fw_ch_wd;
3519}
Govind Singhd76a5b02016-03-08 15:12:14 +05303520
3521/**
Krunal Soniaa664da2016-06-15 23:46:40 -07003522 * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
3523 * @mask: given bitmask
3524 *
3525 * This helper function should return number of setbits from bitmask
3526 *
3527 * Return: number of setbits from bitmask
3528 */
3529uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
3530{
3531 uint32_t num_of_setbits = 0;
3532
3533 while (mask) {
3534 mask &= (mask - 1);
3535 num_of_setbits++;
3536 }
3537 return num_of_setbits;
3538}
3539
3540/**
Govind Singhd76a5b02016-03-08 15:12:14 +05303541 * wma_config_debug_module_cmd - set debug log config
3542 * @wmi_handle: wmi layer handle
3543 * @param: debug log parameter
3544 * @val: debug log value
3545 * @module_id_bitmap: debug module id bitmap
3546 * @bitmap_len: debug module bitmap length
3547 *
3548 * Return: QDF_STATUS_SUCCESS for success or error code
3549 */
3550QDF_STATUS
3551wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
3552 A_UINT32 val, A_UINT32 *module_id_bitmap,
3553 A_UINT32 bitmap_len)
3554{
3555 struct dbglog_params dbg_param;
3556 dbg_param.param = param;
3557 dbg_param.val = val;
3558 dbg_param.module_id_bitmap = module_id_bitmap;
3559 dbg_param.bitmap_len = bitmap_len;
3560
3561 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
3562}
Peng Xu8fdaa492016-06-22 10:20:47 -07003563
3564/**
3565 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
3566 *
3567 * This function checks if driver is capable of p2p listen offload
3568 * true: capable of p2p offload
3569 * false: not capable
3570 *
3571 * Return: true - capable, false - not capable
3572 */
3573bool wma_is_p2p_lo_capable(void)
3574{
3575 tp_wma_handle wma;
3576
3577 wma = cds_get_context(QDF_MODULE_ID_WMA);
3578 if (!wma) {
3579 WMA_LOGE("%s: Invalid WMA handle", __func__);
3580 return false;
3581 }
3582
3583 if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
3584 WMI_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT))
3585 return true;
3586
3587 return false;
3588}