blob: 7816236f9c4d028772df16c5a0bcfc9a75c39070 [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#include "wlan_tgt_def_config.h"
46
Nirav Shahcbc6d722016-03-01 16:24:53 +053047#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053048#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053049#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050#include "ol_txrx_peer_find.h"
51
52#include "wma_types.h"
53#include "lim_api.h"
54#include "lim_session_utils.h"
55
56#include "cds_utils.h"
57
58#if !defined(REMOVE_PKT_LOG)
59#include "pktlog_ac.h"
60#endif /* REMOVE_PKT_LOG */
61
62#include "dbglog_host.h"
63#include "csr_api.h"
64#include "ol_fw.h"
65
66#include "dfs.h"
67#include "wma_internal.h"
Chandrasekaran, Manishekar0d814c72015-11-05 10:42:48 +053068#include "cds_concurrency.h"
Govind Singhd76a5b02016-03-08 15:12:14 +053069#include "wmi_unified_param.h"
Naveen Rawatc0c91cd2015-11-05 14:27:37 -080070#include "linux/ieee80211.h"
71
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072/* MCS Based rate table */
73/* HT MCS parameters with Nss = 1 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080074static struct index_data_rate_type mcs_nss1[] = {
75 /* MCS L20 S20 L40 S40 */
76 {0, {65, 72}, {135, 150 } },
77 {1, {130, 144}, {270, 300 } },
78 {2, {195, 217}, {405, 450 } },
79 {3, {260, 289}, {540, 600 } },
80 {4, {390, 433}, {815, 900 } },
81 {5, {520, 578}, {1080, 1200} },
82 {6, {585, 650}, {1215, 1350} },
83 {7, {650, 722}, {1350, 1500} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084};
85
86/* HT MCS parameters with Nss = 2 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080087static struct index_data_rate_type mcs_nss2[] = {
88 /* MCS L20 S20 L40 S40 */
89 {0, {130, 144}, {270, 300 } },
90 {1, {260, 289}, {540, 600 } },
91 {2, {390, 433}, {810, 900 } },
92 {3, {520, 578}, {1080, 1200} },
93 {4, {780, 867}, {1620, 1800} },
94 {5, {1040, 1156}, {2160, 2400} },
95 {6, {1170, 1300}, {2430, 2700} },
96 {7, {1300, 1440}, {2700, 3000} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097};
98
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080099/* MCS Based VHT rate table */
100/* MCS parameters with Nss = 1*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800101static struct index_vht_data_rate_type vht_mcs_nss1[] = {
102 /* MCS L20 S20 L40 S40 L80 S80 */
103 {0, {65, 72 }, {135, 150}, {293, 325} },
104 {1, {130, 144}, {270, 300}, {585, 650} },
105 {2, {195, 217}, {405, 450}, {878, 975} },
106 {3, {260, 289}, {540, 600}, {1170, 1300} },
107 {4, {390, 433}, {810, 900}, {1755, 1950} },
108 {5, {520, 578}, {1080, 1200}, {2340, 2600} },
109 {6, {585, 650}, {1215, 1350}, {2633, 2925} },
110 {7, {650, 722}, {1350, 1500}, {2925, 3250} },
111 {8, {780, 867}, {1620, 1800}, {3510, 3900} },
112 {9, {865, 960}, {1800, 2000}, {3900, 4333} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113};
114
115/*MCS parameters with Nss = 2*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800116static struct index_vht_data_rate_type vht_mcs_nss2[] = {
117 /* MCS L20 S20 L40 S40 L80 S80 */
118 {0, {130, 144}, {270, 300}, { 585, 650} },
119 {1, {260, 289}, {540, 600}, {1170, 1300} },
120 {2, {390, 433}, {810, 900}, {1755, 1950} },
121 {3, {520, 578}, {1080, 1200}, {2340, 2600} },
122 {4, {780, 867}, {1620, 1800}, {3510, 3900} },
123 {5, {1040, 1156}, {2160, 2400}, {4680, 5200} },
124 {6, {1170, 1300}, {2430, 2700}, {5265, 5850} },
125 {7, {1300, 1444}, {2700, 3000}, {5850, 6500} },
126 {8, {1560, 1733}, {3240, 3600}, {7020, 7800} },
127 {9, {1730, 1920}, {3600, 4000}, {7800, 8667} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800129
130#ifdef BIG_ENDIAN_HOST
131
132/* ############# function definitions ############ */
133
134/**
135 * wma_swap_bytes() - swap bytes
136 * @pv: buffer
137 * @n: swap bytes
138 *
139 * Return: none
140 */
141void wma_swap_bytes(void *pv, uint32_t n)
142{
143 int32_t no_words;
144 int32_t i;
145 uint32_t *word_ptr;
146
147 no_words = n / sizeof(uint32_t);
148 word_ptr = (uint32_t *) pv;
149 for (i = 0; i < no_words; i++) {
150 *(word_ptr + i) = __cpu_to_le32(*(word_ptr + i));
151 }
152}
153
154#define SWAPME(x, len) wma_swap_bytes(&x, len);
155#endif /* BIG_ENDIAN_HOST */
156
157/**
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800158 * wma_mcs_rate_match() - find the match mcs rate
159 * @match_rate: the rate to look up
160 * @is_sgi: return if the SGI rate is found
161 * @nss: the nss in use
162 * @nss1_rate: the nss1 rate
163 * @nss1_srate: the nss1 SGI rate
164 * @nss2_rate: the nss2 rate
165 * @nss2_srate: the nss2 SGI rate
166 *
167 * This is a helper function to find the match of the tx_rate
168 * in terms of the nss1/nss2 rate with non-SGI/SGI.
169 *
170 * Return: the found rate or 0 otherwise
171 */
172static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi,
173 uint8_t nss, uint16_t nss1_rate,
174 uint16_t nss1_srate,
175 uint16_t nss2_rate,
176 uint16_t nss2_srate)
177{
178 WMA_LOGD("%s match_rate: %d, %d %d %d %d",
179 __func__, match_rate, nss1_rate, nss1_srate, nss2_rate,
180 nss2_srate);
181
182 if (match_rate == nss1_rate) {
183 return nss1_rate;
184 } else if (match_rate == nss1_srate) {
185 *is_sgi = true;
186 return nss1_srate;
187 } else if (nss == 2 && match_rate == nss2_rate)
188 return nss2_rate;
189 else if (nss == 2 && match_rate == nss2_srate) {
190 *is_sgi = true;
191 return nss2_srate;
192 } else
193 return 0;
194}
195
196/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 * wma_get_mcs_idx() - get mcs index
198 * @maxRate: max rate
199 * @rate_flags: rate flags
200 * @nss: number of nss
201 * @mcsRateFlag: mcs rate flag
202 *
203 * Return: return mcs index
204 */
205static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
206 uint8_t nss, uint8_t *mcsRateFlag)
207{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800208 uint8_t index = 0;
209 uint16_t match_rate;
210 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800212 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
213 __func__, maxRate, rate_flags, nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214
215 *mcsRateFlag = rate_flags;
216 *mcsRateFlag &= ~eHAL_TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800217 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800218 if (rate_flags & eHAL_TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800219 /* check for vht80 nss1/2 rate set */
220 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
221 vht_mcs_nss1[index].ht80_rate[0],
222 vht_mcs_nss1[index].ht80_rate[1],
223 vht_mcs_nss2[index].ht80_rate[0],
224 vht_mcs_nss2[index].ht80_rate[1]);
225 if (match_rate)
226 goto rate_found;
227 }
228 if ((rate_flags & eHAL_TX_RATE_VHT40) |
229 (rate_flags & eHAL_TX_RATE_VHT80)) {
230 /* check for vht40 nss1/2 rate set */
231 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
232 vht_mcs_nss1[index].ht40_rate[0],
233 vht_mcs_nss1[index].ht40_rate[1],
234 vht_mcs_nss2[index].ht40_rate[0],
235 vht_mcs_nss2[index].ht40_rate[1]);
236 if (match_rate) {
237 *mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
238 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239 }
240 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800241 if ((rate_flags & eHAL_TX_RATE_VHT20) |
242 (rate_flags & eHAL_TX_RATE_VHT40) |
243 (rate_flags & eHAL_TX_RATE_VHT80)) {
244 /* check for vht20 nss1/2 rate set */
245 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
246 vht_mcs_nss1[index].ht20_rate[0],
247 vht_mcs_nss1[index].ht20_rate[1],
248 vht_mcs_nss2[index].ht20_rate[0],
249 vht_mcs_nss2[index].ht20_rate[1]);
250 if (match_rate) {
251 *mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 |
252 eHAL_TX_RATE_VHT40);
253 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800254 }
255 }
256 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800257 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800258 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800259 /* check for ht40 nss1/2 rate set */
260 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
261 mcs_nss1[index].ht40_rate[0],
262 mcs_nss1[index].ht40_rate[1],
263 mcs_nss2[index].ht40_rate[0],
264 mcs_nss2[index].ht40_rate[1]);
265 if (match_rate) {
266 *mcsRateFlag = eHAL_TX_RATE_HT40;
267 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800268 }
269 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800270 if (rate_flags & eHAL_TX_RATE_HT20) {
271 /* check for ht20 nss1/2 rate set */
272 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
273 mcs_nss1[index].ht20_rate[0],
274 mcs_nss1[index].ht20_rate[1],
275 mcs_nss2[index].ht20_rate[0],
276 mcs_nss2[index].ht20_rate[1]);
277 if (match_rate) {
278 *mcsRateFlag = eHAL_TX_RATE_HT20;
279 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800280 }
281 }
282 }
283
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800284rate_found:
285 /* set SGI flag only if this is SGI rate */
286 if (match_rate && is_sgi == true)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800287 *mcsRateFlag |= eHAL_TX_RATE_SGI;
288
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800289 WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
290 __func__, match_rate, index, *mcsRateFlag, is_sgi);
291
292 return match_rate ? index : INVALID_MCS_IDX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293}
294
295/**
296 * host_map_smps_mode() - map fw smps mode to tSmpsModeValue
297 * @fw_smps_mode: fw smps mode
298 *
299 * Return: return tSmpsModeValue
300 */
301tSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
302{
303 tSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
304 switch (fw_smps_mode) {
305 case WMI_SMPS_FORCED_MODE_STATIC:
306 smps_mode = STATIC_SMPS_MODE;
307 break;
308 case WMI_SMPS_FORCED_MODE_DYNAMIC:
309 smps_mode = DYNAMIC_SMPS_MODE;
310 break;
311 default:
312 smps_mode = SMPS_MODE_DISABLED;
313 }
314
315 return smps_mode;
316}
317
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800318/**
319 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
320 * mode commmand param
321 * @smps_mode: SMPS mode according to the protocol
322 *
323 * Return: int > 0 for success else failure
324 */
325int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
326{
327 int param = -EINVAL;
328
329 switch (smps_mode) {
330 case STATIC_SMPS_MODE:
331 param = WMI_SMPS_FORCED_MODE_STATIC;
332 break;
333 case DYNAMIC_SMPS_MODE:
334 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
335 break;
336 case SMPS_MODE_DISABLED:
337 param = WMI_SMPS_FORCED_MODE_DISABLED;
338 break;
339 default:
340 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
341 smps_mode);
342 }
343 return param;
344}
345
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800346#ifdef WLAN_FEATURE_STATS_EXT
347/**
348 * wma_stats_ext_event_handler() - extended stats event handler
349 * @handle: wma handle
350 * @event_buf: event buffer received from fw
351 * @len: length of data
352 *
353 * Return: 0 for success or error code
354 */
355int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
356 uint32_t len)
357{
358 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
359 tSirStatsExtEvent *stats_ext_event;
360 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530361 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362 cds_msg_t cds_msg;
363 uint8_t *buf_ptr;
364 uint32_t alloc_len;
365
366 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
367
368 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
369 if (!param_buf) {
370 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
371 return -EINVAL;
372 }
373
374 stats_ext_info = param_buf->fixed_param;
375 buf_ptr = (uint8_t *) stats_ext_info;
376
377 alloc_len = sizeof(tSirStatsExtEvent);
378 alloc_len += stats_ext_info->data_len;
379
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530380 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800381 if (NULL == stats_ext_event) {
382 WMA_LOGE("%s: Memory allocation failure", __func__);
383 return -ENOMEM;
384 }
385
386 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
387
388 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
389 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530390 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 buf_ptr, stats_ext_event->event_data_len);
392
393 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
394 cds_msg.bodyptr = (void *)stats_ext_event;
395 cds_msg.bodyval = 0;
396
397 status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530398 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800399 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530400 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 return -EFAULT;
402 }
403
404 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
405 return 0;
406}
407#endif /* WLAN_FEATURE_STATS_EXT */
408
Nirav Shah93e789e2016-04-14 19:47:43 +0530409
Govind Singha471e5e2015-10-12 17:11:14 +0530410/**
411 * wma_profile_data_report_event_handler() - fw profiling handler
412 * @handle: wma handle
413 * @event_buf: event buffer received from fw
414 * @len: length of data
415 *
416 * Return: 0 for success or error code
417 */
418int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
419 uint32_t len)
420{
421 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
422 wmi_wlan_profile_ctx_t *profile_ctx;
423 wmi_wlan_profile_t *profile_data;
424 uint32_t i = 0;
425 uint32_t entries;
426 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530427 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530428 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
429
430 if (!param_buf) {
431 WMA_LOGE("%s: Invalid profile data event buf", __func__);
432 return -EINVAL;
433 }
434 profile_ctx = param_buf->profile_ctx;
435 buf_ptr = (uint8_t *)profile_ctx;
436 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
437 profile_data = (wmi_wlan_profile_t *) buf_ptr;
438 entries = profile_ctx->bin_count;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530439 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530440 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530441 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530442 "TOT: %d\n"
443 "tx_msdu_cnt: %d\n"
444 "tx_mpdu_cnt: %d\n"
445 "tx_ppdu_cnt: %d\n"
446 "rx_msdu_cnt: %d\n"
447 "rx_mpdu_cnt: %d\n"
448 "bin_count: %d\n",
449 profile_ctx->tot,
450 profile_ctx->tx_msdu_cnt,
451 profile_ctx->tx_mpdu_cnt,
452 profile_ctx->tx_ppdu_cnt,
453 profile_ctx->rx_msdu_cnt,
454 profile_ctx->rx_mpdu_cnt,
455 profile_ctx->bin_count);
456
Nirav Shah93e789e2016-04-14 19:47:43 +0530457 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
458 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
459
Govind Singha471e5e2015-10-12 17:11:14 +0530460 for (i = 0; i < entries; i++) {
461 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
462 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530463 snprintf(temp_str, sizeof(temp_str),
464 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530465 profile_data[i].id,
466 profile_data[i].cnt,
467 profile_data[i].tot,
468 profile_data[i].min,
469 profile_data[i].max,
470 profile_data[i].hist_intvl,
471 profile_data[i].hist[0],
472 profile_data[i].hist[1],
473 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530474 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
475 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530476 }
477
478 return 0;
479}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480
481#ifdef WLAN_FEATURE_LINK_LAYER_STATS
482
483/**
484 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
485 * @handle: wma handle
486 * @cmd_param_info: data received with event from fw
487 * @len: length of data
488 *
489 * Return: 0 for success or error code
490 */
491static int wma_unified_link_peer_stats_event_handler(void *handle,
492 uint8_t *cmd_param_info,
493 uint32_t len)
494{
495 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
496 wmi_peer_stats_event_fixed_param *fixed_param;
497 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
498 wmi_rate_stats *rate_stats;
499 tSirLLStatsResults *link_stats_results;
500 uint8_t *results, *t_peer_stats, *t_rate_stats;
501 uint32_t count, num_rates = 0;
502 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
503 size_t peer_info_size, peer_stats_size, rate_stats_size;
504 size_t link_stats_results_size;
505
Anurag Chouhan6d760662016-02-20 16:05:43 +0530506 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507
508 if (!pMac) {
509 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
510 return -EINVAL;
511 }
512
513 if (!pMac->sme.pLinkLayerStatsIndCallback) {
514 WMA_LOGD("%s: HDD callback is null", __func__);
515 return -EINVAL;
516 }
517
518 WMA_LOGD("%s: Posting Peer Stats event to HDD", __func__);
519 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
520 if (!param_tlvs) {
521 WMA_LOGA("%s: Invalid stats event", __func__);
522 return -EINVAL;
523 }
524 /*
525 * cmd_param_info contains
526 * wmi_peer_stats_event_fixed_param fixed_param;
527 * num_peers * size of(struct wmi_peer_link_stats)
528 * num_rates * size of(struct wmi_rate_stats)
529 * num_rates is the sum of the rates of all the peers.
530 */
531 fixed_param = param_tlvs->fixed_param;
532 peer_stats = param_tlvs->peer_stats;
533 rate_stats = param_tlvs->peer_rate_stats;
534
535 if (!fixed_param || !peer_stats ||
536 (peer_stats->num_rates && !rate_stats)) {
537 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
538 return -EINVAL;
539 }
540
541 /*
542 * num_rates - sum of the rates of all the peers
543 */
544 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
545 for (count = 0; count < fixed_param->num_peers; count++) {
546 num_rates += temp_peer_stats->num_rates;
547 temp_peer_stats++;
548 }
549
550 peer_stats_size = sizeof(tSirWifiPeerStat);
551 peer_info_size = sizeof(tSirWifiPeerInfo);
552 rate_stats_size = sizeof(tSirWifiRateStat);
553 link_stats_results_size =
554 sizeof(*link_stats_results) + peer_stats_size +
555 (fixed_param->num_peers * peer_info_size) +
556 (num_rates * rate_stats_size);
557
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530558 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 if (NULL == link_stats_results) {
560 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
561 __func__, link_stats_results_size);
562 return -ENOMEM;
563 }
564
565 WMA_LOGD("Peer stats from FW event buf");
566 WMA_LOGD("Fixed Param:");
567 WMA_LOGD("request_id %u num_peers %u peer_event_number %u more_data %u",
568 fixed_param->request_id, fixed_param->num_peers,
569 fixed_param->peer_event_number, fixed_param->more_data);
570
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530571 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572
573 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
574 link_stats_results->rspId = fixed_param->request_id;
575 link_stats_results->ifaceId = 0;
576 link_stats_results->num_peers = fixed_param->num_peers;
577 link_stats_results->peer_event_number = fixed_param->peer_event_number;
578 link_stats_results->moreResultToFollow = fixed_param->more_data;
579
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530580 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581 &fixed_param->num_peers, peer_stats_size);
582
583 results = (uint8_t *) link_stats_results->results;
584 t_peer_stats = (uint8_t *) peer_stats;
585 t_rate_stats = (uint8_t *) rate_stats;
586 next_res_offset = peer_stats_size;
587 next_peer_offset = WMI_TLV_HDR_SIZE;
588 next_rate_offset = WMI_TLV_HDR_SIZE;
589 for (count = 0; count < fixed_param->num_peers; count++) {
590 WMA_LOGD("Peer Info:");
591 WMA_LOGD("peer_type %u capabilities %u num_rates %u",
592 peer_stats->peer_type, peer_stats->capabilities,
593 peer_stats->num_rates);
594
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530595 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596 t_peer_stats + next_peer_offset, peer_info_size);
597 next_res_offset += peer_info_size;
598
599 /* Copy rate stats associated with this peer */
600 for (count = 0; count < peer_stats->num_rates; count++) {
601 WMA_LOGD("Rate Stats Info:");
602 WMA_LOGD("rate %u bitrate %u tx_mpdu %u rx_mpdu %u "
603 "mpdu_lost %u retries %u retries_short %u "
604 "retries_long %u", rate_stats->rate,
605 rate_stats->bitrate, rate_stats->tx_mpdu,
606 rate_stats->rx_mpdu, rate_stats->mpdu_lost,
607 rate_stats->retries, rate_stats->retries_short,
608 rate_stats->retries_long);
609 rate_stats++;
610
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530611 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612 t_rate_stats + next_rate_offset,
613 rate_stats_size);
614 next_res_offset += rate_stats_size;
615 next_rate_offset += sizeof(*rate_stats);
616 }
617 next_peer_offset += sizeof(*peer_stats);
618 peer_stats++;
619 }
620
621 /* call hdd callback with Link Layer Statistics
622 * vdev_id/ifacId in link_stats_results will be
623 * used to retrieve the correct HDD context
624 */
625 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
626 WMA_LINK_LAYER_STATS_RESULTS_RSP,
627 link_stats_results);
628 WMA_LOGD("%s: Peer Stats event posted to HDD", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530629 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630
631 return 0;
632}
633
634
635/**
636 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
637 * @handle: wma handle
638 * @cmd_param_info: data received with event from fw
639 * @len: length of data
640 *
641 * Return: 0 for success or error code
642 */
643static int wma_unified_link_radio_stats_event_handler(void *handle,
644 uint8_t *cmd_param_info,
645 uint32_t len)
646{
647 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
648 wmi_radio_link_stats_event_fixed_param *fixed_param;
649 wmi_radio_link_stats *radio_stats;
650 wmi_channel_stats *channel_stats;
651 tSirLLStatsResults *link_stats_results;
652 uint8_t *results, *t_radio_stats, *t_channel_stats;
653 uint32_t next_res_offset, next_chan_offset, count;
654 size_t radio_stats_size, chan_stats_size;
655 size_t link_stats_results_size;
656
Anurag Chouhan6d760662016-02-20 16:05:43 +0530657 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658
659 if (!pMac) {
660 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
661 return -EINVAL;
662 }
663
664 if (!pMac->sme.pLinkLayerStatsIndCallback) {
665 WMA_LOGD("%s: HDD callback is null", __func__);
666 return -EINVAL;
667 }
668
669 WMA_LOGD("%s: Posting Radio Stats event to HDD", __func__);
670 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
671 if (!param_tlvs) {
672 WMA_LOGA("%s: Invalid stats event", __func__);
673 return -EINVAL;
674 }
675
676 /*
677 * cmd_param_info contains
678 * wmi_radio_link_stats_event_fixed_param fixed_param;
679 * size of(struct wmi_radio_link_stats);
680 * num_channels * size of(struct wmi_channel_stats)
681 */
682 fixed_param = param_tlvs->fixed_param;
683 radio_stats = param_tlvs->radio_stats;
684 channel_stats = param_tlvs->channel_stats;
685
686 if (!fixed_param || !radio_stats ||
687 (radio_stats->num_channels && !channel_stats)) {
688 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
689 return -EINVAL;
690 }
691
692 radio_stats_size = sizeof(tSirWifiRadioStat);
693 chan_stats_size = sizeof(tSirWifiChannelStats);
694 link_stats_results_size = sizeof(*link_stats_results) +
695 radio_stats_size + (radio_stats->num_channels * chan_stats_size);
696
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530697 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 if (NULL == link_stats_results) {
699 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
700 __func__, link_stats_results_size);
701 return -ENOMEM;
702 }
703
704 WMA_LOGD("Radio stats from FW event buf");
705 WMA_LOGD("Fixed Param:");
706 WMA_LOGD("request_id %u num_radio %u more_radio_events %u",
707 fixed_param->request_id, fixed_param->num_radio,
708 fixed_param->more_radio_events);
709
710 WMA_LOGD("Radio Info");
711 WMA_LOGD("radio_id %u on_time %u tx_time %u rx_time %u on_time_scan %u "
712 "on_time_nbd %u on_time_gscan %u on_time_roam_scan %u "
713 "on_time_pno_scan %u on_time_hs20 %u num_channels %u",
714 radio_stats->radio_id, radio_stats->on_time,
715 radio_stats->tx_time, radio_stats->rx_time,
716 radio_stats->on_time_scan, radio_stats->on_time_nbd,
717 radio_stats->on_time_gscan,
718 radio_stats->on_time_roam_scan,
719 radio_stats->on_time_pno_scan,
720 radio_stats->on_time_hs20, radio_stats->num_channels);
721
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530722 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800723
724 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
725 link_stats_results->rspId = fixed_param->request_id;
726 link_stats_results->ifaceId = 0;
727 link_stats_results->num_radio = fixed_param->num_radio;
728 link_stats_results->peer_event_number = 0;
729 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
730
731 results = (uint8_t *) link_stats_results->results;
732 t_radio_stats = (uint8_t *) radio_stats;
733 t_channel_stats = (uint8_t *) channel_stats;
734
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530735 qdf_mem_copy(results, t_radio_stats + WMI_TLV_HDR_SIZE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736 radio_stats_size);
737
738 next_res_offset = radio_stats_size;
739 next_chan_offset = WMI_TLV_HDR_SIZE;
740 WMA_LOGD("Channel Stats Info");
741 for (count = 0; count < radio_stats->num_channels; count++) {
742 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u "
743 "center_freq1 %u radio_awake_time %u cca_busy_time %u",
744 channel_stats->channel_width,
745 channel_stats->center_freq,
746 channel_stats->center_freq0,
747 channel_stats->center_freq1,
748 channel_stats->radio_awake_time,
749 channel_stats->cca_busy_time);
750 channel_stats++;
751
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530752 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753 t_channel_stats + next_chan_offset,
754 chan_stats_size);
755 next_res_offset += chan_stats_size;
756 next_chan_offset += sizeof(*channel_stats);
757 }
758
759 /* call hdd callback with Link Layer Statistics
760 * vdev_id/ifacId in link_stats_results will be
761 * used to retrieve the correct HDD context
762 */
763 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
764 WMA_LINK_LAYER_STATS_RESULTS_RSP,
765 link_stats_results);
766 WMA_LOGD("%s: Radio Stats event posted to HDD", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530767 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768
769 return 0;
770}
771
772/**
773 * wma_register_ll_stats_event_handler() - register link layer stats related
774 * event handler
775 * @wma_handle: wma handle
776 *
777 * Return: none
778 */
779void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
780{
781 if (NULL == wma_handle) {
782 WMA_LOGE("%s: wma_handle is NULL", __func__);
783 return;
784 }
785
786 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +0530787 WMI_IFACE_LINK_STATS_EVENTID,
788 wma_unified_link_iface_stats_event_handler,
789 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +0530791 WMI_PEER_LINK_STATS_EVENTID,
792 wma_unified_link_peer_stats_event_handler,
793 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +0530795 WMI_RADIO_LINK_STATS_EVENTID,
796 wma_unified_link_radio_stats_event_handler,
797 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798
799 return;
800}
801
802
803/**
804 * wma_process_ll_stats_clear_req() - clear link layer stats
805 * @wma: wma handle
806 * @clearReq: ll stats clear request command params
807 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530808 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800809 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530810QDF_STATUS wma_process_ll_stats_clear_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811 (tp_wma_handle wma, const tpSirLLStatsClearReq clearReq)
812{
Govind Singh4863da42016-03-08 11:45:00 +0530813 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 int ret;
815
816 if (!clearReq || !wma) {
817 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530818 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 }
820
Govind Singh4863da42016-03-08 11:45:00 +0530821 cmd.stop_req = clearReq->stopReq;
822 cmd.sta_id = clearReq->staId;
823 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824
Govind Singh4863da42016-03-08 11:45:00 +0530825 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
826 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827 if (ret) {
828 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530829 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830 }
831
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530832 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833}
834
835/**
836 * wma_process_ll_stats_set_req() - link layer stats set request
837 * @wma: wma handle
838 * @setReq: ll stats set request command params
839 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530840 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530842QDF_STATUS wma_process_ll_stats_set_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843 (tp_wma_handle wma, const tpSirLLStatsSetReq setReq)
844{
Govind Singh4863da42016-03-08 11:45:00 +0530845 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 int ret;
847
848 if (!setReq || !wma) {
849 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530850 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800851 }
852
Govind Singh4863da42016-03-08 11:45:00 +0530853 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
854 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855 setReq->aggressiveStatisticsGathering;
856
Govind Singh4863da42016-03-08 11:45:00 +0530857 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
858 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859 if (ret) {
860 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530861 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862 }
863
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530864 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800865}
866
867/**
868 * wma_process_ll_stats_get_req() - link layer stats get request
869 * @wma:wma handle
870 * @getReq:ll stats get request command params
871 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530872 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530874QDF_STATUS wma_process_ll_stats_get_req
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800875 (tp_wma_handle wma, const tpSirLLStatsGetReq getReq)
876{
Govind Singh4863da42016-03-08 11:45:00 +0530877 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878 int ret;
879
880 if (!getReq || !wma) {
881 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530882 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883 }
884
Govind Singh4863da42016-03-08 11:45:00 +0530885 cmd.req_id = getReq->reqId;
886 cmd.param_id_mask = getReq->paramIdMask;
887 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888
Govind Singh4863da42016-03-08 11:45:00 +0530889 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
890 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800891 if (ret) {
892 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530893 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 }
895
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530896 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800897}
898
899/**
900 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
901 * @wma:wma handle
902 * @cmd_param_info: data from event
903 * @len: length
904 *
905 * Return: 0 for success or error code
906 */
907int wma_unified_link_iface_stats_event_handler(void *handle,
908 uint8_t *cmd_param_info,
909 uint32_t len)
910{
911 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
912 wmi_iface_link_stats_event_fixed_param *fixed_param;
913 wmi_iface_link_stats *link_stats;
914 wmi_wmm_ac_stats *ac_stats;
915 tSirLLStatsResults *link_stats_results;
916 uint8_t *results, *t_link_stats, *t_ac_stats;
917 uint32_t next_res_offset, next_ac_offset, count;
918 uint32_t roaming_offset, roaming_size;
919 size_t link_stats_size, ac_stats_size, iface_info_size;
920 size_t link_stats_results_size;
921
Anurag Chouhan6d760662016-02-20 16:05:43 +0530922 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923
924 if (!pMac) {
925 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
926 return -EINVAL;
927 }
928
929 if (!pMac->sme.pLinkLayerStatsIndCallback) {
930 WMA_LOGD("%s: HDD callback is null", __func__);
931 return -EINVAL;
932 }
933
934 WMA_LOGD("%s: Posting Iface Stats event to HDD", __func__);
935 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
936 if (!param_tlvs) {
937 WMA_LOGA("%s: Invalid stats event", __func__);
938 return -EINVAL;
939 }
940
941 /*
942 * cmd_param_info contains
943 * wmi_iface_link_stats_event_fixed_param fixed_param;
944 * wmi_iface_link_stats iface_link_stats;
945 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
946 */
947 fixed_param = param_tlvs->fixed_param;
948 link_stats = param_tlvs->iface_link_stats;
949 ac_stats = param_tlvs->ac;
950
951 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats)) {
952 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
953 return -EINVAL;
954 }
955
956 link_stats_size = sizeof(tSirWifiIfaceStat);
957 iface_info_size = sizeof(tSirWifiInterfaceInfo);
958 ac_stats_size = sizeof(tSirWifiWmmAcStat);
959 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
960
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530961 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800962 if (!link_stats_results) {
963 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
964 __func__, link_stats_results_size);
965 return -ENOMEM;
966 }
967
968 WMA_LOGD("Interface stats from FW event buf");
969 WMA_LOGD("Fixed Param:");
970 WMA_LOGD("request_id %u vdev_id %u",
971 fixed_param->request_id, fixed_param->vdev_id);
972
973 WMA_LOGD("Iface Stats:");
974 WMA_LOGD("beacon_rx %u mgmt_rx %u mgmt_action_rx %u mgmt_action_tx %u "
975 "rssi_mgmt %u rssi_data %u rssi_ack %u num_peers %u "
976 "num_peer_events %u num_ac %u roam_state %u"
977 " avg_bcn_spread_offset_high %u"
978 " avg_bcn_spread_offset_low %u"
979 " is leaky_ap %u"
980 " avg_rx_frames_leaked %u"
981 " rx_leak_window %u",
982 link_stats->beacon_rx, link_stats->mgmt_rx,
983 link_stats->mgmt_action_rx, link_stats->mgmt_action_tx,
984 link_stats->rssi_mgmt, link_stats->rssi_data,
985 link_stats->rssi_ack, link_stats->num_peers,
986 link_stats->num_peer_events, link_stats->num_ac,
987 link_stats->roam_state,
988 link_stats->avg_bcn_spread_offset_high,
989 link_stats->avg_bcn_spread_offset_low,
990 link_stats->is_leaky_ap,
991 link_stats->avg_rx_frms_leaked,
992 link_stats->rx_leak_window);
993
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530994 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995
996 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
997 link_stats_results->rspId = fixed_param->request_id;
998 link_stats_results->ifaceId = fixed_param->vdev_id;
999 link_stats_results->num_peers = link_stats->num_peers;
1000 link_stats_results->peer_event_number = 0;
1001 link_stats_results->moreResultToFollow = 0;
1002
1003 results = (uint8_t *) link_stats_results->results;
1004 t_link_stats = (uint8_t *) link_stats;
1005 t_ac_stats = (uint8_t *) ac_stats;
1006
1007 /* Copy roaming state */
1008 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
1009 roaming_size = member_size(tSirWifiInterfaceInfo, roaming);
1010
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301011 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 roaming_size);
1013
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301014 qdf_mem_copy(results + iface_info_size,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015 t_link_stats + WMI_TLV_HDR_SIZE,
1016 link_stats_size - iface_info_size -
1017 WIFI_AC_MAX * ac_stats_size);
1018
1019 next_res_offset = link_stats_size - WIFI_AC_MAX * ac_stats_size;
1020 next_ac_offset = WMI_TLV_HDR_SIZE;
1021
1022 WMA_LOGD("AC Stats:");
1023 for (count = 0; count < link_stats->num_ac; count++) {
1024 WMA_LOGD("ac_type %u tx_mpdu %u rx_mpdu %u tx_mcast %u "
1025 "rx_mcast %u rx_ampdu %u tx_ampdu %u mpdu_lost %u "
1026 "retries %u retries_short %u retries_long %u "
1027 "contention_time_min %u contention_time_max %u "
1028 "contention_time_avg %u contention_num_samples %u",
1029 ac_stats->ac_type, ac_stats->tx_mpdu,
1030 ac_stats->rx_mpdu, ac_stats->tx_mcast,
1031 ac_stats->rx_mcast, ac_stats->rx_ampdu,
1032 ac_stats->tx_ampdu, ac_stats->mpdu_lost,
1033 ac_stats->retries, ac_stats->retries_short,
1034 ac_stats->retries_long, ac_stats->contention_time_min,
1035 ac_stats->contention_time_max,
1036 ac_stats->contention_time_avg,
1037 ac_stats->contention_num_samples);
1038 ac_stats++;
1039
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301040 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001041 t_ac_stats + next_ac_offset, ac_stats_size);
1042 next_res_offset += ac_stats_size;
1043 next_ac_offset += sizeof(*ac_stats);
1044 }
1045
1046 /* call hdd callback with Link Layer Statistics
1047 * vdev_id/ifacId in link_stats_results will be
1048 * used to retrieve the correct HDD context
1049 */
1050 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1051 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1052 link_stats_results);
1053 WMA_LOGD("%s: Iface Stats event posted to HDD", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301054 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001055
1056 return 0;
1057}
1058
1059#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1060
1061/**
1062 * wma_update_pdev_stats() - update pdev stats
1063 * @wma: wma handle
1064 * @pdev_stats: pdev stats
1065 *
1066 * Return: none
1067 */
1068static void wma_update_pdev_stats(tp_wma_handle wma,
1069 wmi_pdev_stats *pdev_stats)
1070{
1071 tAniGetPEStatsRsp *stats_rsp_params;
1072 uint32_t temp_mask;
1073 uint8_t *stats_buf;
1074 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
1075 struct wma_txrx_node *node;
1076 uint8_t i;
1077
1078 for (i = 0; i < wma->max_bssid; i++) {
1079 node = &wma->interfaces[i];
1080 stats_rsp_params = node->stats_rsp;
1081 if (stats_rsp_params) {
1082 node->fw_stats_set |= FW_PDEV_STATS_SET;
1083 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
1084 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1085 temp_mask = stats_rsp_params->statsMask;
1086 if (temp_mask & (1 << eCsrSummaryStats))
1087 stats_buf += sizeof(tCsrSummaryStatsInfo);
1088
1089 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
1090 classa_stats =
1091 (tCsrGlobalClassAStatsInfo *) stats_buf;
1092 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
1093 }
1094 }
1095 }
1096}
1097
1098/**
1099 * wma_update_vdev_stats() - update vdev stats
1100 * @wma: wma handle
1101 * @vdev_stats: vdev stats
1102 *
1103 * Return: none
1104 */
1105static void wma_update_vdev_stats(tp_wma_handle wma,
1106 wmi_vdev_stats *vdev_stats)
1107{
1108 tAniGetPEStatsRsp *stats_rsp_params;
1109 tCsrSummaryStatsInfo *summary_stats = NULL;
1110 uint8_t *stats_buf;
1111 struct wma_txrx_node *node;
1112 uint8_t i;
1113 int8_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301114 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
1116 cds_msg_t sme_msg = { 0 };
1117
1118 node = &wma->interfaces[vdev_stats->vdev_id];
1119 stats_rsp_params = node->stats_rsp;
1120 if (stats_rsp_params) {
1121 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1122 node->fw_stats_set |= FW_VDEV_STATS_SET;
1123 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
1124 vdev_stats->vdev_id);
1125 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
1126 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
1127 for (i = 0; i < 4; i++) {
1128 summary_stats->tx_frm_cnt[i] =
1129 vdev_stats->tx_frm_cnt[i];
1130 summary_stats->fail_cnt[i] =
1131 vdev_stats->fail_cnt[i];
1132 summary_stats->multiple_retry_cnt[i] =
1133 vdev_stats->multiple_retry_cnt[i];
1134 }
1135
1136 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
1137 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
1138 summary_stats->rx_discard_cnt =
1139 vdev_stats->rx_discard_cnt;
1140 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
1141 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
1142 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
1143 }
1144 }
1145
1146 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
1147 vdev_stats->vdev_id,
1148 vdev_stats->vdev_snr.bcn_snr, vdev_stats->vdev_snr.dat_snr);
1149
1150 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
1151 if ((vdev_stats->vdev_snr.bcn_snr == WMA_TGT_INVALID_SNR) &&
1152 (vdev_stats->vdev_snr.dat_snr == WMA_TGT_INVALID_SNR)) {
1153 /*
1154 * Firmware sends invalid snr till it sees
1155 * Beacon/Data after connection since after
1156 * vdev up fw resets the snr to invalid.
1157 * In this duartion Host will return the last know
1158 * rssi during connection.
1159 */
1160 WMA_LOGE("Invalid SNR from firmware");
1161
1162 } else {
1163 if (vdev_stats->vdev_snr.bcn_snr != WMA_TGT_INVALID_SNR) {
1164 rssi = vdev_stats->vdev_snr.bcn_snr;
1165 } else if (vdev_stats->vdev_snr.dat_snr !=
1166 WMA_TGT_INVALID_SNR) {
1167 rssi = vdev_stats->vdev_snr.dat_snr;
1168 }
1169
1170 /*
1171 * Get the absolute rssi value from the current rssi value
1172 * the sinr value is hardcoded into 0 in the core stack
1173 */
1174 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
1175 }
1176
1177 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
1178 pGetRssiReq->sessionId);
1179
1180 /* update the average rssi value to UMAC layer */
1181 if (NULL != pGetRssiReq->rssiCallback) {
1182 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
1183 pGetRssiReq->staId,
1184 pGetRssiReq->pDevContext);
1185 }
1186
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301187 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001188 wma->pGetRssiReq = NULL;
1189 }
1190
1191 if (node->psnr_req) {
1192 tAniGetSnrReq *p_snr_req = node->psnr_req;
1193
1194 if (vdev_stats->vdev_snr.bcn_snr != WMA_TGT_INVALID_SNR)
1195 p_snr_req->snr = vdev_stats->vdev_snr.bcn_snr;
1196 else if (vdev_stats->vdev_snr.dat_snr != WMA_TGT_INVALID_SNR)
1197 p_snr_req->snr = vdev_stats->vdev_snr.dat_snr;
1198 else
1199 p_snr_req->snr = WMA_TGT_INVALID_SNR;
1200
1201 sme_msg.type = eWNI_SME_SNR_IND;
1202 sme_msg.bodyptr = p_snr_req;
1203 sme_msg.bodyval = 0;
1204
Anurag Chouhan6d760662016-02-20 16:05:43 +05301205 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301206 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301208 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209 }
1210
1211 node->psnr_req = NULL;
1212 }
1213}
1214
1215/**
1216 * wma_post_stats() - update stats to PE
1217 * @wma: wma handle
1218 * @node: txrx node
1219 *
1220 * Return: none
1221 */
1222static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
1223{
1224 tAniGetPEStatsRsp *stats_rsp_params;
1225
1226 stats_rsp_params = node->stats_rsp;
1227 /* send response to UMAC */
1228 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, (void *)stats_rsp_params, 0);
1229 node->stats_rsp = NULL;
1230 node->fw_stats_set = 0;
1231}
1232
1233/**
1234 * wma_update_peer_stats() - update peer stats
1235 * @wma: wma handle
1236 * @peer_stats: peer stats
1237 *
1238 * Return: none
1239 */
1240static void wma_update_peer_stats(tp_wma_handle wma,
1241 wmi_peer_stats *peer_stats)
1242{
1243 tAniGetPEStatsRsp *stats_rsp_params;
1244 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
1245 struct wma_txrx_node *node;
1246 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
1247 uint32_t temp_mask;
1248
1249 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
1250 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
1251 return;
1252
1253 node = &wma->interfaces[vdev_id];
1254 if (node->stats_rsp) {
1255 node->fw_stats_set |= FW_PEER_STATS_SET;
1256 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
1257 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
1258 stats_buf = (uint8_t *) (stats_rsp_params + 1);
1259 temp_mask = stats_rsp_params->statsMask;
1260 if (temp_mask & (1 << eCsrSummaryStats))
1261 stats_buf += sizeof(tCsrSummaryStatsInfo);
1262
1263 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
1264 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
1265 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
1266 /*The linkspeed returned by fw is in kbps so convert
1267 *it in to units of 500kbps which is expected by UMAC*/
1268 if (peer_stats->peer_tx_rate) {
1269 classa_stats->tx_rate =
1270 peer_stats->peer_tx_rate / 500;
1271 }
1272
1273 classa_stats->tx_rate_flags = node->rate_flags;
1274 if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) {
1275 classa_stats->mcs_index =
1276 wma_get_mcs_idx((peer_stats->peer_tx_rate /
1277 100), node->rate_flags,
1278 node->nss, &mcsRateFlags);
1279 /* rx_frag_cnt and promiscuous_rx_frag_cnt
1280 * parameter is currently not used. lets use the
1281 * same parameter to hold the nss value and mcs
1282 * rate flags */
1283 classa_stats->rx_frag_cnt = node->nss;
1284 classa_stats->promiscuous_rx_frag_cnt =
1285 mcsRateFlags;
1286 WMA_LOGD("Computed mcs_idx:%d mcs_rate_flags:%d",
1287 classa_stats->mcs_index, mcsRateFlags);
1288 }
1289 /* FW returns tx power in intervals of 0.5 dBm
1290 Convert it back to intervals of 1 dBm */
1291 classa_stats->max_pwr =
1292 roundup(classa_stats->max_pwr, 2) >> 1;
1293 WMA_LOGD("peer tx rate flags:%d nss:%d max_txpwr:%d",
1294 node->rate_flags, node->nss,
1295 classa_stats->max_pwr);
1296 }
1297
1298 if (node->fw_stats_set & FW_STATS_SET) {
1299 WMA_LOGD("<--STATS RSP VDEV_ID:%d", vdev_id);
1300 wma_post_stats(wma, node);
1301 }
1302 }
1303}
1304
1305/**
1306 * wma_post_link_status() - post link status to SME
1307 * @pGetLinkStatus: SME Link status
1308 * @link_status: Link status
1309 *
1310 * Return: none
1311 */
1312void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
1313 uint8_t link_status)
1314{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301315 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316 cds_msg_t sme_msg = { 0 };
1317
1318 pGetLinkStatus->linkStatus = link_status;
1319 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
1320 sme_msg.bodyptr = pGetLinkStatus;
1321 sme_msg.bodyval = 0;
1322
Anurag Chouhan6d760662016-02-20 16:05:43 +05301323 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301324 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001325 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301326 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 }
1328}
1329
1330/**
1331 * wma_link_status_event_handler() - link status event handler
1332 * @handle: wma handle
1333 * @cmd_param_info: data from event
1334 * @len: length
1335 *
1336 * Return: 0 for success or error code
1337 */
1338int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
1339 uint32_t len)
1340{
1341 tp_wma_handle wma = (tp_wma_handle) handle;
1342 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
1343 wmi_vdev_rate_stats_event_fixed_param *event;
1344 wmi_vdev_rate_ht_info *ht_info;
1345 struct wma_txrx_node *intr = wma->interfaces;
1346 uint8_t link_status = LINK_STATUS_LEGACY;
1347 int i;
1348
1349 param_buf =
1350 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
1351 if (!param_buf) {
1352 WMA_LOGA("%s: Invalid stats event", __func__);
1353 return -EINVAL;
1354 }
1355
1356 event = (wmi_vdev_rate_stats_event_fixed_param *) param_buf->fixed_param;
1357 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
1358
1359 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
1360 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
1361 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
1362 __func__, ht_info->vdevid, ht_info->tx_nss,
1363 ht_info->rx_nss, ht_info->tx_preamble,
1364 ht_info->rx_preamble);
1365 if (ht_info->vdevid < wma->max_bssid
1366 && intr[ht_info->vdevid].plink_status_req) {
1367 if (ht_info->tx_nss || ht_info->rx_nss)
1368 link_status = LINK_STATUS_MIMO;
1369
1370 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
1371 (ht_info->rx_preamble == LINK_RATE_VHT))
1372 link_status |= LINK_STATUS_VHT;
1373
1374 if (intr[ht_info->vdevid].nss == 2)
1375 link_status |= LINK_SUPPORT_MIMO;
1376
1377 if (intr[ht_info->vdevid].rate_flags &
1378 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
1379 eHAL_TX_RATE_VHT80))
1380 link_status |= LINK_SUPPORT_VHT;
1381
1382 wma_post_link_status(intr[ht_info->vdevid].plink_status_req,
1383 link_status);
1384 intr[ht_info->vdevid].plink_status_req = NULL;
1385 link_status = LINK_STATUS_LEGACY;
1386 }
1387
1388 ht_info++;
1389 }
1390
1391 return 0;
1392}
1393
1394/**
1395 * wma_stats_event_handler() - stats event handler
1396 * @handle: wma handle
1397 * @cmd_param_info: data from event
1398 * @len: length
1399 *
1400 * Return: 0 for success or error code
1401 */
1402int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
1403 uint32_t len)
1404{
1405 tp_wma_handle wma = (tp_wma_handle) handle;
1406 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
1407 wmi_stats_event_fixed_param *event;
1408 wmi_pdev_stats *pdev_stats;
1409 wmi_vdev_stats *vdev_stats;
1410 wmi_peer_stats *peer_stats;
1411 uint8_t i, *temp;
1412
1413
1414 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
1415 if (!param_buf) {
1416 WMA_LOGA("%s: Invalid stats event", __func__);
1417 return -EINVAL;
1418 }
1419 event = param_buf->fixed_param;
1420 temp = (uint8_t *) param_buf->data;
1421
1422 WMA_LOGD("%s: num_stats: pdev: %u vdev: %u peer %u",
1423 __func__, event->num_pdev_stats, event->num_vdev_stats,
1424 event->num_peer_stats);
1425 if (event->num_pdev_stats > 0) {
1426 for (i = 0; i < event->num_pdev_stats; i++) {
1427 pdev_stats = (wmi_pdev_stats *) temp;
1428 wma_update_pdev_stats(wma, pdev_stats);
1429 temp += sizeof(wmi_pdev_stats);
1430 }
1431 }
1432
1433 if (event->num_vdev_stats > 0) {
1434 for (i = 0; i < event->num_vdev_stats; i++) {
1435 vdev_stats = (wmi_vdev_stats *) temp;
1436 wma_update_vdev_stats(wma, vdev_stats);
1437 temp += sizeof(wmi_vdev_stats);
1438 }
1439 }
1440
1441 if (event->num_peer_stats > 0) {
1442 for (i = 0; i < event->num_peer_stats; i++) {
1443 peer_stats = (wmi_peer_stats *) temp;
1444 wma_update_peer_stats(wma, peer_stats);
1445 temp += sizeof(wmi_peer_stats);
1446 }
1447 }
1448
1449 WMA_LOGI("%s: Exit", __func__);
1450 return 0;
1451}
1452
1453/**
1454 * wma_send_link_speed() - send link speed to SME
1455 * @link_speed: link speed
1456 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301457 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301459QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301461 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 cds_msg_t sme_msg = { 0 };
1463 tSirLinkSpeedInfo *ls_ind =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301464 (tSirLinkSpeedInfo *) qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 if (!ls_ind) {
1466 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301467 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 } else {
1469 ls_ind->estLinkSpeed = link_speed;
1470 sme_msg.type = eWNI_SME_LINK_SPEED_IND;
1471 sme_msg.bodyptr = ls_ind;
1472 sme_msg.bodyval = 0;
1473
Anurag Chouhan6d760662016-02-20 16:05:43 +05301474 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301475 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001476 WMA_LOGE("%s: Fail to post linkspeed ind msg",
1477 __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301478 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001479 }
1480 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301481 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482}
1483
1484/**
1485 * wma_link_speed_event_handler() - link speed event handler
1486 * @handle: wma handle
1487 * @cmd_param_info: event data
1488 * @len: length
1489 *
1490 * Return: 0 for success or error code
1491 */
1492int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
1493 uint32_t len)
1494{
1495 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
1496 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301497 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498
1499 param_buf =
1500 (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *) cmd_param_info;
1501 if (!param_buf) {
1502 WMA_LOGE("%s: Invalid linkspeed event", __func__);
1503 return -EINVAL;
1504 }
1505 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301506 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
1507 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 return -EINVAL;
1509 }
1510 return 0;
1511}
1512
1513/**
1514 * wma_wni_cfg_dnld() - cfg download request
1515 * @handle: wma handle
1516 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301517 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301519QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301521 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301522 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523
1524 WMA_LOGD("%s: Enter", __func__);
1525
1526 if (NULL == mac) {
1527 WMA_LOGP("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301528 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301529 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001530 }
1531
1532 process_cfg_download_req(mac);
1533
1534 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301535 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536}
1537
1538/**
1539 * wma_unified_debug_print_event_handler() - debug print event handler
1540 * @handle: wma handle
1541 * @datap: data pointer
1542 * @len: length
1543 *
1544 * Return: 0 for success or error code
1545 */
1546int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
1547 uint32_t len)
1548{
1549 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
1550 uint8_t *data;
1551 uint32_t datalen;
1552
1553 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
1554 if (!param_buf) {
1555 WMA_LOGE("Get NULL point message from FW");
1556 return -ENOMEM;
1557 }
1558 data = param_buf->data;
1559 datalen = param_buf->num_data;
1560
1561#ifdef BIG_ENDIAN_HOST
1562 {
1563 char dbgbuf[500] = { 0 };
1564 memcpy(dbgbuf, data, datalen);
1565 SWAPME(dbgbuf, datalen);
1566 WMA_LOGD("FIRMWARE:%s", dbgbuf);
1567 return 0;
1568 }
1569#else
1570 WMA_LOGD("FIRMWARE:%s", data);
1571 return 0;
1572#endif /* BIG_ENDIAN_HOST */
1573}
1574
1575/**
1576 * wma_check_scan_in_progress() - check scan is progress or not
1577 * @handle: wma handle
1578 *
1579 * Return: true/false
1580 */
1581bool wma_check_scan_in_progress(WMA_HANDLE handle)
1582{
1583 tp_wma_handle wma_handle = handle;
1584 int i;
1585
1586 for (i = 0; i < wma_handle->max_bssid; i++) {
1587 if (wma_handle->interfaces[i].scan_info.scan_id) {
1588
1589 WMA_LOGE("%s: scan in progress on interface[%d],scanid = %d",
1590 __func__, i,
1591 wma_handle->interfaces[i].scan_info.scan_id);
1592 return true;
1593 }
1594 }
1595 return false;
1596}
1597
1598/**
1599 * wma_is_sap_active() - check sap is active or not
1600 * @handle: wma handle
1601 *
1602 * Return: true/false
1603 */
1604bool wma_is_sap_active(tp_wma_handle wma_handle)
1605{
1606 int i;
1607
1608 for (i = 0; i < wma_handle->max_bssid; i++) {
1609 if (!wma_handle->interfaces[i].vdev_up)
1610 continue;
1611 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
1612 wma_handle->interfaces[i].sub_type == 0)
1613 return true;
1614 }
1615 return false;
1616}
1617
1618/**
1619 * wma_is_p2p_go_active() - check p2p go is active or not
1620 * @handle: wma handle
1621 *
1622 * Return: true/false
1623 */
1624bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
1625{
1626 int i;
1627
1628 for (i = 0; i < wma_handle->max_bssid; i++) {
1629 if (!wma_handle->interfaces[i].vdev_up)
1630 continue;
1631 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
1632 wma_handle->interfaces[i].sub_type ==
1633 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
1634 return true;
1635 }
1636 return false;
1637}
1638
1639/**
1640 * wma_is_p2p_cli_active() - check p2p cli is active or not
1641 * @handle: wma handle
1642 *
1643 * Return: true/false
1644 */
1645bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
1646{
1647 int i;
1648
1649 for (i = 0; i < wma_handle->max_bssid; i++) {
1650 if (!wma_handle->interfaces[i].vdev_up)
1651 continue;
1652 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
1653 wma_handle->interfaces[i].sub_type ==
1654 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
1655 return true;
1656 }
1657 return false;
1658}
1659
1660/**
1661 * wma_is_sta_active() - check sta is active or not
1662 * @handle: wma handle
1663 *
1664 * Return: true/false
1665 */
1666bool wma_is_sta_active(tp_wma_handle wma_handle)
1667{
1668 int i;
1669
1670 for (i = 0; i < wma_handle->max_bssid; i++) {
1671 if (!wma_handle->interfaces[i].vdev_up)
1672 continue;
1673 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
1674 wma_handle->interfaces[i].sub_type == 0)
1675 return true;
1676 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
1677 return true;
1678 }
1679 return false;
1680}
1681
1682/**
1683 * wma_peer_phymode() - get phymode
1684 * @nw_type: nw type
1685 * @sta_type: sta type
1686 * @is_ht: is ht supported
1687 * @is_cw40: is channel width 40 supported
1688 * @is_vht: is vht supported
1689 * @is_cw_vht: is channel width 80 supported
1690 *
1691 * Return: WLAN_PHY_MODE
1692 */
1693WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
1694 uint8_t is_ht, uint8_t ch_width,
1695 uint8_t is_vht)
1696{
1697 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
1698
1699 switch (nw_type) {
1700 case eSIR_11B_NW_TYPE:
1701 phymode = MODE_11B;
1702 if (is_ht || is_vht)
1703 WMA_LOGE("HT/VHT is enabled with 11B NW type");
1704 break;
1705 case eSIR_11G_NW_TYPE:
1706 if (!(is_ht || is_vht)) {
1707 phymode = MODE_11G;
1708 break;
1709 }
1710 if (CH_WIDTH_40MHZ < ch_width)
1711 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
1712 if (ch_width)
1713 phymode = (is_vht) ?
1714 MODE_11AC_VHT40 : MODE_11NG_HT40;
1715 else
1716 phymode = (is_vht) ?
1717 MODE_11AC_VHT20 : MODE_11NG_HT20;
1718 break;
1719 case eSIR_11A_NW_TYPE:
1720 if (!(is_ht || is_vht)) {
1721 phymode = MODE_11A;
1722 break;
1723 }
1724 if (is_vht) {
1725#if CONFIG_160MHZ_SUPPORT != 0
1726 if (ch_width == CH_WIDTH_160MHZ)
1727 phymode = MODE_11AC_VHT160;
1728 else if (ch_width == CH_WIDTH_80P80MHZ)
1729 phymode = MODE_11AC_VHT80_80;
1730 else
1731#endif
1732 if (ch_width == CH_WIDTH_80MHZ)
1733 phymode = MODE_11AC_VHT80;
1734 else
1735 phymode = (ch_width) ?
1736 MODE_11AC_VHT40 : MODE_11AC_VHT20;
1737 } else
1738 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
1739 break;
1740 default:
1741 WMA_LOGP("%s: Invalid nw type %d", __func__, nw_type);
1742 break;
1743 }
1744 WMA_LOGD("%s: nw_type %d is_ht %d ch_width %d is_vht %d phymode %d",
1745 __func__, nw_type, is_ht, ch_width, is_vht, phymode);
1746
1747 return phymode;
1748}
1749
1750/**
1751 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
1752 * @wma_handle: wma handle
1753 * @vdev_id: vdev id
1754 * @value: value
1755 *
1756 * Return: 0 for success or return error
1757 */
1758int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
1759 uint8_t vdev_id, uint32_t value)
1760{
1761 struct ol_txrx_stats_req req;
1762 ol_txrx_vdev_handle vdev;
1763
1764 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
1765 if (!vdev) {
1766 WMA_LOGE("%s:Invalid vdev handle", __func__);
1767 return -EINVAL;
1768 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301769 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 req.stats_type_reset_mask = value;
Nirav Shahd2310422016-01-21 18:58:06 +05301771 ol_txrx_fw_stats_get(vdev, &req, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001772
1773 return 0;
1774}
1775
1776#ifdef HELIUMPLUS
1777#define SET_UPLOAD_MASK(_mask, _rate_info) \
1778 ((_mask) = 1 << (_rate_info ## _V2))
1779#else /* !HELIUMPLUS */
1780#define SET_UPLOAD_MASK(_mask, _rate_info) \
1781 ((_mask) = 1 << (_rate_info))
1782#endif
1783
Nirav Shah93e789e2016-04-14 19:47:43 +05301784#ifdef HELIUMPLUS
1785bool wma_is_valid_fw_stats_cmd(uint32_t value)
1786{
1787 if (value > (HTT_DBG_NUM_STATS + 1) ||
1788 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
1789 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
1790 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
1791 WMA_LOGE("%s: Not supported", __func__);
1792 return false;
1793 }
1794 return true;
1795}
1796#else
1797bool wma_is_valid_fw_stats_cmd(uint32_t value)
1798{
1799 if (value > (HTT_DBG_NUM_STATS + 1) ||
1800 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
1801 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
1802 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
1803 WMA_LOGE("%s: Not supported", __func__);
1804 return false;
1805 }
1806 return true;
1807}
1808#endif
1809
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810/**
1811 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
1812 * @wma_handle: wma handle
1813 * @vdev_id: vdev id
1814 * @value: value
1815 *
1816 * Return: 0 for success or return error
1817 */
1818int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
1819 uint8_t vdev_id, uint32_t value)
1820{
1821 struct ol_txrx_stats_req req;
1822 ol_txrx_vdev_handle vdev;
1823 uint32_t l_up_mask;
1824
1825 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
1826 if (!vdev) {
1827 WMA_LOGE("%s:Invalid vdev handle", __func__);
1828 return -EINVAL;
1829 }
Nirav Shah93e789e2016-04-14 19:47:43 +05301830
1831 if (wma_is_valid_fw_stats_cmd(value) == false)
1832 return -EINVAL;
1833
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301834 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 req.print.verbose = 1;
1836
Nirav Shah93e789e2016-04-14 19:47:43 +05301837 /* TODO: Need to check how to avoid mem leak*/
1838 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839 req.stats_type_upload_mask = l_up_mask;
1840
Nirav Shahd2310422016-01-21 18:58:06 +05301841 ol_txrx_fw_stats_get(vdev, &req, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001842
1843 return 0;
1844}
1845
1846/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 * wma_get_stats_rsp_buf() - fill get stats response buffer
1848 * @get_stats_param: get stats parameters
1849 *
1850 * Return: stats response buffer
1851 */
1852static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
1853 (tAniGetPEStatsReq *get_stats_param)
1854{
1855 tAniGetPEStatsRsp *stats_rsp_params;
1856 uint32_t len, temp_mask, counter = 0;
1857
1858 len = sizeof(tAniGetPEStatsRsp);
1859 temp_mask = get_stats_param->statsMask;
1860
1861 while (temp_mask) {
1862 if (temp_mask & 1) {
1863 switch (counter) {
1864 case eCsrSummaryStats:
1865 len += sizeof(tCsrSummaryStatsInfo);
1866 break;
1867 case eCsrGlobalClassAStats:
1868 len += sizeof(tCsrGlobalClassAStatsInfo);
1869 break;
1870 case eCsrGlobalClassBStats:
1871 len += sizeof(tCsrGlobalClassBStatsInfo);
1872 break;
1873 case eCsrGlobalClassCStats:
1874 len += sizeof(tCsrGlobalClassCStatsInfo);
1875 break;
1876 case eCsrGlobalClassDStats:
1877 len += sizeof(tCsrGlobalClassDStatsInfo);
1878 break;
1879 case eCsrPerStaStats:
1880 len += sizeof(tCsrPerStaStatsInfo);
1881 break;
1882 }
1883 }
1884
1885 counter++;
1886 temp_mask >>= 1;
1887 }
1888
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301889 stats_rsp_params = (tAniGetPEStatsRsp *) qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 if (!stats_rsp_params) {
1891 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301892 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893 return NULL;
1894 }
1895
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301896 qdf_mem_zero(stats_rsp_params, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 stats_rsp_params->staId = get_stats_param->staId;
1898 stats_rsp_params->statsMask = get_stats_param->statsMask;
1899 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
1900 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301901 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 return stats_rsp_params;
1903}
1904
1905/**
1906 * wma_get_stats_req() - get stats request
1907 * @handle: wma handle
1908 * @get_stats_param: stats params
1909 *
1910 * Return: none
1911 */
1912void wma_get_stats_req(WMA_HANDLE handle,
1913 tAniGetPEStatsReq *get_stats_param)
1914{
1915 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1916 struct wma_txrx_node *node;
Govind Singh4863da42016-03-08 11:45:00 +05301917 struct pe_stats_req cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05301919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920
1921 WMA_LOGD("%s: Enter", __func__);
1922 node = &wma_handle->interfaces[get_stats_param->sessionId];
1923 if (node->stats_rsp) {
1924 pGetPEStatsRspParams = node->stats_rsp;
1925 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
1926 pGetPEStatsRspParams->statsMask ==
1927 get_stats_param->statsMask) {
1928 WMA_LOGI("Stats for staId %d with stats mask %d "
1929 "is pending.... ignore new request",
1930 get_stats_param->staId,
1931 get_stats_param->statsMask);
1932 goto end;
1933 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301934 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935 node->stats_rsp = NULL;
1936 node->fw_stats_set = 0;
1937 }
1938 }
1939
1940 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
1941 if (!pGetPEStatsRspParams)
1942 goto end;
1943
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001944 node->fw_stats_set = 0;
1945 node->stats_rsp = pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05301946
1947 cmd.session_id = get_stats_param->sessionId;
1948 if (wmi_unified_get_stats_cmd(wma_handle->wmi_handle, &cmd,
1949 node->bssid)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950
1951 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
1952 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 goto failed;
1954 }
1955
1956 goto end;
1957failed:
1958
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301959 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 node->stats_rsp = NULL;
1961 /* send response to UMAC */
1962 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
1963 0);
1964end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301965 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 WMA_LOGD("%s: Exit", __func__);
1967 return;
1968}
1969
1970/**
1971 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
1972 * @vdev_id: vdev id
1973 * @buffer_size: size of buffer
1974 *
1975 * Return: none
1976 */
1977void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
1978{
1979 tp_wma_handle wma;
1980 struct beacon_info *beacon;
1981 uint8_t *buf;
1982 uint32_t buf_size;
1983
Anurag Chouhan6d760662016-02-20 16:05:43 +05301984 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 if (!wma) {
1986 WMA_LOGE("%s: Invalid WMA handle", __func__);
1987 return NULL;
1988 }
1989
1990 if (vdev_id >= wma->max_bssid) {
1991 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
1992 return NULL;
1993 }
1994
1995 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
1996 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
1997 return NULL;
1998 }
1999
2000 beacon = wma->interfaces[vdev_id].beacon;
2001
2002 if (!beacon) {
2003 WMA_LOGE("%s: beacon invalid", __func__);
2004 return NULL;
2005 }
2006
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302007 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008
Nirav Shahcbc6d722016-03-01 16:24:53 +05302009 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302010 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011
2012 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302013 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
2015 return NULL;
2016 }
2017
Nirav Shahcbc6d722016-03-01 16:24:53 +05302018 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002019
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302020 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021
2022 if (buffer_size)
2023 *buffer_size = buf_size;
2024
2025 return buf;
2026}
2027
2028/**
2029 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
2030 * @vdev_id: vdev id
2031 *
2032 * Return: mac address
2033 */
2034uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
2035{
2036 tp_wma_handle wma;
2037
Anurag Chouhan6d760662016-02-20 16:05:43 +05302038 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039 if (!wma) {
2040 WMA_LOGE("%s: Invalid WMA handle", __func__);
2041 return NULL;
2042 }
2043
2044 if (vdev_id >= wma->max_bssid) {
2045 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2046 return NULL;
2047 }
2048
2049 return wma->interfaces[vdev_id].addr;
2050}
2051
2052/**
2053 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
2054 * @vdev_id: vdev id
2055 *
2056 * Return: entry from vdev table
2057 */
2058struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
2059{
2060 tp_wma_handle wma;
2061
Anurag Chouhan6d760662016-02-20 16:05:43 +05302062 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 if (!wma) {
2064 WMA_LOGE("%s: Invalid WMA handle", __func__);
2065 return NULL;
2066 }
2067
2068 if (vdev_id >= wma->max_bssid) {
2069 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
2070 return NULL;
2071 }
2072
2073 return &wma->interfaces[vdev_id];
2074}
2075
2076/**
2077 * wma_is_vdev_up() - return whether a vdev is up
2078 * @vdev_id: vdev id
2079 *
2080 * Return: true if the vdev is up, false otherwise
2081 */
2082bool wma_is_vdev_up(uint8_t vdev_id)
2083{
2084 struct wma_txrx_node *vdev = wma_get_interface_by_vdev_id(vdev_id);
2085 if (vdev)
2086 return vdev->vdev_up;
2087 else
2088 return false;
2089}
2090
2091#if defined(QCA_WIFI_FTM)
2092/**
2093 * wma_utf_rsp() - utf response
2094 * @wma_handle: wma handle
2095 * @payload: payload
2096 * @len: length of payload
2097 *
2098 * Return: 0 for success or error code
2099 */
2100int wma_utf_rsp(tp_wma_handle wma_handle, uint8_t **payload, uint32_t *len)
2101{
2102 int ret = -1;
2103 uint32_t payload_len;
2104
2105 payload_len = wma_handle->utf_event_info.length;
2106 if (payload_len) {
2107 ret = 0;
2108
2109 /*
2110 * The first 4 bytes holds the payload size
2111 * and the actual payload sits next to it
2112 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302113 *payload = (uint8_t *) qdf_mem_malloc((uint32_t) payload_len
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114 + sizeof(A_UINT32));
2115 *(A_UINT32 *) &(*payload[0]) =
2116 wma_handle->utf_event_info.length;
2117 memcpy(*payload + sizeof(A_UINT32),
2118 wma_handle->utf_event_info.data, payload_len);
2119 wma_handle->utf_event_info.length = 0;
2120 *len = payload_len;
2121 }
2122
2123 return ret;
2124}
2125
2126/**
2127 * wma_post_ftm_response() - post ftm response to upper layer
2128 * @wma_handle: wma handle
2129 *
2130 * Return: none
2131 */
2132static void wma_post_ftm_response(tp_wma_handle wma_handle)
2133{
2134 int ret;
2135 uint8_t *payload;
2136 uint32_t data_len;
2137 cds_msg_t msg = { 0 };
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302138 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139
2140 ret = wma_utf_rsp(wma_handle, &payload, &data_len);
2141
2142 if (ret) {
2143 return;
2144 }
2145
2146 sys_build_message_header(SYS_MSG_ID_FTM_RSP, &msg);
2147 msg.bodyptr = payload;
2148 msg.bodyval = 0;
2149
2150 status = cds_mq_post_message(CDS_MQ_ID_SYS, &msg);
2151
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302152 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002153 WMA_LOGE("failed to post ftm response to SYS");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302154 qdf_mem_free(payload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002155 }
2156}
2157
2158/**
2159 * wma_process_utf_event() - process utf event
2160 * @handle: wma handle
2161 * @datap: data buffer
2162 * @dataplen: data length
2163 *
2164 * Return: 0 for success or error code
2165 */
2166static int
2167wma_process_utf_event(WMA_HANDLE handle, uint8_t *datap, uint32_t dataplen)
2168{
2169 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05302170 struct seg_hdr_info segHdrInfo;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 uint8_t totalNumOfSegments, currentSeq;
2172 WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf;
2173 uint8_t *data;
2174 uint32_t datalen;
2175
2176 param_buf = (WMI_PDEV_UTF_EVENTID_param_tlvs *) datap;
2177 if (!param_buf) {
2178 WMA_LOGE("Get NULL point message from FW");
2179 return -EINVAL;
2180 }
2181 data = param_buf->data;
2182 datalen = param_buf->num_data;
2183
Govind Singhd76a5b02016-03-08 15:12:14 +05302184 segHdrInfo = *(struct seg_hdr_info *) &(data[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185
2186 wma_handle->utf_event_info.currentSeq = (segHdrInfo.segmentInfo & 0xF);
2187
2188 currentSeq = (segHdrInfo.segmentInfo & 0xF);
2189 totalNumOfSegments = (segHdrInfo.segmentInfo >> 4) & 0xF;
2190
2191 datalen = datalen - sizeof(segHdrInfo);
2192
2193 if (currentSeq == 0) {
2194 wma_handle->utf_event_info.expectedSeq = 0;
2195 wma_handle->utf_event_info.offset = 0;
2196 } else {
2197 if (wma_handle->utf_event_info.expectedSeq != currentSeq)
2198 WMA_LOGE("Mismatch in expecting seq expected"
2199 " Seq %d got seq %d",
2200 wma_handle->utf_event_info.expectedSeq,
2201 currentSeq);
2202 }
2203
2204 memcpy(&wma_handle->utf_event_info.
2205 data[wma_handle->utf_event_info.offset],
2206 &data[sizeof(segHdrInfo)], datalen);
2207 wma_handle->utf_event_info.offset =
2208 wma_handle->utf_event_info.offset + datalen;
2209 wma_handle->utf_event_info.expectedSeq++;
2210
2211 if (wma_handle->utf_event_info.expectedSeq == totalNumOfSegments) {
2212 if (wma_handle->utf_event_info.offset != segHdrInfo.len)
2213 WMA_LOGE("All segs received total len mismatch.."
2214 " len %zu total len %d",
2215 wma_handle->utf_event_info.offset,
2216 segHdrInfo.len);
2217
2218 wma_handle->utf_event_info.length =
2219 wma_handle->utf_event_info.offset;
2220 }
2221
2222 wma_post_ftm_response(wma_handle);
2223
2224 return 0;
2225}
2226
2227/**
2228 * wma_utf_detach() - utf detach
2229 * @wma_handle: wma handle
2230 *
2231 * Return: none
2232 */
2233void wma_utf_detach(tp_wma_handle wma_handle)
2234{
2235 if (wma_handle->utf_event_info.data) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302236 qdf_mem_free(wma_handle->utf_event_info.data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237 wma_handle->utf_event_info.data = NULL;
2238 wma_handle->utf_event_info.length = 0;
2239 wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
2240 WMI_PDEV_UTF_EVENTID);
2241 }
2242}
2243
2244/**
2245 * wma_utf_attach() - utf attach
2246 * @wma_handle: wma handle
2247 *
2248 * Return: none
2249 */
2250void wma_utf_attach(tp_wma_handle wma_handle)
2251{
2252 int ret;
2253
2254 wma_handle->utf_event_info.data = (unsigned char *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302255 qdf_mem_malloc(MAX_UTF_EVENT_LENGTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002256 wma_handle->utf_event_info.length = 0;
2257
2258 ret = wmi_unified_register_event_handler(wma_handle->wmi_handle,
2259 WMI_PDEV_UTF_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05302260 wma_process_utf_event,
2261 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262
2263 if (ret)
2264 WMA_LOGP("%s: Failed to register UTF event callback", __func__);
2265}
2266
2267/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002268 * wma_utf_cmd() - utf command
2269 * @wma_handle: wma handle
2270 * @data: data
2271 * @len: length
2272 *
Govind Singhd76a5b02016-03-08 15:12:14 +05302273 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002274 */
Govind Singhd76a5b02016-03-08 15:12:14 +05302275QDF_STATUS wma_utf_cmd(tp_wma_handle wma_handle, uint8_t *data, uint16_t len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276{
Govind Singhd76a5b02016-03-08 15:12:14 +05302277 struct pdev_utf_params param = {0};
2278
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 wma_handle->utf_event_info.length = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05302280 param.utf_payload = data;
2281 param.len = len;
2282
2283 return wmi_unified_pdev_utf_cmd_send(wma_handle->wmi_handle, &param,
2284 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285}
2286
2287/**
2288 * wma_process_ftm_command() - process ftm command
2289 * @wma_handle: wma handle
2290 * @msg_buffer: message buffer
2291 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302292 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302294QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295wma_process_ftm_command(tp_wma_handle wma_handle,
2296 struct ar6k_testmode_cmd_data *msg_buffer)
2297{
2298 uint8_t *data = NULL;
2299 uint16_t len = 0;
2300 int ret;
2301
2302 if (!msg_buffer)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302303 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002304
Anurag Chouhan6d760662016-02-20 16:05:43 +05302305 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002306 WMA_LOGE("FTM command issued in non-FTM mode");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302307 qdf_mem_free(msg_buffer->data);
2308 qdf_mem_free(msg_buffer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302309 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310 }
2311
2312 data = msg_buffer->data;
2313 len = msg_buffer->len;
2314
2315 ret = wma_utf_cmd(wma_handle, data, len);
2316
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302317 qdf_mem_free(msg_buffer->data);
2318 qdf_mem_free(msg_buffer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319
2320 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302321 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002322
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302323 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324}
2325#endif /* QCA_WIFI_FTM */
2326
2327/**
2328 * wma_get_wcnss_software_version() - get wcnss software version
2329 * @p_cds_gctx: cds context
2330 * @pVersion: version pointer
2331 * @versionBufferSize: buffer size
2332 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302333 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002334 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302335QDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 uint8_t *pVersion,
2337 uint32_t versionBufferSize)
2338{
2339 tp_wma_handle wma_handle;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302340 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341
2342 if (NULL == wma_handle) {
2343 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302344 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002345 }
2346
2347 snprintf(pVersion, versionBufferSize, "%x",
2348 (unsigned int)wma_handle->target_fw_version);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302349 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350}
2351
2352/**
2353 * wma_get_tx_rx_ss_from_config() - Get Tx/Rx spatial stream from HW mode config
2354 * @mac_ss: Config which indicates the HW mode as per 'hw_mode_ss_config'
2355 * @tx_ss: Contains the Tx spatial stream
2356 * @rx_ss: Contains the Rx spatial stream
2357 *
2358 * Returns the number of spatial streams of Tx and Rx
2359 *
2360 * Return: None
2361 */
2362void wma_get_tx_rx_ss_from_config(enum hw_mode_ss_config mac_ss,
2363 uint32_t *tx_ss,
2364 uint32_t *rx_ss)
2365{
2366 switch (mac_ss) {
2367 case HW_MODE_SS_0x0:
2368 *tx_ss = 0;
2369 *rx_ss = 0;
2370 break;
2371 case HW_MODE_SS_1x1:
2372 *tx_ss = 1;
2373 *rx_ss = 1;
2374 break;
2375 case HW_MODE_SS_2x2:
2376 *tx_ss = 2;
2377 *rx_ss = 2;
2378 break;
2379 case HW_MODE_SS_3x3:
2380 *tx_ss = 3;
2381 *rx_ss = 3;
2382 break;
2383 case HW_MODE_SS_4x4:
2384 *tx_ss = 4;
2385 *rx_ss = 4;
2386 break;
2387 default:
2388 *tx_ss = 0;
2389 *rx_ss = 0;
2390 }
2391}
2392
2393/**
2394 * wma_get_matching_hw_mode_index() - Get matching HW mode index
2395 * @wma: WMA handle
2396 * @mac0_tx_ss: Number of tx spatial streams of MAC0
2397 * @mac0_rx_ss: Number of rx spatial streams of MAC0
2398 * @mac0_bw: Bandwidth of MAC0 of type 'hw_mode_bandwidth'
2399 * @mac1_tx_ss: Number of tx spatial streams of MAC1
2400 * @mac1_rx_ss: Number of rx spatial streams of MAC1
2401 * @mac1_bw: Bandwidth of MAC1 of type 'hw_mode_bandwidth'
2402 * @dbs: DBS capability of type 'hw_mode_dbs_capab'
2403 * @dfs: Agile DFS capability of type 'hw_mode_agile_dfs_capab'
2404 *
2405 * Fetches the HW mode index corresponding to the HW mode provided
2406 *
2407 * Return: Positive hw mode index in case a match is found or a negative
2408 * value, otherwise
2409 */
2410static int8_t wma_get_matching_hw_mode_index(tp_wma_handle wma,
2411 uint32_t mac0_tx_ss, uint32_t mac0_rx_ss,
2412 enum hw_mode_bandwidth mac0_bw,
2413 uint32_t mac1_tx_ss, uint32_t mac1_rx_ss,
2414 enum hw_mode_bandwidth mac1_bw,
2415 enum hw_mode_dbs_capab dbs,
2416 enum hw_mode_agile_dfs_capab dfs)
2417{
2418 uint32_t i;
2419 uint32_t t_mac0_tx_ss, t_mac0_rx_ss, t_mac0_bw;
2420 uint32_t t_mac1_tx_ss, t_mac1_rx_ss, t_mac1_bw;
2421 uint32_t dbs_mode, agile_dfs_mode;
2422 int8_t found = -EINVAL;
2423
2424 if (!wma) {
2425 WMA_LOGE("%s: Invalid WMA handle", __func__);
2426 return found;
2427 }
2428
2429 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2430 t_mac0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(
2431 wma->hw_mode.hw_mode_list[i]);
2432 if (t_mac0_tx_ss != mac0_tx_ss)
2433 continue;
2434
2435 t_mac0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(
2436 wma->hw_mode.hw_mode_list[i]);
2437 if (t_mac0_rx_ss != mac0_rx_ss)
2438 continue;
2439
2440 t_mac0_bw = WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET(
2441 wma->hw_mode.hw_mode_list[i]);
2442 if (t_mac0_bw != mac0_bw)
2443 continue;
2444
2445 t_mac1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(
2446 wma->hw_mode.hw_mode_list[i]);
2447 if (t_mac1_tx_ss != mac1_tx_ss)
2448 continue;
2449
2450 t_mac1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(
2451 wma->hw_mode.hw_mode_list[i]);
2452 if (t_mac1_rx_ss != mac1_rx_ss)
2453 continue;
2454
2455 t_mac1_bw = WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET(
2456 wma->hw_mode.hw_mode_list[i]);
2457 if (t_mac1_bw != mac1_bw)
2458 continue;
2459
2460 dbs_mode = WMI_DBS_HW_MODE_DBS_MODE_GET(
2461 wma->hw_mode.hw_mode_list[i]);
2462 if (dbs_mode != dbs)
2463 continue;
2464
2465 agile_dfs_mode = WMI_DBS_HW_MODE_AGILE_DFS_GET(
2466 wma->hw_mode.hw_mode_list[i]);
2467 if (agile_dfs_mode != dfs)
2468 continue;
2469
2470 found = i;
2471 WMA_LOGI("%s: hw_mode index %d found",
2472 __func__, i);
2473 break;
2474 }
2475 return found;
2476}
2477
2478/**
2479 * wma_get_hw_mode_from_dbs_hw_list() - Get hw_mode index
2480 * @mac0_ss: MAC0 spatial stream configuration
2481 * @mac0_bw: MAC0 bandwidth configuration
2482 * @mac1_ss: MAC1 spatial stream configuration
2483 * @mac1_bw: MAC1 bandwidth configuration
2484 * @dbs: HW DBS capability
2485 * @dfs: HW Agile DFS capability
2486 *
2487 * Get the HW mode index corresponding to the HW modes spatial stream,
2488 * bandwidth, DBS and Agile DFS capability
2489 *
2490 * Return: Index number if a match is found or -negative value if not found
2491 */
2492int8_t wma_get_hw_mode_idx_from_dbs_hw_list(enum hw_mode_ss_config mac0_ss,
2493 enum hw_mode_bandwidth mac0_bw,
2494 enum hw_mode_ss_config mac1_ss,
2495 enum hw_mode_bandwidth mac1_bw,
2496 enum hw_mode_dbs_capab dbs,
2497 enum hw_mode_agile_dfs_capab dfs)
2498{
2499 tp_wma_handle wma;
2500 uint32_t mac0_tx_ss, mac0_rx_ss;
2501 uint32_t mac1_tx_ss, mac1_rx_ss;
2502
Anurag Chouhan6d760662016-02-20 16:05:43 +05302503 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 if (!wma) {
2505 WMA_LOGE("%s: Invalid WMA handle", __func__);
2506 return -EINVAL;
2507 }
2508
2509 wma_get_tx_rx_ss_from_config(mac0_ss, &mac0_tx_ss, &mac0_rx_ss);
2510 wma_get_tx_rx_ss_from_config(mac1_ss, &mac1_tx_ss, &mac1_rx_ss);
2511
2512 WMA_LOGI("%s: MAC0: TxSS=%d, RxSS=%d, BW=%d",
2513 __func__, mac0_tx_ss, mac0_rx_ss, mac0_bw);
2514 WMA_LOGI("%s: MAC1: TxSS=%d, RxSS=%d, BW=%d",
2515 __func__, mac1_tx_ss, mac1_rx_ss, mac1_bw);
2516 WMA_LOGI("%s: DBS capab=%d, Agile DFS capab=%d",
2517 __func__, dbs, dfs);
2518
2519 return wma_get_matching_hw_mode_index(wma, mac0_tx_ss, mac0_rx_ss,
2520 mac0_bw,
2521 mac1_tx_ss, mac1_rx_ss,
2522 mac1_bw,
2523 dbs, dfs);
2524}
2525
2526/**
2527 * wma_get_hw_mode_from_idx() - Get HW mode based on index
2528 * @idx: HW mode index
2529 * @hw_mode: HW mode params
2530 *
2531 * Fetches the HW mode parameters
2532 *
2533 * Return: Success if hw mode is obtained and the hw mode params
2534 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302535QDF_STATUS wma_get_hw_mode_from_idx(uint32_t idx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 struct sir_hw_mode_params *hw_mode)
2537{
2538 tp_wma_handle wma;
2539 uint32_t param;
2540
Anurag Chouhan6d760662016-02-20 16:05:43 +05302541 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 if (!wma) {
2543 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302544 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 }
2546
2547 if (idx > wma->num_dbs_hw_modes) {
2548 WMA_LOGE("%s: Invalid index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302549 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 }
2551
Mahesh Kumar Kalikot Veetild43e1652015-11-02 15:35:10 -08002552 if (!wma->num_dbs_hw_modes) {
2553 WMA_LOGE("%s: No dbs hw modes available", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302554 return QDF_STATUS_E_FAILURE;
Mahesh Kumar Kalikot Veetild43e1652015-11-02 15:35:10 -08002555 }
2556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 param = wma->hw_mode.hw_mode_list[idx];
2558
2559 hw_mode->mac0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param);
2560 hw_mode->mac0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(param);
2561 hw_mode->mac0_bw = WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET(param);
2562 hw_mode->mac1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(param);
2563 hw_mode->mac1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(param);
2564 hw_mode->mac1_bw = WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET(param);
2565 hw_mode->dbs_cap = WMI_DBS_HW_MODE_DBS_MODE_GET(param);
2566 hw_mode->agile_dfs_cap = WMI_DBS_HW_MODE_AGILE_DFS_GET(param);
2567
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302568 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569}
2570
2571/**
2572 * wma_get_num_dbs_hw_modes() - Get number of HW mode
2573 *
2574 * Fetches the number of DBS HW modes returned by the FW
2575 *
2576 * Return: Negative value on error or returns the number of DBS HW modes
2577 */
2578int8_t wma_get_num_dbs_hw_modes(void)
2579{
2580 tp_wma_handle wma;
2581
Anurag Chouhan6d760662016-02-20 16:05:43 +05302582 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 if (!wma) {
2584 WMA_LOGE("%s: Invalid WMA handle", __func__);
2585 return -EINVAL;
2586 }
2587 return wma->num_dbs_hw_modes;
2588}
2589
2590/**
2591 * wma_is_hw_dbs_capable() - Check if HW is DBS capable
2592 *
2593 * Checks if the HW is DBS capable
2594 *
2595 * Return: true if the HW is DBS capable
2596 */
2597bool wma_is_hw_dbs_capable(void)
2598{
2599 tp_wma_handle wma;
2600 uint32_t param, i, found = 0;
2601
Anurag Chouhan6d760662016-02-20 16:05:43 +05302602 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 if (!wma) {
2604 WMA_LOGE("%s: Invalid WMA handle", __func__);
2605 return false;
2606 }
2607
2608 if (!wma_is_dbs_enable()) {
2609 WMA_LOGI("%s: DBS is disabled", __func__);
2610 return false;
2611 }
2612
2613 WMA_LOGI("%s: DBS service bit map: %d", __func__,
2614 WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2615 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT));
2616
2617 /* The agreement with FW is that: To know if the target is DBS
2618 * capable, DBS needs to be supported both in the HW mode list
2619 * and in the service ready event
2620 */
2621 if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2622 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT)))
2623 return false;
2624
2625 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2626 param = wma->hw_mode.hw_mode_list[i];
2627 WMA_LOGI("%s: HW param: %x", __func__, param);
2628 if (WMI_DBS_HW_MODE_DBS_MODE_GET(param)) {
2629 WMA_LOGI("%s: HW (%d) is DBS capable", __func__, i);
2630 found = 1;
2631 break;
2632 }
2633 }
2634
2635 if (found)
2636 return true;
2637
2638 return false;
2639}
2640
2641/**
2642 * wma_is_hw_agile_dfs_capable() - Check if HW is agile DFS capable
2643 *
2644 * Checks if the HW is agile DFS capable
2645 *
2646 * Return: true if the HW is agile DFS capable
2647 */
2648bool wma_is_hw_agile_dfs_capable(void)
2649{
2650 tp_wma_handle wma;
2651 uint32_t param, i, found = 0;
2652
Anurag Chouhan6d760662016-02-20 16:05:43 +05302653 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002654 if (!wma) {
2655 WMA_LOGE("%s: Invalid WMA handle", __func__);
2656 return false;
2657 }
2658
2659 if (!wma_is_agile_dfs_enable()) {
2660 WMA_LOGI("%s: Agile DFS is disabled", __func__);
2661 return false;
2662 }
2663
2664 WMA_LOGI("%s: DBS service bit map: %d", __func__,
2665 WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2666 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT));
2667
2668 /* The agreement with FW is that to know if the target is Agile DFS
2669 * capable, DBS needs to be supported in the service bit map and
2670 * Agile DFS needs to be supported in the HW mode list
2671 */
2672 if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
2673 WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT)))
2674 return false;
2675
2676 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2677 param = wma->hw_mode.hw_mode_list[i];
2678 WMA_LOGI("%s: HW param: %x", __func__, param);
2679 if (WMI_DBS_HW_MODE_AGILE_DFS_GET(param)) {
2680 WMA_LOGI("%s: HW %d is agile DFS capable",
2681 __func__, i);
2682 found = 1;
2683 break;
2684 }
2685 }
2686
2687 if (found)
2688 return true;
2689
2690 return false;
2691}
2692
2693/**
2694 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
2695 * @vdev_id: VDEV whose MAC ID is required
2696 *
2697 * Get MAC id corresponding to a vdev id from the WMA structure
2698 *
2699 * Return: Negative value on failure and MAC id on success
2700 */
2701int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
2702{
2703 tp_wma_handle wma;
2704
Anurag Chouhan6d760662016-02-20 16:05:43 +05302705 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 if (!wma) {
2707 WMA_LOGE("%s: Invalid WMA handle", __func__);
2708 return -EINVAL;
2709 }
2710
2711 if (wma->interfaces)
2712 return wma->interfaces[vdev_id].mac_id;
2713
2714 return -EINVAL;
2715}
2716
2717/**
2718 * wma_get_old_and_new_hw_index() - Get the old and new HW index
2719 * @old_hw_mode_index: Value at this pointer contains the old HW mode index
2720 * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX
2721 * @new_hw_mode_index: Value at this pointer contains the new HW mode index
2722 * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX
2723 *
2724 * Get the old and new HW index configured in the driver
2725 *
2726 * Return: Failure in case the HW mode indices cannot be fetched and Success
2727 * otherwise. When no HW mode transition has happened the values of
2728 * old_hw_mode_index and new_hw_mode_index will be the same.
2729 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302730QDF_STATUS wma_get_old_and_new_hw_index(uint32_t *old_hw_mode_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 uint32_t *new_hw_mode_index)
2732{
2733 tp_wma_handle wma;
2734
Anurag Chouhan6d760662016-02-20 16:05:43 +05302735 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736 if (!wma) {
2737 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302738 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002739 }
2740
2741 *old_hw_mode_index = wma->old_hw_mode_index;
2742 *new_hw_mode_index = wma->new_hw_mode_index;
2743
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302744 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745}
2746
2747/**
2748 * wma_update_intf_hw_mode_params() - Update WMA params
2749 * @vdev_id: VDEV id whose params needs to be updated
2750 * @mac_id: MAC id to be updated
2751 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
2752 *
2753 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
2754 *
2755 * Return: None
2756 */
2757void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
2758 uint32_t cfgd_hw_mode_index)
2759{
2760 tp_wma_handle wma;
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002761 uint32_t param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002762
Anurag Chouhan6d760662016-02-20 16:05:43 +05302763 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764 if (!wma) {
2765 WMA_LOGE("%s: Invalid WMA handle", __func__);
2766 return;
2767 }
2768
2769 if (!wma->interfaces) {
2770 WMA_LOGE("%s: Interface is NULL", __func__);
2771 return;
2772 }
2773
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002774 if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) {
2775 WMA_LOGE("%s: Invalid index", __func__);
2776 return;
2777 }
2778
2779 param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 wma->interfaces[vdev_id].mac_id = mac_id;
2781 if (mac_id == 0) {
2782 wma->interfaces[vdev_id].tx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002783 WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 wma->interfaces[vdev_id].rx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002785 WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786 } else {
2787 wma->interfaces[vdev_id].tx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002788 WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002789 wma->interfaces[vdev_id].rx_streams =
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08002790 WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 }
2792}
2793
2794/**
2795 * wma_get_dbs_hw_modes() - Get the DBS HW modes for userspace
2796 * @one_by_one_dbs: 1x1 DBS capability of HW
2797 * @two_by_two_dbs: 2x2 DBS capability of HW
2798 *
2799 * Provides the DBS HW mode capability such as whether
2800 * 1x1 DBS, 2x2 DBS is supported by the HW or not.
2801 *
2802 * Return: Failure in case of error and 0 on success
2803 * one_by_one_dbs/two_by_two_dbs will be false,
2804 * if they are not supported.
2805 * one_by_one_dbs/two_by_two_dbs will be true,
2806 * if they are supported.
2807 * false values of one_by_one_dbs/two_by_two_dbs,
2808 * indicate DBS is disabled
2809 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302810QDF_STATUS wma_get_dbs_hw_modes(bool *one_by_one_dbs, bool *two_by_two_dbs)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811{
2812 tp_wma_handle wma;
2813 uint32_t i;
2814 int8_t found_one_by_one = -EINVAL, found_two_by_two = -EINVAL;
2815 uint32_t conf1_tx_ss, conf1_rx_ss;
2816 uint32_t conf2_tx_ss, conf2_rx_ss;
2817
2818 *one_by_one_dbs = false;
2819 *two_by_two_dbs = false;
2820
2821 if (wma_is_hw_dbs_capable() == false) {
2822 WMA_LOGE("%s: HW is not DBS capable", __func__);
2823 /* Caller will understand that DBS is disabled */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302824 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825
2826 }
2827
Anurag Chouhan6d760662016-02-20 16:05:43 +05302828 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 if (!wma) {
2830 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302831 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 }
2833
2834 /* To check 1x1 capability */
2835 wma_get_tx_rx_ss_from_config(HW_MODE_SS_1x1,
2836 &conf1_tx_ss, &conf1_rx_ss);
2837 /* To check 2x2 capability */
2838 wma_get_tx_rx_ss_from_config(HW_MODE_SS_2x2,
2839 &conf2_tx_ss, &conf2_rx_ss);
2840
2841 for (i = 0; i < wma->num_dbs_hw_modes; i++) {
2842 uint32_t t_conf0_tx_ss, t_conf0_rx_ss;
2843 uint32_t t_conf1_tx_ss, t_conf1_rx_ss;
2844 uint32_t dbs_mode;
2845
2846 t_conf0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(
2847 wma->hw_mode.hw_mode_list[i]);
2848 t_conf0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(
2849 wma->hw_mode.hw_mode_list[i]);
2850 t_conf1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(
2851 wma->hw_mode.hw_mode_list[i]);
2852 t_conf1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(
2853 wma->hw_mode.hw_mode_list[i]);
2854 dbs_mode = WMI_DBS_HW_MODE_DBS_MODE_GET(
2855 wma->hw_mode.hw_mode_list[i]);
2856
2857 if (((((t_conf0_tx_ss == conf1_tx_ss) &&
2858 (t_conf0_rx_ss == conf1_rx_ss)) ||
2859 ((t_conf1_tx_ss == conf1_tx_ss) &&
2860 (t_conf1_rx_ss == conf1_rx_ss))) &&
2861 (dbs_mode == HW_MODE_DBS)) &&
2862 (found_one_by_one < 0)) {
2863 found_one_by_one = i;
2864 WMA_LOGI("%s: 1x1 hw_mode index %d found",
2865 __func__, i);
2866 /* Once an entry is found, need not check for 1x1
2867 * again
2868 */
2869 continue;
2870 }
2871
2872 if (((((t_conf0_tx_ss == conf2_tx_ss) &&
2873 (t_conf0_rx_ss == conf2_rx_ss)) ||
2874 ((t_conf1_tx_ss == conf2_tx_ss) &&
2875 (t_conf1_rx_ss == conf2_rx_ss))) &&
2876 (dbs_mode == HW_MODE_DBS)) &&
2877 (found_two_by_two < 0)) {
2878 found_two_by_two = i;
2879 WMA_LOGI("%s: 2x2 hw_mode index %d found",
2880 __func__, i);
2881 /* Once an entry is found, need not check for 2x2
2882 * again
2883 */
2884 continue;
2885 }
2886 }
2887
2888 if (found_one_by_one >= 0)
2889 *one_by_one_dbs = true;
2890 if (found_two_by_two >= 0)
2891 *two_by_two_dbs = true;
2892
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302893 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894}
2895
2896/**
2897 * wma_get_current_hw_mode() - Get current HW mode params
2898 * @hw_mode: HW mode parameters
2899 *
2900 * Provides the current HW mode parameters if the HW mode is initialized
2901 * in the driver
2902 *
2903 * Return: Success if the current HW mode params are successfully populated
2904 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302905QDF_STATUS wma_get_current_hw_mode(struct sir_hw_mode_params *hw_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302907 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 uint32_t old_hw_index = 0, new_hw_index = 0;
2909
2910 WMA_LOGI("%s: Get the current hw mode", __func__);
2911
2912 status = wma_get_old_and_new_hw_index(&old_hw_index,
2913 &new_hw_index);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302914 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 WMA_LOGE("%s: Failed to get HW mode index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302916 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 }
2918
2919 if (new_hw_index == WMA_DEFAULT_HW_MODE_INDEX) {
2920 WMA_LOGE("%s: HW mode is not yet initialized", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302921 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 }
2923
2924 status = wma_get_hw_mode_from_idx(new_hw_index, hw_mode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302925 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 WMA_LOGE("%s: Failed to get HW mode index", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302927 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302929 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930}
2931
2932/**
2933 * wma_is_dbs_enable() - Check if master DBS control is enabled
2934 *
2935 * Checks if the master DBS control is enabled. This will be used
2936 * to override any other DBS capability
2937 *
2938 * Return: True if master DBS control is enabled
2939 */
2940bool wma_is_dbs_enable(void)
2941{
2942 tp_wma_handle wma;
2943
2944 if (wma_is_dual_mac_disabled_in_ini())
2945 return false;
2946
Anurag Chouhan6d760662016-02-20 16:05:43 +05302947 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 if (!wma) {
2949 WMA_LOGE("%s: Invalid WMA handle", __func__);
2950 return false;
2951 }
2952
2953 WMA_LOGD("%s: DBS=%d", __func__,
2954 WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config));
2955
2956 if (WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config))
2957 return true;
2958
2959 return false;
2960}
2961
2962/**
2963 * wma_is_agile_dfs_enable() - Check if master Agile DFS control is enabled
2964 *
2965 * Checks if the master Agile DFS control is enabled. This will be used
2966 * to override any other Agile DFS capability
2967 *
2968 * Return: True if master Agile DFS control is enabled
2969 */
2970bool wma_is_agile_dfs_enable(void)
2971{
2972 tp_wma_handle wma;
2973
2974 if (wma_is_dual_mac_disabled_in_ini())
2975 return false;
2976
Anurag Chouhan6d760662016-02-20 16:05:43 +05302977 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978 if (!wma) {
2979 WMA_LOGE("%s: Invalid WMA handle", __func__);
2980 return false;
2981 }
2982
2983 WMA_LOGD("%s: DFS=%d Single mac with DFS=%d", __func__,
2984 WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(
2985 wma->dual_mac_cfg.cur_fw_mode_config),
2986 WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(
2987 wma->dual_mac_cfg.cur_scan_config));
2988
2989 if ((WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(
2990 wma->dual_mac_cfg.cur_fw_mode_config)) &&
2991 (WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(
2992 wma->dual_mac_cfg.cur_scan_config)))
2993 return true;
2994
2995 return false;
2996}
2997
2998/**
2999 * wma_get_updated_scan_config() - Get the updated scan configuration
3000 * @scan_config: Pointer containing the updated scan config
3001 * @dbs_scan: 0 or 1 indicating if DBS scan needs to be enabled/disabled
3002 * @dbs_plus_agile_scan: 0 or 1 indicating if DBS plus agile scan needs to be
3003 * enabled/disabled
3004 * @single_mac_scan_with_dfs: 0 or 1 indicating if single MAC scan with DFS
3005 * needs to be enabled/disabled
3006 *
3007 * Takes the current scan configuration and set the necessary scan config
3008 * bits to either 0/1 and provides the updated value to the caller who
3009 * can use this to pass it on to the FW
3010 *
3011 * Return: 0 on success
3012 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303013QDF_STATUS wma_get_updated_scan_config(uint32_t *scan_config,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014 bool dbs_scan,
3015 bool dbs_plus_agile_scan,
3016 bool single_mac_scan_with_dfs)
3017{
3018 tp_wma_handle wma;
3019
Anurag Chouhan6d760662016-02-20 16:05:43 +05303020 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 if (!wma) {
3022 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303023 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 }
3025 *scan_config = wma->dual_mac_cfg.cur_scan_config;
3026
3027 WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_SET(*scan_config, dbs_scan);
3028 WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_SET(*scan_config,
3029 dbs_plus_agile_scan);
3030 WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_SET(*scan_config,
3031 single_mac_scan_with_dfs);
3032
3033 WMA_LOGD("%s: *scan_config:%x ", __func__, *scan_config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303034 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035}
3036
3037/**
3038 * wma_get_updated_fw_mode_config() - Get the updated fw mode configuration
3039 * @fw_mode_config: Pointer containing the updated fw mode config
3040 * @dbs: 0 or 1 indicating if DBS needs to be enabled/disabled
3041 * @agile_dfs: 0 or 1 indicating if agile DFS needs to be enabled/disabled
3042 *
3043 * Takes the current fw mode configuration and set the necessary fw mode config
3044 * bits to either 0/1 and provides the updated value to the caller who
3045 * can use this to pass it on to the FW
3046 *
3047 * Return: 0 on success
3048 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303049QDF_STATUS wma_get_updated_fw_mode_config(uint32_t *fw_mode_config,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 bool dbs,
3051 bool agile_dfs)
3052{
3053 tp_wma_handle wma;
3054
Anurag Chouhan6d760662016-02-20 16:05:43 +05303055 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 if (!wma) {
3057 WMA_LOGE("%s: Invalid WMA handle", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303058 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 }
3060 *fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3061
3062 WMI_DBS_FW_MODE_CFG_DBS_SET(*fw_mode_config, dbs);
3063 WMI_DBS_FW_MODE_CFG_AGILE_DFS_SET(*fw_mode_config, agile_dfs);
3064
3065 WMA_LOGD("%s: *fw_mode_config:%x ", __func__, *fw_mode_config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303066 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067}
3068
3069/**
3070 * wma_get_dbs_config() - Get DBS bit
3071 *
3072 * Gets the DBS bit of fw_mode_config_bits
3073 *
3074 * Return: 0 or 1 to indicate the DBS bit
3075 */
3076bool wma_get_dbs_config(void)
3077{
3078 tp_wma_handle wma;
3079 uint32_t fw_mode_config;
3080
3081 if (wma_is_dual_mac_disabled_in_ini())
3082 return false;
3083
Anurag Chouhan6d760662016-02-20 16:05:43 +05303084 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003085 if (!wma) {
3086 WMA_LOGE("%s: Invalid WMA handle", __func__);
3087 /* We take that it is disabled and proceed */
3088 return false;
3089 }
3090 fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3091
3092 return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config);
3093}
3094
3095/**
3096 * wma_get_agile_dfs_config() - Get Agile DFS bit
3097 *
3098 * Gets the Agile DFS bit of fw_mode_config_bits
3099 *
3100 * Return: 0 or 1 to indicate the Agile DFS bit
3101 */
3102bool wma_get_agile_dfs_config(void)
3103{
3104 tp_wma_handle wma;
3105 uint32_t fw_mode_config;
3106
3107 if (wma_is_dual_mac_disabled_in_ini())
3108 return false;
3109
Anurag Chouhan6d760662016-02-20 16:05:43 +05303110 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111 if (!wma) {
3112 WMA_LOGE("%s: Invalid WMA handle", __func__);
3113 /* We take that it is disabled and proceed */
3114 return false;
3115 }
3116 fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config;
3117
3118 return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config);
3119}
3120
3121/**
3122 * wma_get_dbs_scan_config() - Get DBS scan bit
3123 *
3124 * Gets the DBS scan bit of concurrent_scan_config_bits
3125 *
3126 * Return: 0 or 1 to indicate the DBS scan bit
3127 */
3128bool wma_get_dbs_scan_config(void)
3129{
3130 tp_wma_handle wma;
3131 uint32_t scan_config;
3132
3133 if (wma_is_dual_mac_disabled_in_ini())
3134 return false;
3135
Anurag Chouhan6d760662016-02-20 16:05:43 +05303136 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137 if (!wma) {
3138 WMA_LOGE("%s: Invalid WMA handle", __func__);
3139 /* We take that it is disabled and proceed */
3140 return false;
3141 }
3142 scan_config = wma->dual_mac_cfg.cur_scan_config;
3143
3144 return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config);
3145}
3146
3147/**
3148 * wma_get_dbs_plus_agile_scan_config() - Get DBS plus agile scan bit
3149 *
3150 * Gets the DBS plus agile scan bit of concurrent_scan_config_bits
3151 *
3152 * Return: 0 or 1 to indicate the DBS plus agile scan bit
3153 */
3154bool wma_get_dbs_plus_agile_scan_config(void)
3155{
3156 tp_wma_handle wma;
3157 uint32_t scan_config;
3158
3159 if (wma_is_dual_mac_disabled_in_ini())
3160 return false;
3161
Anurag Chouhan6d760662016-02-20 16:05:43 +05303162 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 if (!wma) {
3164 WMA_LOGE("%s: Invalid WMA handle", __func__);
3165 /* We take that it is disabled and proceed */
3166 return false;
3167 }
3168 scan_config = wma->dual_mac_cfg.cur_scan_config;
3169
3170 return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config);
3171}
3172
3173/**
3174 * wma_get_single_mac_scan_with_dfs_config() - Get Single MAC scan with DFS bit
3175 *
3176 * Gets the Single MAC scan with DFS bit of concurrent_scan_config_bits
3177 *
3178 * Return: 0 or 1 to indicate the Single MAC scan with DFS bit
3179 */
3180bool wma_get_single_mac_scan_with_dfs_config(void)
3181{
3182 tp_wma_handle wma;
3183 uint32_t scan_config;
3184
3185 if (wma_is_dual_mac_disabled_in_ini())
3186 return false;
3187
Anurag Chouhan6d760662016-02-20 16:05:43 +05303188 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189 if (!wma) {
3190 WMA_LOGE("%s: Invalid WMA handle", __func__);
3191 /* We take that it is disabled and proceed */
3192 return false;
3193 }
3194 scan_config = wma->dual_mac_cfg.cur_scan_config;
3195
3196 return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config);
3197}
3198
3199/**
3200 * wma_is_dual_mac_disabled_in_ini() - Check if dual mac is disabled in INI
3201 *
3202 * Checks if the dual mac feature is disabled in INI
3203 *
3204 * Return: true if the dual mac feature is disabled from INI
3205 */
3206bool wma_is_dual_mac_disabled_in_ini(void)
3207{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303208 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209
3210 if (!mac) {
3211 WMA_LOGE("%s: Invalid mac pointer", __func__);
3212 return true;
3213 }
3214
3215 if (mac->dual_mac_feature_disable)
3216 return true;
3217
3218 return false;
3219}
3220
3221/**
3222 * wma_get_prev_dbs_config() - Get prev DBS bit
3223 *
3224 * Gets the previous DBS bit of fw_mode_config_bits
3225 *
3226 * Return: 0 or 1 to indicate the DBS bit
3227 */
3228bool wma_get_prev_dbs_config(void)
3229{
3230 tp_wma_handle wma;
3231 uint32_t fw_mode_config;
3232
3233 if (wma_is_dual_mac_disabled_in_ini())
3234 return false;
3235
Anurag Chouhan6d760662016-02-20 16:05:43 +05303236 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 if (!wma) {
3238 WMA_LOGE("%s: Invalid WMA handle", __func__);
3239 /* We take that it is disabled and proceed */
3240 return false;
3241 }
3242 fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config;
3243
3244 return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config);
3245}
3246
3247/**
3248 * wma_get_prev_agile_dfs_config() - Get prev Agile DFS bit
3249 *
3250 * Gets the previous Agile DFS bit of fw_mode_config_bits
3251 *
3252 * Return: 0 or 1 to indicate the Agile DFS bit
3253 */
3254bool wma_get_prev_agile_dfs_config(void)
3255{
3256 tp_wma_handle wma;
3257 uint32_t fw_mode_config;
3258
3259 if (wma_is_dual_mac_disabled_in_ini())
3260 return false;
3261
Anurag Chouhan6d760662016-02-20 16:05:43 +05303262 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 if (!wma) {
3264 WMA_LOGE("%s: Invalid WMA handle", __func__);
3265 /* We take that it is disabled and proceed */
3266 return false;
3267 }
3268 fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config;
3269
3270 return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config);
3271}
3272
3273/**
3274 * wma_get_prev_dbs_scan_config() - Get prev DBS scan bit
3275 *
3276 * Gets the previous DBS scan bit of concurrent_scan_config_bits
3277 *
3278 * Return: 0 or 1 to indicate the DBS scan bit
3279 */
3280bool wma_get_prev_dbs_scan_config(void)
3281{
3282 tp_wma_handle wma;
3283 uint32_t scan_config;
3284
3285 if (wma_is_dual_mac_disabled_in_ini())
3286 return false;
3287
Anurag Chouhan6d760662016-02-20 16:05:43 +05303288 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 if (!wma) {
3290 WMA_LOGE("%s: Invalid WMA handle", __func__);
3291 /* We take that it is disabled and proceed */
3292 return false;
3293 }
3294 scan_config = wma->dual_mac_cfg.prev_scan_config;
3295
3296 return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config);
3297}
3298
3299/**
3300 * wma_get_prev_dbs_plus_agile_scan_config() - Get prev DBS plus agile scan bit
3301 *
3302 * Gets the previous DBS plus agile scan bit of concurrent_scan_config_bits
3303 *
3304 * Return: 0 or 1 to indicate the DBS plus agile scan bit
3305 */
3306bool wma_get_prev_dbs_plus_agile_scan_config(void)
3307{
3308 tp_wma_handle wma;
3309 uint32_t scan_config;
3310
3311 if (wma_is_dual_mac_disabled_in_ini())
3312 return false;
3313
Anurag Chouhan6d760662016-02-20 16:05:43 +05303314 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003315 if (!wma) {
3316 WMA_LOGE("%s: Invalid WMA handle", __func__);
3317 /* We take that it is disabled and proceed */
3318 return false;
3319 }
3320 scan_config = wma->dual_mac_cfg.prev_scan_config;
3321
3322 return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config);
3323}
3324
3325/**
3326 * wma_get_prev_single_mac_scan_with_dfs_config() - Get prev Single MAC scan
3327 * with DFS bit
3328 *
3329 * Gets the previous Single MAC scan with DFS bit of concurrent_scan_config_bits
3330 *
3331 * Return: 0 or 1 to indicate the Single MAC scan with DFS bit
3332 */
3333bool wma_get_prev_single_mac_scan_with_dfs_config(void)
3334{
3335 tp_wma_handle wma;
3336 uint32_t scan_config;
3337
3338 if (wma_is_dual_mac_disabled_in_ini())
3339 return false;
3340
Anurag Chouhan6d760662016-02-20 16:05:43 +05303341 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342 if (!wma) {
3343 WMA_LOGE("%s: Invalid WMA handle", __func__);
3344 /* We take that it is disabled and proceed */
3345 return false;
3346 }
3347 scan_config = wma->dual_mac_cfg.prev_scan_config;
3348
3349 return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config);
3350}
3351
3352/**
3353 * wma_is_scan_simultaneous_capable() - Check if scan parallelization is
3354 * supported or not
3355 *
3356 * currently scan parallelization feature support is dependent on DBS but
3357 * it can be independent in future.
3358 *
3359 * Return: True if master DBS control is enabled
3360 */
3361bool wma_is_scan_simultaneous_capable(void)
3362{
3363 if (wma_is_hw_dbs_capable())
3364 return true;
3365
3366 return false;
3367}
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003368
3369/**
3370 * wma_get_vht_ch_width - return vht channel width
3371 *
3372 * Return: return vht channel width
3373 */
3374uint32_t wma_get_vht_ch_width(void)
3375{
3376 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303377 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08003378
3379 if (NULL == wm_hdl)
3380 return fw_ch_wd;
3381
3382 if (wm_hdl->vht_cap_info &
3383 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
3384 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
3385 else if (wm_hdl->vht_cap_info &
3386 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
3387 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
3388
3389 return fw_ch_wd;
3390}
Govind Singhd76a5b02016-03-08 15:12:14 +05303391
3392/**
3393 * wma_config_debug_module_cmd - set debug log config
3394 * @wmi_handle: wmi layer handle
3395 * @param: debug log parameter
3396 * @val: debug log value
3397 * @module_id_bitmap: debug module id bitmap
3398 * @bitmap_len: debug module bitmap length
3399 *
3400 * Return: QDF_STATUS_SUCCESS for success or error code
3401 */
3402QDF_STATUS
3403wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
3404 A_UINT32 val, A_UINT32 *module_id_bitmap,
3405 A_UINT32 bitmap_len)
3406{
3407 struct dbglog_params dbg_param;
3408 dbg_param.param = param;
3409 dbg_param.val = val;
3410 dbg_param.module_id_bitmap = module_id_bitmap;
3411 dbg_param.bitmap_len = bitmap_len;
3412
3413 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
3414}