blob: 1a11104162bffa2643826c89e19cef9cad01d200 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
3 *
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 sch_api.cc contains functions related to the API exposed
31 * by scheduler module
32 *
33 * Author: Sandesh Goel
34 * Date: 02/25/02
35 * History:-
36 * Date Modified by Modification Information
37 * --------------------------------------------------------------------
38 *
39 */
40#include "cds_api.h"
41#include "ani_global.h"
42#include "wni_cfg.h"
43
44#include "sir_mac_prot_def.h"
45#include "sir_mac_prop_exts.h"
46#include "sir_common.h"
47
48#include "cfg_api.h"
49
50#include "lim_api.h"
51
52#include "sch_api.h"
53#include "sch_debug.h"
54
55#include "sch_sys_params.h"
56#include "lim_trace.h"
57#include "lim_types.h"
58
59#include "wma_types.h"
60
61/* -------------------------------------------------------------------- */
62/* */
63/* Static Variables */
64/* */
65/* ------------------------------------------------------------------- */
66
67/* -------------------------------------------------------------------- */
68/**
69 * sch_get_cfp_count
70 *
71 * FUNCTION:
72 * Function used by other Sirius modules to read CFPcount
73 *
74 * LOGIC:
75 *
76 * ASSUMPTIONS:
77 *
78 * NOTE:
79 *
80 * @param None
81 * @return None
82 */
83
84uint8_t sch_get_cfp_count(tpAniSirGlobal pMac)
85{
86 return pMac->sch.schObject.gSchCFPCount;
87}
88
89/* -------------------------------------------------------------------- */
90/**
91 * sch_get_cfp_dur_remaining
92 *
93 * FUNCTION:
94 * Function used by other Sirius modules to read CFPDuration remaining
95 *
96 * LOGIC:
97 *
98 * ASSUMPTIONS:
99 *
100 * NOTE:
101 *
102 * @param None
103 * @return None
104 */
105
106uint16_t sch_get_cfp_dur_remaining(tpAniSirGlobal pMac)
107{
108 return pMac->sch.schObject.gSchCFPDurRemaining;
109}
110
111/* -------------------------------------------------------------------- */
112/**
113 * sch_init_globals
114 *
115 * FUNCTION:
116 * Initialize globals
117 *
118 * LOGIC:
119 *
120 * ASSUMPTIONS:
121 *
122 * NOTE:
123 *
124 * @param None
125 * @return None
126 */
127
128void sch_init_globals(tpAniSirGlobal pMac)
129{
130 pMac->sch.gSchHcfEnabled = false;
131
132 pMac->sch.gSchScanRequested = false;
133 pMac->sch.gSchScanReqRcvd = false;
134
135 pMac->sch.gSchGenBeacon = 1;
136 pMac->sch.gSchBeaconsSent = 0;
137 pMac->sch.gSchBeaconsWritten = 0;
138 pMac->sch.gSchBcnParseErrorCnt = 0;
139 pMac->sch.gSchBcnIgnored = 0;
140 pMac->sch.gSchBBXportRcvCnt = 0;
141 pMac->sch.gSchUnknownRcvCnt = 0;
142 pMac->sch.gSchBcnRcvCnt = 0;
143 pMac->sch.gSchRRRcvCnt = 0;
144 pMac->sch.qosNullCnt = 0;
145 pMac->sch.numData = 0;
146 pMac->sch.numPoll = 0;
147 pMac->sch.numCorrupt = 0;
148 pMac->sch.numBogusInt = 0;
149 pMac->sch.numTxAct0 = 0;
150 pMac->sch.rrTimeout = SCH_RR_TIMEOUT;
151 pMac->sch.pollPeriod = SCH_POLL_PERIOD;
152 pMac->sch.multipleSched = 1;
153 pMac->sch.maxPollTimeouts = 20;
154 pMac->sch.checkCfbFlagStuck = 0;
155}
156
157/* -------------------------------------------------------------------- */
158/**
159 * sch_post_message
160 *
161 * FUNCTION:
162 * Post the beacon message to the scheduler message queue
163 *
164 * LOGIC:
165 *
166 * ASSUMPTIONS:
167 *
168 * NOTE:
169 *
170 * @param pMsg pointer to message
171 * @return None
172 */
173
174tSirRetStatus sch_post_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
175{
176 sch_process_message(pMac, pMsg);
177
178 return eSIR_SUCCESS;
179}
180
181/* --------------------------------------------------------------------------- */
182/**
183 * sch_send_start_scan_rsp
184 *
185 * FUNCTION:
186 *
187 * LOGIC:
188 *
189 * ASSUMPTIONS:
190 *
191 * NOTE:
192 *
193 * @param None
194 * @return None
195 */
196
197void sch_send_start_scan_rsp(tpAniSirGlobal pMac)
198{
199 tSirMsgQ msgQ;
200 uint32_t retCode;
201
202 PELOG1(sch_log(pMac, LOG1, FL("Sending LIM message to go into scan"));)
203 msgQ.type = SIR_SCH_START_SCAN_RSP;
204 if ((retCode = lim_post_msg_api(pMac, &msgQ)) != eSIR_SUCCESS)
205 sch_log(pMac, LOGE,
206 FL("Posting START_SCAN_RSP to LIM failed, reason=%X"),
207 retCode);
208}
209
210/**
211 * sch_send_beacon_req
212 *
213 * FUNCTION:
214 *
215 * LOGIC:
216 * 1) SCH received SIR_SCH_BEACON_GEN_IND
217 * 2) SCH updates TIM IE and other beacon related IE's
218 * 3) SCH sends WMA_SEND_BEACON_REQ to HAL. HAL then copies the beacon
219 * template to memory
220 *
221 * ASSUMPTIONS:
222 * Memory allocation is reqd to send this message and SCH allocates memory.
223 * The assumption is that HAL will "free" this memory.
224 *
225 * NOTE:
226 *
227 * @param pMac global
228 *
229 * @param beaconPayload
230 *
231 * @param size - Length of the beacon
232 *
233 * @return CDF_STATUS
234 */
235tSirRetStatus sch_send_beacon_req(tpAniSirGlobal pMac, uint8_t *beaconPayload,
236 uint16_t size, tpPESession psessionEntry)
237{
238 tSirMsgQ msgQ;
239 tpSendbeaconParams beaconParams = NULL;
240 tSirRetStatus retCode;
241
242 sch_log(pMac, LOG2,
243 FL
244 ("Indicating HAL to copy the beacon template [%d bytes] to memory"),
245 size);
246
247 beaconParams = cdf_mem_malloc(sizeof(tSendbeaconParams));
248 if (NULL == beaconParams)
249 return eSIR_MEM_ALLOC_FAILED;
250
251 msgQ.type = WMA_SEND_BEACON_REQ;
252
253 /* No Dialog Token reqd, as a response is not solicited */
254 msgQ.reserved = 0;
255
256 /* Fill in tSendbeaconParams members */
257 cdf_mem_copy(beaconParams->bssId, psessionEntry->bssId,
258 sizeof(psessionEntry->bssId));
259
260 if (LIM_IS_IBSS_ROLE(psessionEntry)) {
261 beaconParams->timIeOffset = 0;
262 } else {
263 beaconParams->timIeOffset = psessionEntry->schBeaconOffsetBegin;
264 }
265
266 /* p2pIeOffset should be atleast greater than timIeOffset */
267 if ((pMac->sch.schObject.p2pIeOffset != 0) &&
268 (pMac->sch.schObject.p2pIeOffset <
269 psessionEntry->schBeaconOffsetBegin)) {
270 sch_log(pMac, LOGE, FL("Invalid p2pIeOffset:[%d]"),
271 pMac->sch.schObject.p2pIeOffset);
272 CDF_ASSERT(0);
273 cdf_mem_free(beaconParams);
274 return eSIR_FAILURE;
275 }
276 beaconParams->p2pIeOffset = pMac->sch.schObject.p2pIeOffset;
277#ifdef WLAN_SOFTAP_FW_BEACON_TX_PRNT_LOG
278 sch_log(pMac, LOGE, FL("TimIeOffset:[%d]"), beaconParams->TimIeOffset);
279#endif
280
281 beaconParams->beacon = beaconPayload;
282 beaconParams->beaconLength = (uint32_t) size;
283 msgQ.bodyptr = beaconParams;
284 msgQ.bodyval = 0;
285
286 /* Keep a copy of recent beacon frame sent */
287
288 /* free previous copy of the beacon */
289 if (psessionEntry->beacon) {
290 cdf_mem_free(psessionEntry->beacon);
291 }
292
293 psessionEntry->bcnLen = 0;
294 psessionEntry->beacon = NULL;
295
296 psessionEntry->beacon = cdf_mem_malloc(size);
297 if (psessionEntry->beacon != NULL) {
298 cdf_mem_copy(psessionEntry->beacon, beaconPayload, size);
299 psessionEntry->bcnLen = size;
300 }
301
302 MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
303 if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
304 sch_log(pMac, LOGE,
305 FL("Posting SEND_BEACON_REQ to HAL failed, reason=%X"),
306 retCode);
307 } else {
308 sch_log(pMac, LOG2,
309 FL("Successfully posted WMA_SEND_BEACON_REQ to HAL"));
310
311 if (LIM_IS_AP_ROLE(psessionEntry) &&
312 (pMac->sch.schObject.fBeaconChanged)) {
313 if (eSIR_SUCCESS !=
314 (retCode =
315 lim_send_probe_rsp_template_to_hal(pMac, psessionEntry,
316 &psessionEntry->
317 DefProbeRspIeBitmap
318 [0]))) {
319 /* check whether we have to free any memory */
320 sch_log(pMac, LOGE,
321 FL
322 ("FAILED to send probe response template with retCode %d"),
323 retCode);
324 }
325 }
326 }
327
328 return retCode;
329}
330
331uint32_t lim_remove_p2p_ie_from_add_ie(tpAniSirGlobal pMac,
332 tpPESession psessionEntry,
333 uint8_t *addIeWoP2pIe,
334 uint32_t *addnIELenWoP2pIe)
335{
336 uint32_t left = psessionEntry->addIeParams.probeRespDataLen;
337 uint8_t *ptr = psessionEntry->addIeParams.probeRespData_buff;
338 uint8_t elem_id,elem_len;
339 uint32_t offset = 0;
340 uint8_t eid = 0xDD;
341
342 cdf_mem_copy(addIeWoP2pIe, ptr, left);
343 *addnIELenWoP2pIe = left;
344
345 if (addIeWoP2pIe != NULL) {
346 while (left >= 2) {
347 elem_id = ptr[0];
348 elem_len = ptr[1];
349 left -= 2;
350 if(elem_len > left) {
351 sch_log(pMac, LOGE, FL("Invalid IEs"));
352 return eSIR_FAILURE;
353 }
354 if ((elem_id == eid) &&
355 (cdf_mem_compare(&ptr[2],
356 "\x50\x6f\x9a\x09", 4))) {
357 left -= elem_len;
358 ptr += (elem_len + 2);
359 cdf_mem_copy(&addIeWoP2pIe[offset], ptr, left);
360 *addnIELenWoP2pIe -= (2 + elem_len);
361 } else {
362 left -= elem_len;
363 ptr += (elem_len + 2);
364 offset += 2 + elem_len;
365 }
366 }
367 }
368 return eSIR_SUCCESS;
369}
370
371uint32_t lim_send_probe_rsp_template_to_hal(tpAniSirGlobal pMac,
372 tpPESession psessionEntry,
373 uint32_t *IeBitmap)
374{
375 tSirMsgQ msgQ;
376 uint8_t *pFrame2Hal = psessionEntry->pSchProbeRspTemplate;
377 tpSendProbeRespParams pprobeRespParams = NULL;
378 uint32_t retCode = eSIR_FAILURE;
379 uint32_t nPayload, nBytes, nStatus;
380 tpSirMacMgmtHdr pMacHdr;
381 uint32_t addnIEPresent = false;
382 uint32_t addnIELen = 0;
383 uint8_t *addIE = NULL;
384 uint8_t *addIeWoP2pIe = NULL;
385 uint32_t addnIELenWoP2pIe = 0;
386 uint32_t retStatus;
387
388 nStatus =
389 dot11f_get_packed_probe_response_size(pMac,
390 &psessionEntry->probeRespFrame,
391 &nPayload);
392 if (DOT11F_FAILED(nStatus)) {
393 sch_log(pMac, LOGE, FL("Failed to calculate the packed size f"
394 "or a Probe Response (0x%08x)."),
395 nStatus);
396 /* We'll fall back on the worst case scenario: */
397 nPayload = sizeof(tDot11fProbeResponse);
398 } else if (DOT11F_WARNED(nStatus)) {
399 sch_log(pMac, LOGE, FL("There were warnings while calculating"
400 "the packed size for a Probe Response "
401 "(0x%08x)."), nStatus);
402 }
403
404 nBytes = nPayload + sizeof(tSirMacMgmtHdr);
405
406 /* Check if probe response IE is present or not */
407 addnIEPresent = (psessionEntry->addIeParams.probeRespDataLen != 0);
408 if (addnIEPresent) {
409 /*
410 * probe response template should not have P2P IE.
411 * In case probe request has P2P IE or WPS IE, the
412 * probe request will be forwarded to the Host and
413 * Host will send the probe response. In other cases
414 * FW will send the probe response. So, if the template
415 * has P2P IE, the probe response sent to non P2P devices
416 * by the FW, may also have P2P IE which will fail
417 * P2P cert case 6.1.3
418 */
419 addIeWoP2pIe = cdf_mem_malloc(psessionEntry->addIeParams.
420 probeRespDataLen);
421 if (NULL == addIeWoP2pIe) {
422 sch_log(pMac, LOGE,
423 FL("FAILED to alloc memory when removing P2P IE"));
424 return eSIR_MEM_ALLOC_FAILED;
425 }
426
427 retStatus = lim_remove_p2p_ie_from_add_ie(pMac, psessionEntry,
428 addIeWoP2pIe, &addnIELenWoP2pIe);
429 if (retStatus != eSIR_SUCCESS) {
430 cdf_mem_free(addIeWoP2pIe);
431 return eSIR_FAILURE;
432 }
433
434 /* Probe rsp IE available */
435 /*need to check the data length */
436 addIE =
437 cdf_mem_malloc(addnIELenWoP2pIe);
438 if (NULL == addIE) {
439 sch_log(pMac, LOGE,
440 FL
441 ("Unable to get WNI_CFG_PROBE_RSP_ADDNIE_DATA1 length"));
442 cdf_mem_free(addIeWoP2pIe);
443 return eSIR_MEM_ALLOC_FAILED;
444 }
445 addnIELen = addnIELenWoP2pIe;
446
447 if (addnIELen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addnIELen
448 && (nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE) {
449
450 cdf_mem_copy(addIE,
451 addIeWoP2pIe,
452 addnIELenWoP2pIe);
453 }
454 cdf_mem_free(addIeWoP2pIe);
455 }
456
457 if (addnIEPresent) {
458 if ((nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE)
459 nBytes += addnIELen;
460 else
461 addnIEPresent = false; /* Dont include the IE. */
462 }
463 /* Paranoia: */
464 cdf_mem_set(pFrame2Hal, nBytes, 0);
465
466 /* Next, we fill out the buffer descriptor: */
467 lim_populate_mac_header(pMac, pFrame2Hal, SIR_MAC_MGMT_FRAME,
468 SIR_MAC_MGMT_PROBE_RSP,
469 psessionEntry->selfMacAddr,
470 psessionEntry->selfMacAddr);
471
472 pMacHdr = (tpSirMacMgmtHdr) pFrame2Hal;
473
474 sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
475
476 /* That done, pack the Probe Response: */
477 nStatus =
478 dot11f_pack_probe_response(pMac, &psessionEntry->probeRespFrame,
479 pFrame2Hal + sizeof(tSirMacMgmtHdr),
480 nPayload, &nPayload);
481
482 if (DOT11F_FAILED(nStatus)) {
483 sch_log(pMac, LOGE,
484 FL("Failed to pack a Probe Response (0x%08x)."),
485 nStatus);
486
487 cdf_mem_free(addIE);
488 return retCode; /* allocated! */
489 } else if (DOT11F_WARNED(nStatus)) {
490 sch_log(pMac, LOGE, FL("There were warnings while packing a P"
491 "robe Response (0x%08x)."), nStatus);
492 }
493
494 if (addnIEPresent) {
495 cdf_mem_copy(&pFrame2Hal[nBytes - addnIELen],
496 &addIE[0], addnIELen);
497 }
498
499 /* free the allocated Memory */
500 cdf_mem_free(addIE);
501
502 pprobeRespParams = cdf_mem_malloc(sizeof(tSendProbeRespParams));
503 if (NULL == pprobeRespParams) {
504 sch_log(pMac, LOGE,
505 FL
506 ("lim_send_probe_rsp_template_to_hal: HAL probe response params malloc failed for bytes %d"),
507 nBytes);
508 } else {
509 sir_copy_mac_addr(pprobeRespParams->bssId, psessionEntry->bssId);
510 pprobeRespParams->pProbeRespTemplate = pFrame2Hal;
511 pprobeRespParams->probeRespTemplateLen = nBytes;
512 cdf_mem_copy(pprobeRespParams->ucProxyProbeReqValidIEBmap,
513 IeBitmap, (sizeof(uint32_t) * 8));
514 msgQ.type = WMA_SEND_PROBE_RSP_TMPL;
515 msgQ.reserved = 0;
516 msgQ.bodyptr = pprobeRespParams;
517 msgQ.bodyval = 0;
518
519 if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
520 /* free the allocated Memory */
521 sch_log(pMac, LOGE,
522 FL
523 ("lim_send_probe_rsp_template_to_hal: FAIL bytes %d retcode[%X]"),
524 nBytes, retCode);
525 cdf_mem_free(pprobeRespParams);
526 } else {
527 sch_log(pMac, LOG1,
528 FL
529 ("lim_send_probe_rsp_template_to_hal: Probe response template msg posted to HAL of bytes %d"),
530 nBytes);
531 }
532 }
533
534 return retCode;
535}
536
537/**
538 * sch_gen_timing_advert_frame() - Generate the TA frame and populate the buffer
539 * @pMac: the global MAC context
540 * @self_addr: the self MAC address
541 * @buf: the buffer that will contain the frame
542 * @timestamp_offset: return for the offset of the timestamp field
543 * @time_value_offset: return for the time_value field in the TA IE
544 *
545 * Return: the length of the buffer.
546 */
547int sch_gen_timing_advert_frame(tpAniSirGlobal mac_ctx, tSirMacAddr self_addr,
548 uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset)
549{
550 tDot11fTimingAdvertisementFrame frame;
551 uint32_t payload_size, buf_size;
552 int status;
553 struct cdf_mac_addr wildcard_bssid = {
554 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
555 };
556
557 cdf_mem_zero((uint8_t *)&frame, sizeof(tDot11fTimingAdvertisementFrame));
558
559 /* Populate the TA fields */
560 status = populate_dot11f_timing_advert_frame(mac_ctx, &frame);
561 if (status) {
562 sch_log(mac_ctx, LOGE, FL("Error populating TA frame %x"),
563 status);
564 return status;
565 }
566
567 status = dot11f_get_packed_timing_advertisement_frame_size(mac_ctx,
568 &frame, &payload_size);
569 if (DOT11F_FAILED(status)) {
570 sch_log(mac_ctx, LOGE, FL("Error getting packed frame size %x"),
571 status);
572 return status;
573 } else if (DOT11F_WARNED(status)) {
574 sch_log(mac_ctx, LOGW, FL("Warning getting packed frame size"));
575 }
576
577 buf_size = sizeof(tSirMacMgmtHdr) + payload_size;
578 *buf = cdf_mem_malloc(buf_size);
579 if (*buf == NULL) {
580 sch_log(mac_ctx, LOGE, FL("Cannot allocate memory"));
581 return eSIR_FAILURE;
582 }
583 cdf_mem_zero(*buf, buf_size);
584
585 payload_size = 0;
586 status = dot11f_pack_timing_advertisement_frame(mac_ctx, &frame,
587 *buf + sizeof(tSirMacMgmtHdr), buf_size -
588 sizeof(tSirMacMgmtHdr), &payload_size);
589 sch_log(mac_ctx, LOGE, FL("TA payload size2 = %d"), payload_size);
590 if (DOT11F_FAILED(status)) {
591 sch_log(mac_ctx, LOGE, FL("Error packing frame %x"), status);
592 goto fail;
593 } else if (DOT11F_WARNED(status)) {
594 sch_log(mac_ctx, LOGE, FL("Warning packing frame"));
595 }
596
597 lim_populate_mac_header(mac_ctx, *buf, SIR_MAC_MGMT_FRAME,
598 SIR_MAC_MGMT_TIME_ADVERT, wildcard_bssid.bytes, self_addr);
599
600 /* The timestamp field is right after the header */
601 *timestamp_offset = sizeof(tSirMacMgmtHdr);
602
603 *time_value_offset = sizeof(tSirMacMgmtHdr) +
604 sizeof(tDot11fFfTimeStamp) + sizeof(tDot11fFfCapabilities);
605
606 /* Add the Country IE length */
607 dot11f_get_packed_ie_country(mac_ctx, &frame.Country,
608 time_value_offset);
609 /* Add 2 for Country IE EID and Length fields */
610 *time_value_offset += 2;
611
612 /* Add the PowerConstraint IE size */
613 if (frame.Country.present == 1)
614 *time_value_offset += 3;
615
616 /* Add the offset inside TA IE */
617 *time_value_offset += 3;
618
619 return payload_size + sizeof(tSirMacMgmtHdr);
620
621fail:
622 if (*buf)
623 cdf_mem_free(*buf);
624 return status;
625}