blob: 1f367b75a469d41e4c1626e387ecdff92f952b3f [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 */
227 if (vht_ch_wd > WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
228 if (!(IS_VHT_NSS_1x1(beacon_struct->VHTCaps.txMCSMap))
229 &&
230 (!IS_VHT_NSS_1x1(beacon_struct->VHTCaps.rxMCSMap)))
231 vht_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
232 }
233 /*
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700234 * VHT OP IE old definition:
235 * vht_op->chanCenterFreqSeg1: center freq of 80MHz/160MHz/
236 * primary 80 in 80+80MHz.
237 *
238 * vht_op->chanCenterFreqSeg2: center freq of secondary 80
239 * in 80+80MHz.
240 *
241 * VHT OP IE NEW definition:
242 * vht_op->chanCenterFreqSeg1: center freq of 80MHz/primary
243 * 80 in 80+80MHz/center freq of the 80 MHz channel segment
244 * that contains the primary channel in 160MHz mode.
245 *
246 * vht_op->chanCenterFreqSeg2: center freq of secondary 80
247 * in 80+80MHz/center freq of 160MHz.
248 */
249 session->ch_center_freq_seg0 = vht_op->chanCenterFreqSeg1;
250 session->ch_center_freq_seg1 = vht_op->chanCenterFreqSeg2;
251 if (vht_ch_wd == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
252 /* DUT or AP supports only 160MHz */
253 if (ap_bcon_ch_width ==
254 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
255 /* AP is in 160MHz mode */
256 if (!new_ch_width_dfn) {
257 session->ch_center_freq_seg1 =
258 vht_op->chanCenterFreqSeg1;
259 session->ch_center_freq_seg0 =
260 lim_get_80Mhz_center_channel(
261 beacon_struct->channelNumber);
262 }
Naveen Rawatc0c91cd2015-11-05 14:27:37 -0800263 } else {
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700264 /* DUT supports only 160MHz and AP is
265 * in 80+80 mode
266 */
267 vht_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
268 session->ch_center_freq_seg1 = 0;
269 }
270 } else if (vht_ch_wd == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
271 /* DUT or AP supports only 80MHz */
272 if (ap_bcon_ch_width ==
273 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ &&
274 !new_ch_width_dfn)
275 /* AP is in 160MHz mode */
Naveen Rawatc0c91cd2015-11-05 14:27:37 -0800276 session->ch_center_freq_seg0 =
277 lim_get_80Mhz_center_channel(
278 beacon_struct->channelNumber);
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700279 else
280 session->ch_center_freq_seg1 = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700282 session->ch_width = vht_ch_wd + 1;
283 lim_log(mac_ctx, LOGE, FL(
284 "cntr_freq0 %d, cntr_freq1 %d, width %d"),
285 session->ch_center_freq_seg0,
286 session->ch_center_freq_seg1,
287 session->ch_width);
288 if (CH_WIDTH_80MHZ < session->ch_width) {
Krunal Soni53993f72016-07-08 18:20:03 -0700289 session->vht_config.su_beam_former = 0;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700290 session->nss = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700293 if (session->vhtCapabilityPresentInBeacon == 1 &&
294 !session->htSupportedChannelWidthSet &&
Krunal Soni53993f72016-07-08 18:20:03 -0700295 session->vht_config.su_beam_formee == 0) {
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700296 cfg_set_status = cfg_set_int(mac_ctx,
297 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
298 0);
299 if (cfg_set_status != eSIR_SUCCESS)
300 lim_log(mac_ctx, LOGP,
301 FL("Set VHT_SU_BEAMFORMEE_CAP Fail"));
302 }
Kiran Kumar Lokere1d4094e2016-08-31 19:04:04 -0700303 if (session->vhtCapability &&
304 session->vhtCapabilityPresentInBeacon &&
305 beacon_struct->ext_cap.present) {
306 ext_cap = (struct s_ext_cap *)beacon_struct->ext_cap.bytes;
307 session->gLimOperatingMode.present =
308 ext_cap->oper_mode_notification;
309 if (ext_cap->oper_mode_notification) {
310 if (CH_WIDTH_160MHZ > session->ch_width)
311 session->gLimOperatingMode.chanWidth =
312 session->ch_width;
313 else
314 session->gLimOperatingMode.chanWidth =
315 CH_WIDTH_160MHZ;
316 } else {
317 lim_log(mac_ctx, LOGE, FL(
318 "AP does not support op_mode rx"));
319 }
320 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700321 /* Extract the UAPSD flag from WMM Parameter element */
322 if (beacon_struct->wmeEdcaPresent)
323 *uapsd = beacon_struct->edcaParams.qosInfo.uapsd;
Padma, Santhosh Kumar29df3622016-08-16 19:15:16 +0530324
325 if (mac_ctx->roam.configParam.allow_tpc_from_ap) {
326 if (beacon_struct->powerConstraintPresent) {
327 *local_constraint -=
328 beacon_struct->localPowerConstraint.
329 localPowerConstraints;
330 } else {
331 get_local_power_constraint_probe_response(
332 beacon_struct, local_constraint, session);
333 }
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -0700334 }
335 session->country_info_present = false;
336 /* Initializing before first use */
337 if (beacon_struct->countryInfoPresent)
338 session->country_info_present = true;
Agrawal Ashish0f94b572016-02-22 13:27:06 +0530339 /* Check if Extended caps are present in probe resp or not */
340 if (beacon_struct->ext_cap.present)
341 session->is_ext_caps_present = true;
Nitesh Shah0ddd4f62016-05-27 10:07:32 +0530342 /* Update HS 2.0 Information Element */
343 if (beacon_struct->hs20vendor_ie.present) {
344 lim_log(mac_ctx, LOG1,
345 FL("HS20 Indication Element Present, rel#:%u, id:%u\n"),
346 beacon_struct->hs20vendor_ie.release_num,
347 beacon_struct->hs20vendor_ie.hs_id_present);
348 qdf_mem_copy(&session->hs20vendor_ie,
349 &beacon_struct->hs20vendor_ie,
350 sizeof(tDot11fIEhs20vendor_ie) -
351 sizeof(beacon_struct->hs20vendor_ie.hs_id));
352 if (beacon_struct->hs20vendor_ie.hs_id_present)
353 qdf_mem_copy(&session->hs20vendor_ie.hs_id,
354 &beacon_struct->hs20vendor_ie.hs_id,
355 sizeof(beacon_struct->hs20vendor_ie.hs_id));
356 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530357 qdf_mem_free(beacon_struct);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800358 return;
359} /****** end lim_extract_ap_capability() ******/
360
361/**
362 * lim_get_htcb_state
363 *
364 ***FUNCTION:
365 * This routing provides the translation of Airgo Enum to HT enum for determining
366 * secondary channel offset.
367 * Airgo Enum is required for backward compatibility purposes.
368 *
369 *
370 ***NOTE:
371 *
372 * @param pMac - Pointer to Global MAC structure
373 * @return The corresponding HT enumeration
374 */
375ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode)
376{
377 switch (aniCBMode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
379 case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
380 case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800381 case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
382 return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
384 case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
385 case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
387 return PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
389 return PHY_SINGLE_CHANNEL_CENTERED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 default:
391 return PHY_SINGLE_CHANNEL_CENTERED;
392 }
393}