import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / connectivity / conn_soc / drv_wlan / mt_wifi / wlan / mgmt / p2p_rlm.c
CommitLineData
6fa3eb70
S
1/*
2** $Id: @(#) p2p_rlm.c@@
3*/
4
5/*! \file "p2p_rlm.c"
6 \brief
7
8*/
9
10
11
12
13/*******************************************************************************
14* C O M P I L E R F L A G S
15********************************************************************************
16*/
17
18/*******************************************************************************
19* E X T E R N A L R E F E R E N C E S
20********************************************************************************
21*/
22
23#include "precomp.h"
24
25extern VOID
26rlmSyncOperationParams (
27 P_ADAPTER_T prAdapter,
28 P_BSS_INFO_T prBssInfo
29 );
30
31/*******************************************************************************
32* C O N S T A N T S
33********************************************************************************
34*/
35
36/*******************************************************************************
37* D A T A T Y P E S
38********************************************************************************
39*/
40
41/*******************************************************************************
42* P U B L I C D A T A
43********************************************************************************
44*/
45
46/*******************************************************************************
47* P R I V A T E D A T A
48********************************************************************************
49*/
50
51/*******************************************************************************
52* M A C R O S
53********************************************************************************
54*/
55
56/*******************************************************************************
57* F U N C T I O N D E C L A R A T I O N S
58********************************************************************************
59*/
60
61/*******************************************************************************
62* F U N C T I O N S
63********************************************************************************
64*/
65
66/*----------------------------------------------------------------------------*/
67/*!
68* \brief Init AP Bss
69*
70* \param[in]
71*
72* \return none
73*/
74/*----------------------------------------------------------------------------*/
75VOID
76rlmBssInitForAP(
77 P_ADAPTER_T prAdapter,
78 P_BSS_INFO_T prBssInfo
79 )
80{
81 ENUM_BAND_T eBand;
82 UINT_8 ucChannel;
83 ENUM_CHNL_EXT_T eSCO;
84
85 ASSERT(prAdapter);
86 ASSERT(prBssInfo);
87
88 if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) {
89 return;
90 }
91
92 /* Operation band, channel shall be ready before invoking this function.
93 * Bandwidth may be ready if other network is connected
94 */
95 prBssInfo->fg40mBwAllowed = FALSE;
96 prBssInfo->fgAssoc40mBwAllowed = FALSE;
97 prBssInfo->eBssSCO = CHNL_EXT_SCN;
98
99 if (RLM_AP_IS_BW_40_ALLOWED(prAdapter, prBssInfo)) {
100 /* In this case, the first BSS's SCO is 40MHz and known, so AP can
101 * apply 40MHz bandwidth, but the first BSS's SCO may be changed
102 * later if its Beacon lost timeout occurs
103 */
104 if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) &&
105 eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel &&
106 eBand == prBssInfo->eBand) {
107 prBssInfo->eBssSCO = eSCO;
108 }
109 else if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex)) {
110 prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo);
111 }
112
113 if (prBssInfo->eBssSCO != CHNL_EXT_SCN) {
114 prBssInfo->fg40mBwAllowed = TRUE;
115 prBssInfo->fgAssoc40mBwAllowed = TRUE;
116
117 prBssInfo->ucHtOpInfo1 = (UINT_8)
118 (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH);
119
120 rlmUpdateBwByChListForAP(prAdapter, prBssInfo);
121 }
122 }
123
124 DBGLOG(RLM, INFO, ("WLAN AP SCO=%d\n", prBssInfo->eBssSCO));
125}
126
127/*----------------------------------------------------------------------------*/
128/*!
129* \brief For probe response (GO, IBSS) and association response
130*
131* \param[in]
132*
133* \return none
134*/
135/*----------------------------------------------------------------------------*/
136VOID
137rlmRspGenerateObssScanIE (
138 P_ADAPTER_T prAdapter,
139 P_MSDU_INFO_T prMsduInfo
140 )
141{
142 P_BSS_INFO_T prBssInfo;
143 P_IE_OBSS_SCAN_PARAM_T prObssScanIe;
144 P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL;
145
146 ASSERT(prAdapter);
147 ASSERT(prMsduInfo);
148 ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType));
149
150 prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
151
152 prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType];
153 ASSERT(prBssInfo);
154
155 if (RLM_NET_IS_11N(prBssInfo) && !RLM_NET_IS_BOW(prBssInfo) &&
156 prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT &&
157 (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) &&
158 prBssInfo->eBand == BAND_2G4 &&
159 prBssInfo->eBssSCO != CHNL_EXT_SCN) {
160
161 prObssScanIe = (P_IE_OBSS_SCAN_PARAM_T)
162 (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength);
163
164 /* Add 20/40 BSS coexistence IE */
165 prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS;
166 prObssScanIe->ucLength = sizeof(IE_OBSS_SCAN_PARAM_T) - ELEM_HDR_LEN;
167
168 prObssScanIe->u2ScanPassiveDwell =
169 dot11OBSSScanPassiveDwell;
170 prObssScanIe->u2ScanActiveDwell =
171 dot11OBSSScanActiveDwell;
172 prObssScanIe->u2TriggerScanInterval =
173 dot11BSSWidthTriggerScanInterval;
174 prObssScanIe->u2ScanPassiveTotalPerChnl =
175 dot11OBSSScanPassiveTotalPerChannel;
176 prObssScanIe->u2ScanActiveTotalPerChnl =
177 dot11OBSSScanActiveTotalPerChannel;
178 prObssScanIe->u2WidthTransDelayFactor =
179 dot11BSSWidthChannelTransitionDelayFactor;
180 prObssScanIe->u2ScanActivityThres =
181 dot11OBSSScanActivityThreshold;
182
183 ASSERT(IE_SIZE(prObssScanIe) <= (ELEM_HDR_LEN+ ELEM_MAX_LEN_OBSS_SCAN));
184
185 prMsduInfo->u2FrameLength += IE_SIZE(prObssScanIe);
186 }
187}
188
189/*----------------------------------------------------------------------------*/
190/*!
191* \brief P2P GO.
192*
193* \param[in]
194*
195* \return none
196*/
197/*----------------------------------------------------------------------------*/
198BOOLEAN
199rlmUpdateBwByChListForAP (
200 P_ADAPTER_T prAdapter,
201 P_BSS_INFO_T prBssInfo
202 )
203{
204 UINT_8 ucLevel;
205 BOOLEAN fgBwChange;
206
207 ASSERT(prAdapter);
208 ASSERT(prBssInfo);
209
210 fgBwChange = FALSE;
211
212 if (prBssInfo->eBssSCO == CHNL_EXT_SCN) {
213 return fgBwChange;
214 }
215
216 ucLevel = rlmObssChnlLevel(prBssInfo, prBssInfo->eBand,
217 prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO);
218
219 if (ucLevel == CHNL_LEVEL0) {
220 /* Forced to 20MHz, so extended channel is SCN and STA width is zero */
221 prBssInfo->fgObssActionForcedTo20M = TRUE;
222
223 if (prBssInfo->ucHtOpInfo1 != (UINT_8) CHNL_EXT_SCN) {
224 prBssInfo->ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN;
225 fgBwChange = TRUE;
226 }
227
228 cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer,
229 OBSS_20_40M_TIMEOUT * MSEC_PER_SEC);
230 }
231
232 /* Clear up all channel lists */
233 prBssInfo->auc2G_20mReqChnlList[0] = 0;
234 prBssInfo->auc2G_NonHtChnlList[0] = 0;
235 prBssInfo->auc2G_PriChnlList[0] = 0;
236 prBssInfo->auc2G_SecChnlList[0] = 0;
237 prBssInfo->auc5G_20mReqChnlList[0] = 0;
238 prBssInfo->auc5G_NonHtChnlList[0] = 0;
239 prBssInfo->auc5G_PriChnlList[0] = 0;
240 prBssInfo->auc5G_SecChnlList[0] = 0;
241
242 return fgBwChange;
243}
244
245/*----------------------------------------------------------------------------*/
246/*!
247* \brief
248*
249* \param[in]
250*
251* \return none
252*/
253/*----------------------------------------------------------------------------*/
254VOID
255rlmProcessPublicAction (
256 P_ADAPTER_T prAdapter,
257 P_SW_RFB_T prSwRfb
258 )
259{
260 P_ACTION_20_40_COEXIST_FRAME prRxFrame;
261 P_IE_20_40_COEXIST_T prCoexist;
262 P_IE_INTOLERANT_CHNL_REPORT_T prChnlReport;
263 P_BSS_INFO_T prBssInfo;
264 P_STA_RECORD_T prStaRec;
265 PUINT_8 pucIE;
266 UINT_16 u2IELength, u2Offset;
267 UINT_8 i, j;
268
269 ASSERT(prAdapter);
270 ASSERT(prSwRfb);
271
272 prRxFrame = (P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader;
273 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
274
275 if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST ||
276 !prStaRec || prStaRec->ucStaState != STA_STATE_3 ||
277 prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) ||
278 HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) !=
279 NETWORK_TYPE_P2P_INDEX) {
280 return;
281 }
282
283 prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX];
284 ASSERT(prBssInfo);
285
286 if (!IS_BSS_ACTIVE(prBssInfo) ||
287 prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT ||
288 prBssInfo->eBssSCO == CHNL_EXT_SCN) {
289 return;
290 }
291
292 prCoexist = &prRxFrame->rBssCoexist;
293 if (prCoexist->ucData & (BSS_COEXIST_40M_INTOLERANT|BSS_COEXIST_20M_REQ)) {
294 ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G);
295 for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] &&
296 i <= CHNL_LIST_SZ_2G; i++) {
297 if (prBssInfo->auc2G_20mReqChnlList[i] ==
298 prBssInfo->ucPrimaryChannel) {
299 break;
300 }
301 }
302 if ((i > prBssInfo->auc2G_20mReqChnlList[0]) &&
303 (i <= CHNL_LIST_SZ_2G)){
304 prBssInfo->auc2G_20mReqChnlList[i] = prBssInfo->ucPrimaryChannel;
305 prBssInfo->auc2G_20mReqChnlList[0]++;
306 }
307 }
308
309 /* Process intolerant channel report IE */
310 pucIE = (PUINT_8) &prRxFrame->rChnlReport;
311 u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_MGMT_HEADER_LEN + 5);
312
313 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
314 switch (IE_ID(pucIE)) {
315 case ELEM_ID_20_40_INTOLERANT_CHNL_REPORT:
316 prChnlReport = (P_IE_INTOLERANT_CHNL_REPORT_T) pucIE;
317
318 if (prChnlReport->ucLength <= 1) {
319 break;
320 }
321
322 /* To do: process regulatory class. Now we assume 2.4G band */
323
324 for (j = 0; j < prChnlReport->ucLength - 1; j++) {
325 /* Update non-HT channel list */
326 ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G);
327 for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] &&
328 i <= CHNL_LIST_SZ_2G; i++) {
329 if (prBssInfo->auc2G_NonHtChnlList[i] ==
330 prChnlReport->aucChannelList[j]) {
331 break;
332 }
333 }
334 if ((i > prBssInfo->auc2G_NonHtChnlList[0]) &&
335 (i <= CHNL_LIST_SZ_2G)) {
336 prBssInfo->auc2G_NonHtChnlList[i] =
337 prChnlReport->aucChannelList[j];
338 prBssInfo->auc2G_NonHtChnlList[0]++;
339 }
340 }
341 break;
342
343 default:
344 break;
345 }
346 } /* end of IE_FOR_EACH */
347
348 if (rlmUpdateBwByChListForAP(prAdapter, prBssInfo)) {
349 bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex);
350 rlmSyncOperationParams(prAdapter, prBssInfo);
351 }
352
353 /* Check if OBSS scan exemption response should be sent */
354 if (prCoexist->ucData & BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ) {
355 rlmObssScanExemptionRsp(prAdapter, prBssInfo, prSwRfb);
356 }
357}
358
359/*----------------------------------------------------------------------------*/
360/*!
361* \brief
362*
363* \param[in]
364*
365* \return none
366*/
367/*----------------------------------------------------------------------------*/
368VOID
369rlmProcessHtAction (
370 P_ADAPTER_T prAdapter,
371 P_SW_RFB_T prSwRfb
372 )
373{
374 P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame;
375 P_STA_RECORD_T prStaRec;
376
377 ASSERT(prAdapter);
378 ASSERT(prSwRfb);
379
380 prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader;
381 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
382
383 if (prRxFrame->ucAction != ACTION_HT_NOTIFY_CHANNEL_WIDTH ||
384 !prStaRec || prStaRec->ucStaState != STA_STATE_3 ||
385 prSwRfb->u2PacketLen < sizeof(ACTION_NOTIFY_CHNL_WIDTH_FRAME)) {
386 return;
387 }
388
389 /* To do: depending regulation class 13 and 14 based on spec
390 * Note: (ucChannelWidth==1) shall restored back to original capability,
391 * not current setting to 40MHz BW here
392 */
393 if (prRxFrame->ucChannelWidth == 0) {
394 prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH;
395 }
396 else if (prRxFrame->ucChannelWidth == 1) {
397 prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH;
398 }
399 cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3);
400}
401
402/*----------------------------------------------------------------------------*/
403/*!
404* \brief
405*
406* \param[in]
407*
408* \return none
409*/
410/*----------------------------------------------------------------------------*/
411VOID
412rlmHandleObssStatusEventPkt (
413 P_ADAPTER_T prAdapter,
414 P_EVENT_AP_OBSS_STATUS_T prObssStatus
415 )
416{
417 P_BSS_INFO_T prBssInfo;
418
419 ASSERT(prAdapter);
420 ASSERT(prObssStatus);
421 ASSERT(prObssStatus->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX);
422
423 prBssInfo = &prAdapter->rWifiVar.arBssInfo[prObssStatus->ucNetTypeIndex];
424 ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT);
425
426 prBssInfo->fgObssErpProtectMode =
427 (BOOLEAN) prObssStatus->ucObssErpProtectMode;
428 prBssInfo->eObssHtProtectMode =
429 (ENUM_HT_PROTECT_MODE_T) prObssStatus->ucObssHtProtectMode;
430 prBssInfo->eObssGfOperationMode =
431 (ENUM_GF_MODE_T) prObssStatus->ucObssGfOperationMode;
432 prBssInfo->fgObssRifsOperationMode =
433 (BOOLEAN) prObssStatus->ucObssRifsOperationMode;
434 prBssInfo->fgObssBeaconForcedTo20M =
435 (BOOLEAN) prObssStatus->ucObssBeaconForcedTo20M;
436
437 /* Check if Beacon content need to be updated */
438 rlmUpdateParamsForAP(prAdapter, prBssInfo, TRUE);
439}
440
441
442/*----------------------------------------------------------------------------*/
443/*!
444* \brief It is only for AP mode in NETWORK_TYPE_P2P_INDEX.
445*
446* \param[in]
447*
448* \return none
449*/
450/*----------------------------------------------------------------------------*/
451VOID
452rlmUpdateParamsForAP (
453 P_ADAPTER_T prAdapter,
454 P_BSS_INFO_T prBssInfo,
455 BOOLEAN fgUpdateBeacon
456 )
457{
458 P_LINK_T prStaList;
459 P_STA_RECORD_T prStaRec;
460 BOOLEAN fgErpProtectMode, fgSta40mIntolerant;
461 BOOLEAN fgUseShortPreamble, fgUseShortSlotTime;
462 ENUM_HT_PROTECT_MODE_T eHtProtectMode;
463 ENUM_GF_MODE_T eGfOperationMode;
464 UINT_8 ucHtOpInfo1;
465#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION
466 P_GLUE_INFO_T prGlueInfo;
467#endif
468
469 ASSERT(prAdapter);
470 ASSERT(prBssInfo);
471
472 if (!IS_BSS_ACTIVE(prBssInfo) ||
473 prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) {
474 return;
475 }
476
477 fgErpProtectMode = FALSE;
478 eHtProtectMode = HT_PROTECT_MODE_NONE;
479 eGfOperationMode = GF_MODE_NORMAL;
480 fgSta40mIntolerant = FALSE;
481 fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed;
482 fgUseShortSlotTime = TRUE;
483 ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN;
484
485 prStaList = &prBssInfo->rStaRecOfClientList;
486
487 LINK_FOR_EACH_ENTRY(prStaRec, prStaList, rLinkEntry, STA_RECORD_T) {
488 //ASSERT(prStaRec);
489 if(!prStaRec){
490 DBGLOG(P2P, TRACE, ("prStaRec is NULL in rlmUpdateParamsForAP() \n"));
491 break;
492 }
493 if (prStaRec->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 &&
494 prStaRec->ucNetTypeIndex == prBssInfo->ucNetTypeIndex) {
495 if (!(prStaRec->ucPhyTypeSet &
496 (PHY_TYPE_SET_802_11GN | PHY_TYPE_SET_802_11A))) {
497 /* B-only mode, so mode 1 (ERP protection) */
498 fgErpProtectMode = TRUE;
499 }
500
501 if (!(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) {
502 /* BG-only or A-only */
503 eHtProtectMode = HT_PROTECT_MODE_NON_HT;
504 }
505 else if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) {
506 /* 20MHz-only */
507 /*
508 The HT Protection field may be set to 20 MHz protection
509 mode only if the following are true:
510