blob: c263b366d36e18324d15a8fb1407c41937687433 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Amar Singhala297bfa2015-10-15 15:07:29 -07002 * Copyright (c) 2011-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 *
30 * This file lim_prop_exts_utils.cc contains the utility functions
31 * to populate, parse proprietary extensions required to
32 * support ANI feature set.
33 *
34 * Author: Chandra Modumudi
35 * Date: 11/27/02
36 * History:-
37 * Date Modified by Modification Information
38 * --------------------------------------------------------------------
39 *
40 */
41#include "ani_global.h"
42#include "wni_cfg.h"
43#include "sir_common.h"
44#include "sir_debug.h"
45#include "utils_api.h"
46#include "cfg_api.h"
47#include "lim_api.h"
48#include "lim_types.h"
49#include "lim_utils.h"
50#include "lim_assoc_utils.h"
51#include "lim_prop_exts_utils.h"
52#include "lim_ser_des_utils.h"
53#include "lim_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054#include "lim_ft_defs.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080055#include "lim_session.h"
Naveen Rawatc0c91cd2015-11-05 14:27:37 -080056#include "wma.h"
57
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080058#define LIM_GET_NOISE_MAX_TRY 5
Padma, Santhosh Kumar29df3622016-08-16 19:15:16 +053059
60/**
61 * get_local_power_constraint_probe_response() - extracts local constraint
62 * from probe response
63 * @beacon_struct: beacon structure
64 * @local_constraint: local constraint pointer
65 * @session: A pointer to session entry.
66 *
67 * Return: None
68 */
69#ifdef FEATURE_WLAN_ESE
70static void get_local_power_constraint_probe_response(
71 tpSirProbeRespBeacon beacon_struct,
72 int8_t *local_constraint,
73 tpPESession session)
74{
75 if (beacon_struct->eseTxPwr.present)
76 *local_constraint =
77 beacon_struct->eseTxPwr.power_limit;
78 session->is_ese_version_ie_present =
79 beacon_struct->is_ese_ver_ie_present;
80}
81#else
82static void get_local_power_constraint_probe_response(
83 tpSirProbeRespBeacon beacon_struct,
84 int8_t *local_constraint,
85 tpPESession session)
86{
87
88}
89#endif
90
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091/**
92 * lim_extract_ap_capability() - extract AP's HCF/WME/WSM capability
93 * @mac_ctx: Pointer to Global MAC structure
94 * @p_ie: Pointer to starting IE in Beacon/Probe Response
95 * @ie_len: Length of all IEs combined
96 * @qos_cap: Bits are set according to capabilities
97 * @prop_cap: Pointer to prop info IE.
98 * @uapsd: pointer to uapsd
99 * @local_constraint: Pointer to local power constraint.
100 * @session: A pointer to session entry.
101 *
102 * This function is called to extract AP's HCF/WME/WSM capability
103 * from the IEs received from it in Beacon/Probe Response frames
104 *
105 * Return: None
106 */
107void
108lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie,
109 uint16_t ie_len, uint8_t *qos_cap, uint16_t *prop_cap, uint8_t *uapsd,
Amar Singhala297bfa2015-10-15 15:07:29 -0700110 int8_t *local_constraint, tpPESession session)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111{
112 tSirProbeRespBeacon *beacon_struct;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113 uint32_t enable_txbf_20mhz;
114 tSirRetStatus cfg_set_status = eSIR_FAILURE;
115 tSirRetStatus cfg_get_status = eSIR_FAILURE;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700116 uint8_t ap_bcon_ch_width;
117 bool new_ch_width_dfn = false;
118 tDot11fIEVHTOperation *vht_op;
119 uint8_t fw_vht_ch_wd;
120 uint8_t vht_ch_wd;
121 uint8_t center_freq_diff;
Kiran Kumar Lokere1d4094e2016-08-31 19:04:04 -0700122 struct s_ext_cap *ext_cap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800123
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530124 beacon_struct = qdf_mem_malloc(sizeof(tSirProbeRespBeacon));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800125 if (NULL == beacon_struct) {
126 lim_log(mac_ctx, LOGE, FL("Unable to allocate memory"));
127 return;
128 }
129
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530130 qdf_mem_set((uint8_t *) beacon_struct, sizeof(tSirProbeRespBeacon), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 *qos_cap = 0;
132 *prop_cap = 0;
133 *uapsd = 0;
134 lim_log(mac_ctx, LOG3,
135 FL("In lim_extract_ap_capability: The IE's being received:"));
136 sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG3, p_ie, ie_len);
137 if (sir_parse_beacon_ie(mac_ctx, beacon_struct, p_ie,
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700138 (uint32_t) ie_len) != eSIR_SUCCESS) {
139 lim_log(mac_ctx, LOGE, FL(
140 "sir_parse_beacon_ie failed to parse beacon"));
141 qdf_mem_free(beacon_struct);
142 return;
143 }
144 if (beacon_struct->wmeInfoPresent ||
145 beacon_struct->wmeEdcaPresent ||
146 beacon_struct->HTCaps.present)
147 LIM_BSS_CAPS_SET(WME, *qos_cap);
148 if (LIM_BSS_CAPS_GET(WME, *qos_cap)
149 && beacon_struct->wsmCapablePresent)
150 LIM_BSS_CAPS_SET(WSM, *qos_cap);
151 if (beacon_struct->propIEinfo.capabilityPresent)
152 *prop_cap = beacon_struct->propIEinfo.capability;
153 if (beacon_struct->HTCaps.present)
154 mac_ctx->lim.htCapabilityPresentInBeacon = 1;
155 else
156 mac_ctx->lim.htCapabilityPresentInBeacon = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700158 lim_log(mac_ctx, LOG1, FL(
159 "Bcon: VHTCap.present %d SU Beamformer %d BSS_VHT_CAPABLE %d"),
160 beacon_struct->VHTCaps.present,
161 beacon_struct->VHTCaps.suBeamFormerCap,
162 IS_BSS_VHT_CAPABLE(beacon_struct->VHTCaps));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700164 vht_op = &beacon_struct->VHTOperation;
165 if (IS_BSS_VHT_CAPABLE(beacon_struct->VHTCaps) &&
166 vht_op->present &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167 session->vhtCapability) {
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700168 session->vhtCapabilityPresentInBeacon = 1;
169 if (((beacon_struct->Vendor1IEPresent &&
Kapil Gupta4b2efbb2016-10-03 13:07:20 +0530170 beacon_struct->vendor_vht_ie.present &&
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700171 beacon_struct->Vendor3IEPresent)) &&
172 (((beacon_struct->VHTCaps.txMCSMap & VHT_MCS_3x3_MASK) ==
173 VHT_MCS_3x3_MASK) &&
174 ((beacon_struct->VHTCaps.txMCSMap & VHT_MCS_2x2_MASK) !=
175 VHT_MCS_2x2_MASK)))
Krunal Soni53993f72016-07-08 18:20:03 -0700176 session->vht_config.su_beam_formee = 0;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700177 } else {
178 session->vhtCapabilityPresentInBeacon = 0;
179 }
180
181 if (session->vhtCapabilityPresentInBeacon == 1 &&
Krunal Soni53993f72016-07-08 18:20:03 -0700182 session->vht_config.su_beam_formee == 0) {
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700183 cfg_set_status = cfg_set_int(mac_ctx,
184 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
185 0);
186 if (cfg_set_status != eSIR_SUCCESS)
187 lim_log(mac_ctx, LOGP, FL(
188 "Set VHT_SU_BEAMFORMEE_CAP Fail"));
189 }
190 if (session->vhtCapabilityPresentInBeacon == 1 &&
191 !session->htSupportedChannelWidthSet) {
192 cfg_get_status = wlan_cfg_get_int(mac_ctx,
193 WNI_CFG_VHT_ENABLE_TXBF_20MHZ,
194 &enable_txbf_20mhz);
195 if ((IS_SIR_STATUS_SUCCESS(cfg_get_status)) &&
196 (false == enable_txbf_20mhz))
Krunal Soni53993f72016-07-08 18:20:03 -0700197 session->vht_config.su_beam_formee = 0;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700198 } else if (session->vhtCapabilityPresentInBeacon &&
199 vht_op->chanWidth) {
200 /* If VHT is supported min 80 MHz support is must */
201 ap_bcon_ch_width = vht_op->chanWidth;
202 if ((ap_bcon_ch_width == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) &&
203 vht_op->chanCenterFreqSeg2) {
204 new_ch_width_dfn = true;
205 if (vht_op->chanCenterFreqSeg2 >
206 vht_op->chanCenterFreqSeg1)
207 center_freq_diff = vht_op->chanCenterFreqSeg2 -
208 vht_op->chanCenterFreqSeg1;
209 else
210 center_freq_diff = vht_op->chanCenterFreqSeg1 -
211 vht_op->chanCenterFreqSeg2;
212 if (center_freq_diff == 8)
213 ap_bcon_ch_width =
214 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
215 else if (center_freq_diff > 16)
216 ap_bcon_ch_width =
217 WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800218 }
Naveen Rawatc0c91cd2015-11-05 14:27:37 -0800219
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700220 fw_vht_ch_wd = wma_get_vht_ch_width();
221 vht_ch_wd = QDF_MIN(fw_vht_ch_wd, ap_bcon_ch_width);
222 /*
Kiran Kumar Lokere9e58d232016-08-23 18:49:16 -0700223 * If the supported channel width is greater than 80MHz and
224 * AP supports Nss > 1 in 160MHz mode then connect the STA
225 * in 2x2 80MHz mode instead of connecting in 160MHz mode.
226 */
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -0700227 if ((vht_ch_wd > WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) &&
228 mac_ctx->sta_prefer_80MHz_over_160MHz) {
Kiran Kumar Lokere9e58d232016-08-23 18:49:16 -0700229 if (!(IS_VHT_NSS_1x1(beacon_struct->VHTCaps.txMCSMap))
230 &&
231 (!IS_VHT_NSS_1x1(beacon_struct->VHTCaps.rxMCSMap)))
232 vht_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
233 }
234 /*
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700235 * VHT OP IE old definition:
236 * vht_op->chanCenterFreqSeg1: center freq of 80MHz/160MHz/
237 * primary 80 in 80+80MHz.
238 *
239 * vht_op->chanCenterFreqSeg2: center freq of secondary 80
240 * in 80+80MHz.
241 *
242 * VHT OP IE NEW definition:
243 * vht_op->chanCenterFreqSeg1: center freq of 80MHz/primary
244 * 80 in 80+80MHz/center freq of the 80 MHz channel segment
245 * that contains the primary channel in 160MHz mode.
246 *
247 * vht_op->chanCenterFreqSeg2: center freq of secondary 80
248 * in 80+80MHz/center freq of 160MHz.
249 */
250 session->ch_center_freq_seg0 = vht_op->chanCenterFreqSeg1;
251 session->ch_center_freq_seg1 = vht_op->chanCenterFreqSeg2;
252 if (vht_ch_wd == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
253 /* DUT or AP supports only 160MHz */
254 if (ap_bcon_ch_width ==
255 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
256 /* AP is in 160MHz mode */
257 if (!new_ch_width_dfn) {
258 session->ch_center_freq_seg1 =
259 vht_op->chanCenterFreqSeg1;
260 session->ch_center_freq_seg0 =
261 lim_get_80Mhz_center_channel(
262 beacon_struct->channelNumber);
263 }
Naveen Rawatc0c91cd2015-11-05 14:27:37 -0800264 } else {
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700265 /* DUT supports only 160MHz and AP is
266 * in 80+80 mode
267 */
268 vht_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
269 session->ch_center_freq_seg1 = 0;
270 }
271 } else if (vht_ch_wd == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
272 /* DUT or AP supports only 80MHz */
273 if (ap_bcon_ch_width ==
274 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ &&
275 !new_ch_width_dfn)
276 /* AP is in 160MHz mode */
Naveen Rawatc0c91cd2015-11-05 14:27:37 -0800277 session->ch_center_freq_seg0 =
278 lim_get_80Mhz_center_channel(
279 beacon_struct->channelNumber);
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700280 else
281 session->ch_center_freq_seg1 = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800282 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700283 session->ch_width = vht_ch_wd + 1;
284 lim_log(mac_ctx, LOGE, FL(
285 "cntr_freq0 %d, cntr_freq1 %d, width %d"),
286 session->ch_center_freq_seg0,
287 session->ch_center_freq_seg1,
288 session->ch_width);
289 if (CH_WIDTH_80MHZ < session->ch_width) {
Krunal Soni53993f72016-07-08 18:20:03 -0700290 session->vht_config.su_beam_former = 0;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700291 session->nss = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700294 if (session->vhtCapabilityPresentInBeacon == 1 &&
295 !session->htSupportedChannelWidthSet &&
Krunal Soni53993f72016-07-08 18:20:03 -0700296 session->vht_config.su_beam_formee == 0) {
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700297 cfg_set_status = cfg_set_int(mac_ctx,
298 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
299 0);
300 if (cfg_set_status != eSIR_SUCCESS)
301 lim_log(mac_ctx, LOGP,
302 FL("Set VHT_SU_BEAMFORMEE_CAP Fail"));
303 }
Kiran Kumar Lokere1d4094e2016-08-31 19:04:04 -0700304 if (session->vhtCapability &&
305 session->vhtCapabilityPresentInBeacon &&
306 beacon_struct->ext_cap.present) {
307 ext_cap = (struct s_ext_cap *)beacon_struct->ext_cap.bytes;
308 session->gLimOperatingMode.present =
309 ext_cap->oper_mode_notification;
310 if (ext_cap->oper_mode_notification) {
311 if (CH_WIDTH_160MHZ > session->ch_width)
312 session->gLimOperatingMode.chanWidth =
313 session->ch_width;
314 else
315 session->gLimOperatingMode.chanWidth =
316 CH_WIDTH_160MHZ;
317 } else {
318 lim_log(mac_ctx, LOGE, FL(
319 "AP does not support op_mode rx"));
320 }
321 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700322 /* Extract the UAPSD flag from WMM Parameter element */
323 if (beacon_struct->wmeEdcaPresent)
324 *uapsd = beacon_struct->edcaParams.qosInfo.uapsd;
Padma, Santhosh Kumar29df3622016-08-16 19:15:16 +0530325
326 if (mac_ctx->roam.configParam.allow_tpc_from_ap) {
327 if (beacon_struct->powerConstraintPresent) {
328 *local_constraint -=
329 beacon_struct->localPowerConstraint.
330 localPowerConstraints;
331 } else {
332 get_local_power_constraint_probe_response(
333 beacon_struct, local_constraint, session);
334 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700335 }
336 session->country_info_present = false;
337 /* Initializing before first use */
338 if (beacon_struct->countryInfoPresent)
339 session->country_info_present = true;
Agrawal Ashish0f94b572016-02-22 13:27:06 +0530340 /* Check if Extended caps are present in probe resp or not */
341 if (beacon_struct->ext_cap.present)
342 session->is_ext_caps_present = true;
Nitesh Shah0ddd4f62016-05-27 10:07:32 +0530343 /* Update HS 2.0 Information Element */
344 if (beacon_struct->hs20vendor_ie.present) {
345 lim_log(mac_ctx, LOG1,
346 FL("HS20 Indication Element Present, rel#:%u, id:%u\n"),
347 beacon_struct->hs20vendor_ie.release_num,
348 beacon_struct->hs20vendor_ie.hs_id_present);
349 qdf_mem_copy(&session->hs20vendor_ie,
350 &beacon_struct->hs20vendor_ie,
351 sizeof(tDot11fIEhs20vendor_ie) -
352 sizeof(beacon_struct->hs20vendor_ie.hs_id));
353 if (beacon_struct->hs20vendor_ie.hs_id_present)
354 qdf_mem_copy(&session->hs20vendor_ie.hs_id,
355 &beacon_struct->hs20vendor_ie.hs_id,
356 sizeof(beacon_struct->hs20vendor_ie.hs_id));
357 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530358 qdf_mem_free(beacon_struct);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800359 return;
360} /****** end lim_extract_ap_capability() ******/
361
362/**
363 * lim_get_htcb_state
364 *
365 ***FUNCTION:
366 * This routing provides the translation of Airgo Enum to HT enum for determining
367 * secondary channel offset.
368 * Airgo Enum is required for backward compatibility purposes.
369 *
370 *
371 ***NOTE:
372 *
373 * @param pMac - Pointer to Global MAC structure
374 * @return The corresponding HT enumeration
375 */
376ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode)
377{
378 switch (aniCBMode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379 case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
380 case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
381 case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800382 case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
383 return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
385 case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
386 case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
388 return PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800389 case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
390 return PHY_SINGLE_CHANNEL_CENTERED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 default:
392 return PHY_SINGLE_CHANNEL_CENTERED;
393 }
394}