blob: c8da218b9ded04782cde819513600692fd03609b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. 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 @file wlan_hdd_wmm.c
24
25 This module (wlan_hdd_wmm.h interface + wlan_hdd_wmm.c implementation)
26 houses all the logic for WMM in HDD.
27
28 On the control path, it has the logic to setup QoS, modify QoS and delete
29 QoS (QoS here refers to a TSPEC). The setup QoS comes in two flavors: an
30 explicit application invoked and an internal HDD invoked. The implicit QoS
31 is for applications that do NOT call the custom QCT WLAN OIDs for QoS but
32 which DO mark their traffic for priortization. It also has logic to start,
33 update and stop the U-APSD trigger frame generation. It also has logic to
34 read WMM related config parameters from the registry.
35
36 On the data path, it has the logic to figure out the WMM AC of an egress
37 packet and when to signal TL to serve a particular AC queue. It also has the
38 logic to retrieve a packet based on WMM priority in response to a fetch from
39 TL.
40
41 The remaining functions are utility functions for information hiding.
42
43
44 Copyright (c) 2008-9 QUALCOMM Incorporated.
45 All Rights Reserved.
46 Qualcomm Confidential and Proprietary
47============================================================================*/
48
49/*---------------------------------------------------------------------------
50 Include files
51 -------------------------------------------------------------------------*/
52#include <wlan_hdd_tx_rx.h>
53#include <wlan_hdd_dp_utils.h>
54#include <wlan_hdd_wmm.h>
55#include <wlan_hdd_ether.h>
56#include <linux/netdevice.h>
57#include <linux/skbuff.h>
58#include <linux/etherdevice.h>
59#include <linux/if_vlan.h>
60#include <linux/ip.h>
61#include <linux/semaphore.h>
62#include <wlan_hdd_hostapd.h>
63#ifdef FEATURE_WLAN_INTEGRATED_SOC
64#include <wlan_hdd_softap_tx_rx.h>
65#endif
66
67// change logging behavior based upon debug flag
68#ifdef HDD_WMM_DEBUG
69#define WMM_TRACE_LEVEL_FATAL VOS_TRACE_LEVEL_FATAL
70#define WMM_TRACE_LEVEL_ERROR VOS_TRACE_LEVEL_FATAL
71#define WMM_TRACE_LEVEL_WARN VOS_TRACE_LEVEL_FATAL
72#define WMM_TRACE_LEVEL_INFO VOS_TRACE_LEVEL_FATAL
73#define WMM_TRACE_LEVEL_INFO_HIGH VOS_TRACE_LEVEL_FATAL
74#define WMM_TRACE_LEVEL_INFO_LOW VOS_TRACE_LEVEL_FATAL
75#else
76#define WMM_TRACE_LEVEL_FATAL VOS_TRACE_LEVEL_FATAL
77#define WMM_TRACE_LEVEL_ERROR VOS_TRACE_LEVEL_ERROR
78#define WMM_TRACE_LEVEL_WARN VOS_TRACE_LEVEL_WARN
79#define WMM_TRACE_LEVEL_INFO VOS_TRACE_LEVEL_INFO
80#define WMM_TRACE_LEVEL_INFO_HIGH VOS_TRACE_LEVEL_INFO_HIGH
81#define WMM_TRACE_LEVEL_INFO_LOW VOS_TRACE_LEVEL_INFO_LOW
82#endif
83
84
85// UAPSD Mask bits
86// (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored)
87#define HDD_AC_VO 0x1
88#define HDD_AC_VI 0x2
89#define HDD_AC_BK 0x4
90#define HDD_AC_BE 0x8
91
92#define WLAN_HDD_MAX_DSCP 0x3f
93
94static sme_QosWmmUpType hddWmmDscpToUpMap[WLAN_HDD_MAX_DSCP+1];
95
96const v_U8_t hddWmmUpToAcMap[] = {
97 WLANTL_AC_BE,
98 WLANTL_AC_BK,
99 WLANTL_AC_BK,
100 WLANTL_AC_BE,
101 WLANTL_AC_VI,
102 WLANTL_AC_VI,
103 WLANTL_AC_VO,
104 WLANTL_AC_VO
105};
106
107//Linux based UP -> AC Mapping
108const v_U8_t hddLinuxUpToAcMap[8] = {
109 HDD_LINUX_AC_BE,
110 HDD_LINUX_AC_BK,
111 HDD_LINUX_AC_BK,
112 HDD_LINUX_AC_BE,
113 HDD_LINUX_AC_VI,
114 HDD_LINUX_AC_VI,
115 HDD_LINUX_AC_VO,
116 HDD_LINUX_AC_VO
117};
118
119#ifndef WLAN_MDM_CODE_REDUCTION_OPT
120/**
121 @brief hdd_wmm_enable_tl_uapsd() - function which decides whether and
122 how to update UAPSD parameters in TL
123
124 @param pQosContext : [in] the pointer the QoS instance control block
125
126 @return
127 None
128*/
129static void hdd_wmm_enable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext)
130{
131 hdd_adapter_t* pAdapter = pQosContext->pAdapter;
132 WLANTL_ACEnumType acType = pQosContext->acType;
133 hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
134 VOS_STATUS status;
135 v_U32_t service_interval;
136 v_U32_t suspension_interval;
137 sme_QosWmmDirType direction;
138
139
140 // The TSPEC must be valid
141 if (pAc->wmmAcTspecValid == VOS_FALSE)
142 {
143 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
144 "%s: Invoked with invalid TSPEC",
145 __FUNCTION__);
146 return;
147 }
148
149 // determine the service interval
150 if (pAc->wmmAcTspecInfo.min_service_interval)
151 {
152 service_interval = pAc->wmmAcTspecInfo.min_service_interval;
153 }
154 else if (pAc->wmmAcTspecInfo.max_service_interval)
155 {
156 service_interval = pAc->wmmAcTspecInfo.max_service_interval;
157 }
158 else
159 {
160 // no service interval is present in the TSPEC
161 // this is OK, there just won't be U-APSD
162 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
163 "%s: No service interval supplied",
164 __FUNCTION__);
165 return;
166 }
167
168 // determine the suspension interval & direction
169 suspension_interval = pAc->wmmAcTspecInfo.suspension_interval;
170 direction = pAc->wmmAcTspecInfo.ts_info.direction;
171
172 // if we have previously enabled U-APSD, have any params changed?
173 if ((pAc->wmmAcUapsdInfoValid) &&
174 (pAc->wmmAcUapsdServiceInterval == service_interval) &&
175 (pAc->wmmAcUapsdSuspensionInterval == suspension_interval) &&
176 (pAc->wmmAcUapsdDirection == direction))
177 {
178 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
179 "%s: No change in U-APSD parameters",
180 __FUNCTION__);
181 return;
182 }
183
184 // are we in the appropriate power save modes?
185 if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_BEACON_MODE_POWER_SAVE))
186 {
187 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
188 "%s: BMPS is not enabled",
189 __FUNCTION__);
190 return;
191 }
192
193 if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_UAPSD_MODE_POWER_SAVE))
194 {
195 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
196 "%s: U-APSD is not enabled",
197 __FUNCTION__);
198 return;
199 }
200
201 // everything is in place to notify TL
202 status = WLANTL_EnableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
203 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
204 acType,
205 pAc->wmmAcTspecInfo.ts_info.tid,
206 pAc->wmmAcTspecInfo.ts_info.up,
207 service_interval,
208 suspension_interval,
209 direction);
210
211 if ( !VOS_IS_STATUS_SUCCESS( status ) )
212 {
213 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
214 "%s: Failed to enable U-APSD for AC=%d",
215 __FUNCTION__, acType );
216 return;
217 }
218
219 // stash away the parameters that were used
220 pAc->wmmAcUapsdInfoValid = VOS_TRUE;
221 pAc->wmmAcUapsdServiceInterval = service_interval;
222 pAc->wmmAcUapsdSuspensionInterval = suspension_interval;
223 pAc->wmmAcUapsdDirection = direction;
224
225 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
226 "%s: Enabled UAPSD in TL srv_int=%ld "
227 "susp_int=%ld dir=%d AC=%d",
228 __FUNCTION__,
229 service_interval,
230 suspension_interval,
231 direction,
232 acType);
233
234}
235
236/**
237 @brief hdd_wmm_disable_tl_uapsd() - function which decides whether
238 to disable UAPSD parameters in TL
239
240 @param pQosContext : [in] the pointer the QoS instance control block
241
242 @return
243 None
244*/
245static void hdd_wmm_disable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext)
246{
247 hdd_adapter_t* pAdapter = pQosContext->pAdapter;
248 WLANTL_ACEnumType acType = pQosContext->acType;
249 hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
250 VOS_STATUS status;
251
252
253 // have we previously enabled UAPSD?
254 if (pAc->wmmAcUapsdInfoValid == VOS_TRUE)
255 {
256 status = WLANTL_DisableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
257 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
258 acType);
259
260 if ( !VOS_IS_STATUS_SUCCESS( status ) )
261 {
262 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
263 "%s: Failed to disable U-APSD for AC=%d",
264 __FUNCTION__, acType );
265 }
266 else
267 {
268 // TL no longer has valid UAPSD info
269 pAc->wmmAcUapsdInfoValid = VOS_FALSE;
270 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
271 "%s: Disabled UAPSD in TL for AC=%d",
272 __FUNCTION__,
273 acType);
274 }
275 }
276}
277
278#endif
279
280/**
281 @brief hdd_wmm_free_context() - function which frees a QoS context
282
283 @param pQosContext : [in] the pointer the QoS instance control block
284
285 @return
286 None
287*/
288static void hdd_wmm_free_context (hdd_wmm_qos_context_t* pQosContext)
289{
290 hdd_adapter_t* pAdapter;
291
292 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
293 "%s: Entered, context %p",
294 __FUNCTION__, pQosContext);
295
296 if (unlikely((NULL == pQosContext) ||
297 (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
298 {
299 // must have been freed in another thread
300 return;
301 }
302
303 // get pointer to the adapter context
304 pAdapter = pQosContext->pAdapter;
305
306 // take the wmmLock since we're manipulating the context list
307 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
308
309 // make sure nobody thinks this is a valid context
310 pQosContext->magic = 0;
311
312 // unlink the context
313 list_del(&pQosContext->node);
314
315 // done manipulating the list
316 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
317
318 // reclaim memory
319 kfree(pQosContext);
320
321}
322
323#ifndef WLAN_MDM_CODE_REDUCTION_OPT
324/**
325 @brief hdd_wmm_notify_app() - function which notifies an application
326 changes in state of it flow
327
328 @param pQosContext : [in] the pointer the QoS instance control block
329
330 @return
331 None
332*/
333#define MAX_NOTIFY_LEN 50
334static void hdd_wmm_notify_app (hdd_wmm_qos_context_t* pQosContext)
335{
336 hdd_adapter_t* pAdapter;
337 union iwreq_data wrqu;
338 char buf[MAX_NOTIFY_LEN+1];
339
340 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
341 "%s: Entered, context %p",
342 __FUNCTION__, pQosContext);
343
344 if (unlikely((NULL == pQosContext) ||
345 (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
346 {
347 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
348 "%s: Invalid QoS Context",
349 __FUNCTION__);
350 return;
351 }
352
353
354 // create the event
355 memset(&wrqu, 0, sizeof(wrqu));
356 memset(buf, 0, sizeof(buf));
357
358 snprintf(buf, MAX_NOTIFY_LEN, "QCOM: TS change[%u: %u]",
359 (unsigned int)pQosContext->handle,
360 (unsigned int)pQosContext->lastStatus);
361
362 wrqu.data.pointer = buf;
363 wrqu.data.length = strlen(buf);
364
365 // get pointer to the adapter
366 pAdapter = pQosContext->pAdapter;
367
368 // send the event
369 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
370 "%s: Sending [%s]", __FUNCTION__, buf);
371 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
372}
373
374
375/**
376 @brief hdd_wmm_is_access_allowed() - function which determines if access
377 is allowed for the given AC. this is designed to be called during SME
378 callback processing since that is when access can be granted or removed
379
380 @param pAdapter : [in] pointer to adapter context
381 @param pAc : [in] pointer to the per-AC status
382
383 @return : VOS_TRUE - access is allowed
384 : VOS_FALSE - access is not allowed
385 None
386*/
387static v_BOOL_t hdd_wmm_is_access_allowed(hdd_adapter_t* pAdapter,
388 hdd_wmm_ac_status_t* pAc)
389{
390 // if we don't want QoS or the AP doesn't support QoS
391 // or we don't want to do implicit QoS
392 // or if AP doesn't require admission for this AC
393 // then we have access
394 if (!hdd_wmm_is_active(pAdapter) ||
395 !(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->bImplicitQosEnabled ||
396 !pAc->wmmAcAccessRequired)
397 {
398 return VOS_TRUE;
399 }
400
401 // if implicit QoS has already completed, successfully or not,
402 // then access is allowed
403 if (pAc->wmmAcAccessGranted || pAc->wmmAcAccessFailed)
404 {
405 return VOS_TRUE;
406 }
407
408 // admission is required and implicit QoS hasn't completed
409 // however explicit QoS may have completed and we'll have
410 // a Tspec
411 // if we don't have a Tspec then access is not allowed
412 if (!pAc->wmmAcTspecValid)
413 {
414 return VOS_FALSE;
415 }
416
417 // we have a Tspec -- does it allow upstream or bidirectional traffic?
418 // if it only allows downstream traffic then access is not allowed
419 if (pAc->wmmAcTspecInfo.ts_info.direction == SME_QOS_WMM_TS_DIR_DOWNLINK)
420 {
421 return VOS_FALSE;
422 }
423
424 // we meet all of the criteria for access
425 return VOS_TRUE;
426}
427
428#ifdef FEATURE_WLAN_CCX
429/**
430 @brief hdd_wmm_inactivity_timer_cb() - timer handler function which is
431 called for every inactivity interval per AC. This function gets the
432 current transmitted packets on the given AC, and checks if there where
433 any TX activity from the previous interval. If there was no traffic
434 then it would delete the TS that was negotiated on that AC.
435
436 @param pUserData : [in] pointer to pQosContext
437
438 @return : NONE
439*/
440void hdd_wmm_inactivity_timer_cb( v_PVOID_t pUserData )
441{
442 hdd_wmm_qos_context_t* pQosContext = (hdd_wmm_qos_context_t*)pUserData;
443 hdd_adapter_t* pAdapter;
444 hdd_wmm_ac_status_t *pAc;
445 hdd_wlan_wmm_status_e status;
446 VOS_STATUS vos_status;
447 v_U32_t currentTrafficCnt = 0;
448 WLANTL_ACEnumType acType = pQosContext->acType;
449
450 pAdapter = pQosContext->pAdapter;
451 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
452
453 // Get the Tx stats for this AC.
454 currentTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType];
455
456 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
457 FL("WMM inactivity Timer for AC=%d, currentCnt=%d, prevCnt=%d\n"),
458 acType, (int)currentTrafficCnt, (int)pAc->wmmPrevTrafficCnt);
459 if (pAc->wmmPrevTrafficCnt == currentTrafficCnt)
460 {
461 // If there is no traffic activity, delete the TSPEC for this AC
462 status = hdd_wmm_delts(pAdapter, pQosContext->handle);
463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
464 FL("Deleted TS on AC %d, due to inactivity with status = %d!!!"),
465 acType, status);
466 }
467 else
468 {
469 pAc->wmmPrevTrafficCnt = currentTrafficCnt;
470 if (pAc->wmmInactivityTimer.state == VOS_TIMER_STATE_STOPPED)
471 {
472 // Restart the timer
473 vos_status = vos_timer_start(&pAc->wmmInactivityTimer, pAc->wmmInactivityTime);
474 if (!VOS_IS_STATUS_SUCCESS(vos_status))
475 {
476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
477 FL("Restarting inactivity timer failed on AC %d"), acType);
478 }
479 }
480 else
481 {
482 VOS_ASSERT(vos_timer_getCurrentState(
483 &pAc->wmmInactivityTimer) == VOS_TIMER_STATE_STOPPED);
484 }
485 }
486
487 return;
488}
489
490
491/**
492 @brief hdd_wmm_enable_inactivity_timer() - function to enable the
493 traffic inactivity timer for the given AC, if the inactivity_interval
494 specified in the ADDTS parameters is non-zero
495
496 @param pQosContext : [in] pointer to pQosContext
497 @param inactivityTime: [in] value of the inactivity interval in millisecs
498
499 @return : VOS_STATUS_E_FAILURE
500 VOS_STATUS_SUCCESS
501*/
502VOS_STATUS hdd_wmm_enable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext, v_U32_t inactivityTime)
503{
504 VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
505 hdd_adapter_t* pAdapter = pQosContext->pAdapter;
506 WLANTL_ACEnumType acType = pQosContext->acType;
507 hdd_wmm_ac_status_t *pAc;
508
509 pAdapter = pQosContext->pAdapter;
510 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
511
512
513 // If QoS-Tspec is successfully setup and if the inactivity timer is non-zero,
514 // a traffic inactivity timer needs to be started for the given AC
515 vos_status = vos_timer_init(
516 &pAc->wmmInactivityTimer,
517 VOS_TIMER_TYPE_SW,
518 hdd_wmm_inactivity_timer_cb,
519 (v_PVOID_t)pQosContext );
520 if ( !VOS_IS_STATUS_SUCCESS(vos_status))
521 {
522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
523 FL("Initializing inactivity timer failed on AC %d"), acType);
524 return vos_status;
525 }
526
527 // Start the inactivity timer
528 vos_status = vos_timer_start(
529 &pAc->wmmInactivityTimer,
530 inactivityTime);
531 if ( !VOS_IS_STATUS_SUCCESS(vos_status))
532 {
533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
534 FL("Starting inactivity timer failed on AC %d"), acType);
535 return vos_status;
536 }
537 pAc->wmmInactivityTime = inactivityTime;
538 // Initialize the current tx traffic count on this AC
539 pAc->wmmPrevTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType];
540
541 return vos_status;
542}
543
544/**
545 @brief hdd_wmm_enable_inactivity_timer() - function to disable the
546 traffic inactivity timer for the given AC. This would be called when
547 deleting the TS.
548
549 @param pQosContext : [in] pointer to pQosContext
550
551 @return : VOS_STATUS_E_FAILURE
552 VOS_STATUS_SUCCESS
553*/
554VOS_STATUS hdd_wmm_disable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext)
555{
556 hdd_adapter_t* pAdapter = pQosContext->pAdapter;
557 WLANTL_ACEnumType acType = pQosContext->acType;
558 hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
559 VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
560
561 // Clear the timer and the counter
562 pAc->wmmInactivityTime = 0;
563 pAc->wmmPrevTrafficCnt = 0;
564 vos_timer_stop(&pAc->wmmInactivityTimer);
565 vos_status = vos_timer_destroy(&pAc->wmmInactivityTimer);
566
567 return vos_status;
568}
569#endif // FEATURE_WLAN_CCX
570
571/**
572 @brief hdd_wmm_sme_callback() - callback registered by HDD with SME for receiving
573 QoS notifications. Even though this function has a static scope it gets called
574 externally through some function pointer magic (so there is a need for
575 rigorous parameter checking)
576
577 @param hHal : [in] the HAL handle
578 @param HddCtx : [in] the HDD specified handle
579 @param pCurrentQosInfo : [in] the TSPEC params
580 @param SmeStatus : [in] the QoS related SME status
581
582 @return
583 eHAL_STATUS_SUCCESS if all good, eHAL_STATUS_FAILURE otherwise
584*/
585static eHalStatus hdd_wmm_sme_callback (tHalHandle hHal,
586 void * hddCtx,
587 sme_QosWmmTspecInfo* pCurrentQosInfo,
588 sme_QosStatusType smeStatus,
589 v_U32_t qosFlowId)
590{
591 hdd_wmm_qos_context_t* pQosContext = hddCtx;
592 hdd_adapter_t* pAdapter;
593 WLANTL_ACEnumType acType;
594 hdd_wmm_ac_status_t *pAc;
595 VOS_STATUS status;
596
597 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
598 "%s: Entered, context %p",
599 __FUNCTION__, pQosContext);
600
601 if (unlikely((NULL == pQosContext) ||
602 (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
603 {
604 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
605 "%s: Invalid QoS Context",
606 __FUNCTION__);
607 return eHAL_STATUS_FAILURE;
608 }
609
610 pAdapter = pQosContext->pAdapter;
611 acType = pQosContext->acType;
612 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
613
614 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
615 "%s: status %d flowid %d info %p",
616 __FUNCTION__, smeStatus, qosFlowId, pCurrentQosInfo);
617
618 switch (smeStatus)
619 {
620
621 case SME_QOS_STATUS_SETUP_SUCCESS_IND:
622 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
623 "%s: Setup is complete",
624 __FUNCTION__);
625
626 // there will always be a TSPEC returned with this status, even if
627 // a TSPEC is not exchanged OTA
628 if (pCurrentQosInfo)
629 {
630 pAc->wmmAcTspecValid = VOS_TRUE;
631 memcpy(&pAc->wmmAcTspecInfo,
632 pCurrentQosInfo,
633 sizeof(pAc->wmmAcTspecInfo));
634 }
635
636 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
637 {
638
639 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
640 "%s: Implicit Qos, notifying TL for TL AC %d",
641 __FUNCTION__, acType);
642
643 // this was triggered by implicit QoS so we know packets are pending
644 // update state
645 pAc->wmmAcAccessAllowed = VOS_TRUE;
646 pAc->wmmAcAccessGranted = VOS_TRUE;
647 pAc->wmmAcAccessPending = VOS_FALSE;
648
649 // notify TL that packets are pending
650 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
651 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
652 acType );
653
654 if ( !VOS_IS_STATUS_SUCCESS( status ) )
655 {
656 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
657 "%s: Failed to signal TL for AC=%d",
658 __FUNCTION__, acType );
659 }
660 }
661 else
662 {
663 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
664 "%s: Explicit Qos, notifying userspace",
665 __FUNCTION__);
666
667 // this was triggered by an application
668 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS;
669 hdd_wmm_notify_app(pQosContext);
670 }
671
672#ifdef FEATURE_WLAN_CCX
673 // Check if the inactivity interval is specified
674 if (pCurrentQosInfo->inactivity_interval) {
675 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
676 "%s: Inactivity timer value = %d for AC=%d\n",
677 __FUNCTION__, pCurrentQosInfo->inactivity_interval, acType);
678 hdd_wmm_enable_inactivity_timer(pQosContext, pCurrentQosInfo->inactivity_interval);
679 }
680#endif // FEATURE_WLAN_CCX
681
682 // notify TL to enable trigger frames if necessary
683 hdd_wmm_enable_tl_uapsd(pQosContext);
684
685 break;
686
687 case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
688 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
689 "%s: Setup is complete (U-APSD set previously)",
690 __FUNCTION__);
691
692 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
693 {
694
695 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
696 "%s: Implicit Qos, notifying TL",
697 __FUNCTION__);
698
699 // this was triggered by implicit QoS so we know packets are pending
700 // update state
701 pAc->wmmAcAccessAllowed = VOS_TRUE;
702 pAc->wmmAcAccessGranted = VOS_TRUE;
703 pAc->wmmAcAccessPending = VOS_FALSE;
704
705 // notify TL that packets are pending
706 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
707 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
708 acType );
709
710 if ( !VOS_IS_STATUS_SUCCESS( status ) )
711 {
712 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
713 "%s: Failed to signal TL for AC=%d",
714 __FUNCTION__, acType );
715 }
716 }
717 else
718 {
719 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
720 "%s: Explicit Qos, notifying userspace",
721 __FUNCTION__);
722
723 // this was triggered by an application
724 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
725 hdd_wmm_notify_app(pQosContext);
726 }
727
728 break;
729
730 case SME_QOS_STATUS_SETUP_FAILURE_RSP:
731 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
732 "%s: Setup failed",
733 __FUNCTION__);
734 // QoS setup failed
735
736 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
737 {
738
739 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
740 "%s: Implicit Qos, notifying TL",
741 __FUNCTION__);
742
743 // we note the failure, but we also mark access as allowed so that
744 // the packets will flow. Note that the MAC will "do the right thing"
745 pAc->wmmAcAccessPending = VOS_FALSE;
746 pAc->wmmAcAccessFailed = VOS_TRUE;
747 pAc->wmmAcAccessAllowed = VOS_TRUE;
748
749 // this was triggered by implicit QoS so we know packets are pending
750 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
751 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
752 acType );
753
754 if ( !VOS_IS_STATUS_SUCCESS( status ) )
755 {
756 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
757 "%s: Failed to signal TL for AC=%d",
758 __FUNCTION__, acType );
759 }
760 }
761 else
762 {
763 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
764 "%s: Explicit Qos, notifying userspace",
765 __FUNCTION__);
766
767 // this was triggered by an application
768 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED;
769 hdd_wmm_notify_app(pQosContext);
770 }
771
772 /* Setting up QoS Failed, QoS context can be released.
773 * SME is releasing this flow information and if HDD doen't release this context,
774 * next time if application uses the same handle to set-up QoS, HDD (as it has
775 * QoS context for this handle) will issue Modify QoS request to SME but SME will
776 * reject as no it has no information for this flow.
777 */
778 hdd_wmm_free_context(pQosContext);
779 break;
780
781 case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
782 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
783 "%s: Setup Invalid Params, notify TL",
784 __FUNCTION__);
785 // QoS setup failed
786
787 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
788 {
789
790 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
791 "%s: Implicit Qos, notifying TL",
792 __FUNCTION__);
793
794 // we note the failure, but we also mark access as allowed so that
795 // the packets will flow. Note that the MAC will "do the right thing"
796 pAc->wmmAcAccessPending = VOS_FALSE;
797 pAc->wmmAcAccessFailed = VOS_TRUE;
798 pAc->wmmAcAccessAllowed = VOS_TRUE;
799
800 // this was triggered by implicit QoS so we know packets are pending
801 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
802 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
803 acType );
804
805 if ( !VOS_IS_STATUS_SUCCESS( status ) )
806 {
807 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
808 "%s: Failed to signal TL for AC=%d",
809 __FUNCTION__, acType );
810 }
811 }
812 else
813 {
814 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
815 "%s: Explicit Qos, notifying userspace",
816 __FUNCTION__);
817
818 // this was triggered by an application
819 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
820 hdd_wmm_notify_app(pQosContext);
821 }
822 break;
823
824 case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
825 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
826 "%s: Setup failed, not a QoS AP\n",
827 __FUNCTION__);
828 if (!HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
829 {
830 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
831 "%s: Explicit Qos, notifying userspace",
832 __FUNCTION__);
833
834 // this was triggered by an application
835 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
836 hdd_wmm_notify_app(pQosContext);
837 }
838 break;
839
840 case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
841 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
842 "%s: Setup pending",
843 __FUNCTION__);
844 // not a callback status -- ignore if we get it
845 break;
846
847 case SME_QOS_STATUS_SETUP_MODIFIED_IND:
848 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
849 "%s: Setup modified",
850 __FUNCTION__);
851 if (pCurrentQosInfo)
852 {
853 // update the TSPEC
854 pAc->wmmAcTspecValid = VOS_TRUE;
855 memcpy(&pAc->wmmAcTspecInfo,
856 pCurrentQosInfo,
857 sizeof(pAc->wmmAcTspecInfo));
858
859 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
860 {
861 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
862 "%s: Explicit Qos, notifying userspace",
863 __FUNCTION__);
864
865 // this was triggered by an application
866 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFIED;
867 hdd_wmm_notify_app(pQosContext);
868 }
869
870 // need to tell TL to update its UAPSD handling
871 hdd_wmm_enable_tl_uapsd(pQosContext);
872 }
873 break;
874
875 case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
876 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
877 {
878
879 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
880 "%s: Implicit Qos, notifying TL",
881 __FUNCTION__);
882
883 // this was triggered by implicit QoS so we know packets are pending
884 pAc->wmmAcAccessPending = VOS_FALSE;
885 pAc->wmmAcAccessGranted = VOS_TRUE;
886 pAc->wmmAcAccessAllowed = VOS_TRUE;
887
888 // notify TL that packets are pending
889 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
890 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
891 acType );
892
893 if ( !VOS_IS_STATUS_SUCCESS( status ) )
894 {
895 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
896 "%s: Failed to signal TL for AC=%d",
897 __FUNCTION__, acType );
898 }
899 }
900 else
901 {
902 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
903 "%s: Explicit Qos, notifying userspace",
904 __FUNCTION__);
905
906 // this was triggered by an application
907 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
908 hdd_wmm_notify_app(pQosContext);
909 }
910 break;
911
912 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
913 // nothing to do for now
914 break;
915
916 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED:
917 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
918 "%s: Setup successful but U-APSD failed",
919 __FUNCTION__);
920
921 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
922 {
923
924 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
925 "%s: Implicit Qos, notifying TL",
926 __FUNCTION__);
927
928 // QoS setup was successful but setting U=APSD failed
929 // Since the OTA part of the request was successful, we don't mark
930 // this as a failure.
931 // the packets will flow. Note that the MAC will "do the right thing"
932 pAc->wmmAcAccessGranted = VOS_TRUE;
933 pAc->wmmAcAccessAllowed = VOS_TRUE;
934 pAc->wmmAcAccessFailed = VOS_FALSE;
935 pAc->wmmAcAccessPending = VOS_FALSE;
936
937 // this was triggered by implicit QoS so we know packets are pending
938 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
939 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
940 acType );
941
942 if ( !VOS_IS_STATUS_SUCCESS( status ) )
943 {
944 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
945 "%s: Failed to signal TL for AC=%d",
946 __FUNCTION__, acType );
947 }
948 }
949 else
950 {
951 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
952 "%s: Explicit Qos, notifying userspace",
953 __FUNCTION__);
954
955 // this was triggered by an application
956 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_UAPSD_SET_FAILED;
957 hdd_wmm_notify_app(pQosContext);
958 }
959
960 // Since U-APSD portion failed disabled trigger frame generation
961 hdd_wmm_disable_tl_uapsd(pQosContext);
962
963 break;
964
965 case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
966 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
967 "%s: Release is complete",
968 __FUNCTION__);
969
970 if (pCurrentQosInfo)
971 {
972 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
973 "%s: flows still active",
974 __FUNCTION__);
975
976 // there is still at least one flow active for this AC
977 // so update the AC state
978 memcpy(&pAc->wmmAcTspecInfo,
979 pCurrentQosInfo,
980 sizeof(pAc->wmmAcTspecInfo));
981
982 // need to tell TL to update its UAPSD handling
983 hdd_wmm_enable_tl_uapsd(pQosContext);
984 }
985 else
986 {
987 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
988 "%s: last flow",
989 __FUNCTION__);
990
991 // this is the last flow active for this AC so update the AC state
992 pAc->wmmAcTspecValid = VOS_FALSE;
993
994 // need to tell TL to update its UAPSD handling
995 hdd_wmm_disable_tl_uapsd(pQosContext);
996 }
997
998 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
999 {
1000 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1001 "%s: Explicit Qos, notifying userspace",
1002 __FUNCTION__);
1003
1004 // this was triggered by an application
1005 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
1006 hdd_wmm_notify_app(pQosContext);
1007 }
1008
1009 // we are done with this flow
1010 hdd_wmm_free_context(pQosContext);
1011 break;
1012
1013 case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
1014 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1015 "%s: Release failure",
1016 __FUNCTION__);
1017
1018 // we don't need to update our state or TL since nothing has changed
1019 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1020 {
1021 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1022 "%s: Explicit Qos, notifying userspace",
1023 __FUNCTION__);
1024
1025 // this was triggered by an application
1026 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
1027 hdd_wmm_notify_app(pQosContext);
1028 }
1029
1030 break;
1031
1032 case SME_QOS_STATUS_RELEASE_QOS_LOST_IND:
1033 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1034 "%s: QOS Lost indication received",
1035 __FUNCTION__);
1036
1037 // current TSPEC is no longer valid
1038 pAc->wmmAcTspecValid = VOS_FALSE;
1039
1040 // need to tell TL to update its UAPSD handling
1041 hdd_wmm_disable_tl_uapsd(pQosContext);
1042
1043 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
1044 {
1045 // we no longer have implicit access granted
1046 pAc->wmmAcAccessGranted = VOS_FALSE;
1047 pAc->wmmAcAccessFailed = VOS_FALSE;
1048 }
1049 else
1050 {
1051 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1052 "%s: Explicit Qos, notifying userspace",
1053 __FUNCTION__);
1054
1055 // this was triggered by an application
1056 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_LOST;
1057 hdd_wmm_notify_app(pQosContext);
1058 }
1059
1060 // we are done with this flow
1061 hdd_wmm_free_context(pQosContext);
1062 break;
1063
1064 case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
1065 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1066 "%s: Release pending",
1067 __FUNCTION__);
1068 // not a callback status -- ignore if we get it
1069 break;
1070
1071 case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
1072 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1073 "%s: Release Invalid Params",
1074 __FUNCTION__);
1075 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1076 {
1077 // this was triggered by an application
1078 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
1079 hdd_wmm_notify_app(pQosContext);
1080 }
1081 break;
1082
1083 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND:
1084 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1085 "%s: Modification is complete, notify TL",
1086 __FUNCTION__);
1087
1088 // there will always be a TSPEC returned with this status, even if
1089 // a TSPEC is not exchanged OTA
1090 if (pCurrentQosInfo)
1091 {
1092 pAc->wmmAcTspecValid = VOS_TRUE;
1093 memcpy(&pAc->wmmAcTspecInfo,
1094 pCurrentQosInfo,
1095 sizeof(pAc->wmmAcTspecInfo));
1096 }
1097
1098 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1099 {
1100 // this was triggered by an application
1101 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS;
1102 hdd_wmm_notify_app(pQosContext);
1103 }
1104
1105 // notify TL to enable trigger frames if necessary
1106 hdd_wmm_enable_tl_uapsd(pQosContext);
1107
1108 break;
1109
1110 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
1111 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1112 {
1113 // this was triggered by an application
1114 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
1115 hdd_wmm_notify_app(pQosContext);
1116 }
1117 break;
1118
1119 case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
1120 // the flow modification failed so we'll leave in place
1121 // whatever existed beforehand
1122
1123 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1124 {
1125 // this was triggered by an application
1126 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
1127 hdd_wmm_notify_app(pQosContext);
1128 }
1129 break;
1130
1131 case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
1132 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1133 "%s: modification pending",
1134 __FUNCTION__);
1135 // not a callback status -- ignore if we get it
1136 break;
1137
1138 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
1139 // the flow modification was successful but no QoS changes required
1140
1141 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1142 {
1143 // this was triggered by an application
1144 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
1145 hdd_wmm_notify_app(pQosContext);
1146 }
1147 break;
1148
1149 case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
1150 // invalid params -- notify the application
1151 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1152 {
1153 // this was triggered by an application
1154 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
1155 hdd_wmm_notify_app(pQosContext);
1156 }
1157 break;
1158
1159 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_PENDING:
1160 // nothing to do for now. when APSD is established we'll have work to do
1161 break;
1162
1163 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED:
1164 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1165 "%s: Modify successful but U-APSD failed",
1166 __FUNCTION__);
1167
1168 // QoS modification was successful but setting U=APSD failed.
1169 // This will always be an explicit QoS instance, so all we can
1170 // do is notify the application and let it clean up.
1171 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
1172 {
1173 // this was triggered by an application
1174 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_UAPSD_SET_FAILED;
1175 hdd_wmm_notify_app(pQosContext);
1176 }
1177
1178 // Since U-APSD portion failed disabled trigger frame generation
1179 hdd_wmm_disable_tl_uapsd(pQosContext);
1180
1181 break;
1182
1183 case SME_QOS_STATUS_HANDING_OFF:
1184 // no roaming so we won't see this
1185 break;
1186
1187 case SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND:
1188 // need to tell TL to stop trigger frame generation
1189 hdd_wmm_disable_tl_uapsd(pQosContext);
1190 break;
1191
1192 case SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND:
1193 // need to tell TL to start sending trigger frames again
1194 hdd_wmm_enable_tl_uapsd(pQosContext);
1195 break;
1196
1197 default:
1198 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1199 "%s: unexpected SME Status=%d\n",
1200 __FUNCTION__, smeStatus );
1201 VOS_ASSERT(0);
1202 }
1203
1204 // our access to the particular access category may have changed.
1205 // some of the implicit QoS cases above may have already set this
1206 // prior to invoking TL (so that we will properly service the
1207 // Tx queues) but let's consistently handle all cases here
1208 pAc->wmmAcAccessAllowed = hdd_wmm_is_access_allowed(pAdapter, pAc);
1209
1210 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1211 "%s: complete, access for TL AC %d is%sallowed",
1212 __FUNCTION__,
1213 acType,
1214 pAc->wmmAcAccessAllowed ? " " : " not ");
1215
1216 return eHAL_STATUS_SUCCESS;
1217}
1218#endif
1219
1220/**============================================================================
1221 @brief hdd_wmm_do_implicit_qos() - Function which will attempt to setup
1222 QoS for any AC requiring it
1223
1224 @param work : [in] pointer to work structure
1225
1226 @return : void
1227 ===========================================================================*/
1228static void hdd_wmm_do_implicit_qos(struct work_struct *work)
1229{
1230 hdd_wmm_qos_context_t* pQosContext =
1231 container_of(work, hdd_wmm_qos_context_t, wmmAcSetupImplicitQos);
1232 hdd_adapter_t* pAdapter;
1233 WLANTL_ACEnumType acType;
1234 hdd_wmm_ac_status_t *pAc;
1235#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1236 VOS_STATUS status;
1237 sme_QosStatusType smeStatus;
1238#endif
1239 sme_QosWmmTspecInfo qosInfo;
1240
1241 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1242 "%s: Entered, context %p",
1243 __FUNCTION__, pQosContext);
1244
1245 if (unlikely(HDD_WMM_CTX_MAGIC != pQosContext->magic))
1246 {
1247 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1248 "%s: Invalid QoS Context",
1249 __FUNCTION__);
1250 return;
1251 }
1252
1253 pAdapter = pQosContext->pAdapter;
1254 acType = pQosContext->acType;
1255 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
1256
1257 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1258 "%s: pAdapter %p acType %d",
1259 __FUNCTION__, pAdapter, acType);
1260
1261 if (!pAc->wmmAcAccessNeeded)
1262 {
1263 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1264 "%s: AC %d doesn't need service",
1265 __FUNCTION__, acType);
1266 pQosContext->magic = 0;
1267 kfree(pQosContext);
1268 return;
1269 }
1270
1271 pAc->wmmAcAccessPending = VOS_TRUE;
1272 pAc->wmmAcAccessNeeded = VOS_FALSE;
1273
1274 memset(&qosInfo, 0, sizeof(qosInfo));
1275
1276 switch (acType)
1277 {
1278 case WLANTL_AC_VO:
1279 qosInfo.ts_info.up = SME_QOS_WMM_UP_VO;
1280 qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x01;
1281 qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVo;
1282 qosInfo.ts_info.tid = 255;
1283 qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVo;
1284 qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVo;
1285 qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv;
1286 qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVo;
1287 qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVo;
1288 qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv;
1289 break;
1290 case WLANTL_AC_VI:
1291 qosInfo.ts_info.up = SME_QOS_WMM_UP_VI;
1292 qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x02;
1293 qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVi;
1294 qosInfo.ts_info.tid = 255;
1295 qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVi;
1296 qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVi;
1297 qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv;
1298 qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVi;
1299 qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVi;
1300 qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv;
1301 break;
1302 default:
1303 case WLANTL_AC_BE:
1304 qosInfo.ts_info.up = SME_QOS_WMM_UP_BE;
1305 qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x08;
1306 qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBe;
1307 qosInfo.ts_info.tid = 255;
1308 qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBe;
1309 qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBe;
1310 qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv;
1311 qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBe;
1312 qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBe;
1313 qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv;
1314 break;
1315 case WLANTL_AC_BK:
1316 qosInfo.ts_info.up = SME_QOS_WMM_UP_BK;
1317 qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x04;
1318 qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBk;
1319 qosInfo.ts_info.tid = 255;
1320 qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBk;
1321 qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBk;
1322 qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv;
1323 qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBk;
1324 qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBk;
1325 qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv;
1326 break;
1327 }
1328#ifdef FEATURE_WLAN_CCX
1329 qosInfo.inactivity_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraInactivityInterval;
1330#endif
1331 qosInfo.ts_info.burst_size_defn = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->burstSizeDefinition;
1332
1333 switch ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->tsInfoAckPolicy)
1334 {
1335 case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK:
1336 qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
1337 break;
1338
1339 case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK:
1340 qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
1341 break;
1342
1343 default:
1344 // unknown
1345 qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
1346 }
1347
1348 if(qosInfo.ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)
1349 {
1350 if(!sme_QosIsTSInfoAckPolicyValid((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), &qosInfo, pAdapter->sessionId))
1351 {
1352 qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
1353 }
1354 }
1355
1356 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
1357 list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
1358 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
1359
1360#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1361 smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
1362 pAdapter->sessionId,
1363 &qosInfo,
1364 hdd_wmm_sme_callback,
1365 pQosContext,
1366 qosInfo.ts_info.up,
1367 &pQosContext->qosFlowId);
1368
1369 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1370 "%s: sme_QosSetupReq returned %d flowid %d",
1371 __FUNCTION__, smeStatus, pQosContext->qosFlowId);
1372
1373 // need to check the return values and act appropriately
1374 switch (smeStatus)
1375 {
1376 case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
1377 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
1378 // setup is pending, so no more work to do now.
1379 // all further work will be done in hdd_wmm_sme_callback()
1380 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1381 "%s: Setup is pending, no further work",
1382 __FUNCTION__);
1383
1384 break;
1385
1386
1387 case SME_QOS_STATUS_SETUP_FAILURE_RSP:
1388 // we can't tell the difference between when a request fails because
1389 // AP rejected it versus when SME encountered an internal error
1390
1391 // in either case SME won't ever reference this context so
1392 // free the record
1393 hdd_wmm_free_context(pQosContext);
1394
1395 // fall through and start packets flowing
1396 case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
1397 // no ACM in effect, no need to setup U-APSD
1398 case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
1399 // no ACM in effect, U-APSD is desired but was already setup
1400
1401 // for these cases everything is already setup so we can
1402 // signal TL that it has work to do
1403 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1404 "%s: Setup is complete, notify TL",
1405 __FUNCTION__);
1406
1407 pAc->wmmAcAccessAllowed = VOS_TRUE;
1408 pAc->wmmAcAccessGranted = VOS_TRUE;
1409 pAc->wmmAcAccessPending = VOS_FALSE;
1410
1411 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1412 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
1413 acType );
1414
1415 if ( !VOS_IS_STATUS_SUCCESS( status ) )
1416 {
1417 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1418 "%s: Failed to signal TL for AC=%d",
1419 __FUNCTION__, acType );
1420 }
1421
1422 break;
1423
1424
1425 default:
1426 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1427 "%s: unexpected SME Status=%d\n",
1428 __FUNCTION__, smeStatus );
1429 VOS_ASSERT(0);
1430 }
1431#endif
1432
1433}
1434
1435/**============================================================================
1436 @brief hdd_wmm_init() - Function which will initialize the WMM configuation
1437 and status to an initial state. The configuration can later be overwritten
1438 via application APIs
1439
1440 @param pHddCtx : [in] pointer to HDD context
1441
1442 @return : VOS_STATUS_SUCCESS if succssful
1443 : other values if failure
1444
1445 ===========================================================================*/
1446VOS_STATUS hdd_wmm_init ( hdd_context_t* pHddCtx )
1447{
1448 v_U8_t dscp;
1449
1450 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1451 "%s: Entered", __FUNCTION__);
1452
1453 // DSCP to User Priority Lookup Table
1454 for (dscp = 0; dscp <= WLAN_HDD_MAX_DSCP; dscp++)
1455 {
1456 hddWmmDscpToUpMap[dscp] = SME_QOS_WMM_UP_BE;
1457 }
1458 hddWmmDscpToUpMap[8] = SME_QOS_WMM_UP_BK;
1459 hddWmmDscpToUpMap[16] = SME_QOS_WMM_UP_RESV;
1460 hddWmmDscpToUpMap[24] = SME_QOS_WMM_UP_EE;
1461 hddWmmDscpToUpMap[32] = SME_QOS_WMM_UP_CL;
1462 hddWmmDscpToUpMap[40] = SME_QOS_WMM_UP_VI;
1463 hddWmmDscpToUpMap[48] = SME_QOS_WMM_UP_VO;
1464 hddWmmDscpToUpMap[56] = SME_QOS_WMM_UP_NC;
1465
1466 return VOS_STATUS_SUCCESS;
1467}
1468
1469/**============================================================================
1470 @brief hdd_wmm_adapter_init() - Function which will initialize the WMM configuation
1471 and status to an initial state. The configuration can later be overwritten
1472 via application APIs
1473
1474 @param pAdapter : [in] pointer to Adapter context
1475
1476 @return : VOS_STATUS_SUCCESS if succssful
1477 : other values if failure
1478
1479 ===========================================================================*/
1480VOS_STATUS hdd_wmm_adapter_init( hdd_adapter_t *pAdapter )
1481{
1482 hdd_wmm_ac_status_t *pAcStatus;
1483 WLANTL_ACEnumType acType;
1484
1485 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1486 "%s: Entered", __FUNCTION__);
1487
1488 pAdapter->hddWmmStatus.wmmQap = VOS_FALSE;
1489 INIT_LIST_HEAD(&pAdapter->hddWmmStatus.wmmContextList);
1490 mutex_init(&pAdapter->hddWmmStatus.wmmLock);
1491
1492 for (acType = 0; acType < WLANTL_MAX_AC; acType++)
1493 {
1494 pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
1495 pAcStatus->wmmAcAccessRequired = VOS_FALSE;
1496 pAcStatus->wmmAcAccessNeeded = VOS_FALSE;
1497 pAcStatus->wmmAcAccessPending = VOS_FALSE;
1498 pAcStatus->wmmAcAccessFailed = VOS_FALSE;
1499 pAcStatus->wmmAcAccessGranted = VOS_FALSE;
1500 pAcStatus->wmmAcAccessAllowed = VOS_FALSE;
1501 pAcStatus->wmmAcTspecValid = VOS_FALSE;
1502 pAcStatus->wmmAcUapsdInfoValid = VOS_FALSE;
1503 }
1504
1505 return VOS_STATUS_SUCCESS;
1506}
1507/**============================================================================
1508 @brief hdd_wmm_close() - Function which will perform any necessary work to
1509 to clean up the WMM functionality prior to the kernel module unload
1510
1511 @param pAdapter : [in] pointer to adapter context
1512
1513 @return : VOS_STATUS_SUCCESS if succssful
1514 : other values if failure
1515
1516 ===========================================================================*/
1517VOS_STATUS hdd_wmm_adapter_close ( hdd_adapter_t* pAdapter )
1518{
1519 hdd_wmm_qos_context_t* pQosContext;
1520
1521 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1522 "%s: Entered", __FUNCTION__);
1523
1524 // free any context records that we still have linked
1525 while (!list_empty(&pAdapter->hddWmmStatus.wmmContextList))
1526 {
1527 pQosContext = list_first_entry(&pAdapter->hddWmmStatus.wmmContextList,
1528 hdd_wmm_qos_context_t, node);
1529#ifdef FEATURE_WLAN_CCX
1530 hdd_wmm_disable_inactivity_timer(pQosContext);
1531#endif
1532 hdd_wmm_free_context(pQosContext);
1533 }
1534
1535 return VOS_STATUS_SUCCESS;
1536}
1537
1538/**============================================================================
1539 @brief hdd_wmm_classify_pkt() - Function which will classify an OS packet
1540 into a WMM AC based on either 802.1Q or DSCP
1541
1542 @param pAdapter : [in] pointer to adapter context
1543 @param skb : [in] pointer to OS packet (sk_buff)
1544 @param pAcType : [out] pointer to WMM AC type of OS packet
1545
1546 @return : None
1547 ===========================================================================*/
1548v_VOID_t hdd_wmm_classify_pkt ( hdd_adapter_t* pAdapter,
1549 struct sk_buff *skb,
1550 WLANTL_ACEnumType* pAcType,
1551 sme_QosWmmUpType *pUserPri)
1552{
1553 unsigned char * pPkt;
1554 union generic_ethhdr *pHdr;
1555 struct iphdr *pIpHdr;
1556 unsigned char tos;
1557 unsigned char dscp;
1558 sme_QosWmmUpType userPri;
1559 WLANTL_ACEnumType acType;
1560
1561 // this code is executed for every packet therefore
1562 // all debug code is kept conditional
1563
1564#ifdef HDD_WMM_DEBUG
1565 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1566 "%s: Entered", __FUNCTION__);
1567#endif // HDD_WMM_DEBUG
1568
1569 pPkt = skb->data;
1570 pHdr = (union generic_ethhdr *)pPkt;
1571
1572#ifdef HDD_WMM_DEBUG
1573 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1574 "%s: proto/length is 0x%04x",
1575 __FUNCTION__, pHdr->eth_II.h_proto);
1576#endif // HDD_WMM_DEBUG
1577
1578 if (HDD_WMM_CLASSIFICATION_DSCP == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis)
1579 {
1580 if (pHdr->eth_II.h_proto == htons(ETH_P_IP))
1581 {
1582 // case 1: Ethernet II IP packet
1583 pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_II)];
1584 tos = pIpHdr->tos;
1585#ifdef HDD_WMM_DEBUG
1586 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1587 "%s: Ethernet II IP Packet, tos is %d",
1588 __FUNCTION__, tos);
1589#endif // HDD_WMM_DEBUG
1590
1591 }
1592 else if ((ntohs(pHdr->eth_II.h_proto) < WLAN_MIN_PROTO) &&
1593 (pHdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) &&
1594 (pHdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) &&
1595 (pHdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) &&
1596 (pHdr->eth_8023.h_proto == htons(ETH_P_IP)))
1597 {
1598 // case 2: 802.3 LLC/SNAP IP packet
1599 pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023)];
1600 tos = pIpHdr->tos;
1601#ifdef HDD_WMM_DEBUG
1602 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1603 "%s: 802.3 LLC/SNAP IP Packet, tos is %d",
1604 __FUNCTION__, tos);
1605#endif // HDD_WMM_DEBUG
1606 }
1607 else if (pHdr->eth_II.h_proto == htons(ETH_P_8021Q))
1608 {
1609 // VLAN tagged
1610
1611 if (pHdr->eth_IIv.h_vlan_encapsulated_proto == htons(ETH_P_IP))
1612 {
1613 // case 3: Ethernet II vlan-tagged IP packet
1614 pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_IIv)];
1615 tos = pIpHdr->tos;
1616#ifdef HDD_WMM_DEBUG
1617 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1618 "%s: Ethernet II VLAN tagged IP Packet, tos is %d",
1619 __FUNCTION__, tos);
1620#endif // HDD_WMM_DEBUG
1621 }
1622 else if ((ntohs(pHdr->eth_IIv.h_vlan_encapsulated_proto) < WLAN_MIN_PROTO) &&
1623 (pHdr->eth_8023v.h_snap.dsap == WLAN_SNAP_DSAP) &&
1624 (pHdr->eth_8023v.h_snap.ssap == WLAN_SNAP_SSAP) &&
1625 (pHdr->eth_8023v.h_snap.ctrl == WLAN_SNAP_CTRL) &&
1626 (pHdr->eth_8023v.h_proto == htons(ETH_P_IP)))
1627 {
1628 // case 4: 802.3 LLC/SNAP vlan-tagged IP packet
1629 pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023v)];
1630 tos = pIpHdr->tos;
1631#ifdef HDD_WMM_DEBUG
1632 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1633 "%s: 802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d",
1634 __FUNCTION__, tos);
1635#endif // HDD_WMM_DEBUG
1636 }
1637 else
1638 {
1639 // default
1640#ifdef HDD_WMM_DEBUG
1641 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
1642 "%s: VLAN tagged Unhandled Protocol, using default tos",
1643 __FUNCTION__);
1644#endif // HDD_WMM_DEBUG
1645 tos = 0;
1646 }
1647 }
1648 else
1649 {
1650 // default
1651#ifdef HDD_WMM_DEBUG
1652 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
1653 "%s: Unhandled Protocol, using default tos",
1654 __FUNCTION__);
1655#endif // HDD_WMM_DEBUG
1656 //Give the highest priority to 802.1x packet
1657 if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X))
1658 tos = 0xC0;
1659 else
1660 tos = 0;
1661 }
1662
1663 dscp = (tos>>2) & 0x3f;
1664 userPri = hddWmmDscpToUpMap[dscp];
1665
1666#ifdef HDD_WMM_DEBUG
1667 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1668 "%s: tos is %d, dscp is %d, up is %d",
1669 __FUNCTION__, tos, dscp, userPri);
1670#endif // HDD_WMM_DEBUG
1671
1672 }
1673 else if (HDD_WMM_CLASSIFICATION_802_1Q == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis)
1674 {
1675 if (pHdr->eth_IIv.h_vlan_proto == htons(ETH_P_8021Q))
1676 {
1677 // VLAN tagged
1678 userPri = (ntohs(pHdr->eth_IIv.h_vlan_TCI)>>13) & 0x7;
1679#ifdef HDD_WMM_DEBUG
1680 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1681 "%s: Tagged frame, UP is %d",
1682 __FUNCTION__, userPri);
1683#endif // HDD_WMM_DEBUG
1684 }
1685 else
1686 {
1687 // not VLAN tagged, use default
1688#ifdef HDD_WMM_DEBUG
1689 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
1690 "%s: Untagged frame, using default UP",
1691 __FUNCTION__);
1692#endif // HDD_WMM_DEBUG
1693 //Give the highest priority to 802.1x packet
1694 if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X))
1695 userPri = SME_QOS_WMM_UP_VO;
1696 else
1697 userPri = SME_QOS_WMM_UP_BE;
1698 }
1699 }
1700 else
1701 {
1702 // default
1703#ifdef HDD_WMM_DEBUG
1704 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1705 "%s: Unknown classification scheme, using default UP",
1706 __FUNCTION__);
1707#endif // HDD_WMM_DEBUG
1708 userPri = SME_QOS_WMM_UP_BE;
1709 }
1710
1711 acType = hddWmmUpToAcMap[userPri];
1712
1713#ifdef HDD_WMM_DEBUG
1714 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1715 "%s: UP is %d, AC is %d",
1716 __FUNCTION__, userPri, acType);
1717#endif // HDD_WMM_DEBUG
1718
1719 *pUserPri = userPri;
1720 *pAcType = acType;
1721
1722 return;
1723}
1724
1725/**============================================================================
1726 @brief hdd_hostapd_select_quueue() - Function which will classify the packet
1727 according to linux qdisc expectation.
1728
1729
1730 @param dev : [in] pointer to net_device structure
1731 @param skb : [in] pointer to os packet
1732
1733 @return : Qdisc queue index
1734 ===========================================================================*/
1735v_U16_t hdd_hostapd_select_queue(struct net_device * dev, struct sk_buff *skb)
1736{
1737 WLANTL_ACEnumType ac;
1738 sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
1739 v_USHORT_t queueIndex;
1740 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
1741 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
1742 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1743#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1744 tpAniSirGlobal pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_HAL, pHddCtx->pvosContext);
1745#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
1746 v_U8_t STAId;
1747 v_U8_t *pSTAId = (v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
1748
1749 /*Get the Station ID*/
1750#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1751 if (eHAL_STATUS_SUCCESS != halTable_FindStaidByAddr(pMac, (tANI_U8 *)pDestMacAddress, &STAId))
1752 {
1753 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1754 "%s: Failed to find right station", __FUNCTION__);
1755 *pSTAId = HDD_WLAN_INVALID_STA_ID;
1756 goto done;
1757 }
1758#else
1759 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &STAId))
1760 {
1761 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1762 "%s: Failed to find right station", __FUNCTION__);
1763 *pSTAId = HDD_WLAN_INVALID_STA_ID;
1764 goto done;
1765 }
1766#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
1767
1768 spin_lock_bh( &pAdapter->staInfo_lock );
1769 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[STAId].macAddrSTA, pDestMacAddress))
1770 {
1771 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1772 "%s: Station MAC address does not matching", __FUNCTION__);
1773
1774 *pSTAId = HDD_WLAN_INVALID_STA_ID;
1775 goto release_lock;
1776 }
1777 if (pAdapter->aStaInfo[STAId].isUsed && pAdapter->aStaInfo[STAId].isQosEnabled && (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->cfg_ini->WmmMode))
1778 {
1779 /* Get the user priority from IP header & corresponding AC */
1780 hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
1781 }
1782 *pSTAId = STAId;
1783
1784release_lock:
1785 spin_unlock_bh( &pAdapter->staInfo_lock );
1786done:
1787 skb->priority = up;
1788 queueIndex = hddLinuxUpToAcMap[skb->priority];
1789
1790 return queueIndex;
1791}
1792
1793/**============================================================================
1794 @brief hdd_wmm_select_quueue() - Function which will classify the packet
1795 according to linux qdisc expectation.
1796
1797
1798 @param dev : [in] pointer to net_device structure
1799 @param skb : [in] pointer to os packet
1800
1801 @return : Qdisc queue index
1802 ===========================================================================*/
1803v_U16_t hdd_wmm_select_queue(struct net_device * dev, struct sk_buff *skb)
1804{
1805 WLANTL_ACEnumType ac;
1806 sme_QosWmmUpType up = 0;
1807 v_USHORT_t queueIndex;
1808
1809 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1810
1811 // if we don't want QoS or the AP doesn't support Qos
1812 // All traffic will get equal opportuniy to transmit data frames.
1813 if( hdd_wmm_is_active(pAdapter) ) {
1814 /* Get the user priority from IP header & corresponding AC */
1815 hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
1816 }
1817
1818 skb->priority = up;
1819 queueIndex = hddLinuxUpToAcMap[skb->priority];
1820
1821 return queueIndex;
1822}
1823
1824/**============================================================================
1825 @brief hdd_wmm_acquire_access() - Function which will attempt to acquire
1826 admittance for a WMM AC
1827
1828 @param pAdapter : [in] pointer to adapter context
1829 @param acType : [in] WMM AC type of OS packet
1830 @param pGranted : [out] pointer to boolean flag when indicates if access
1831 has been granted or not
1832
1833 @return : VOS_STATUS_SUCCESS if succssful
1834 : other values if failure
1835 ===========================================================================*/
1836VOS_STATUS hdd_wmm_acquire_access( hdd_adapter_t* pAdapter,
1837 WLANTL_ACEnumType acType,
1838 v_BOOL_t * pGranted )
1839{
1840 hdd_wmm_qos_context_t *pQosContext;
1841
1842 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1843 "%s: Entered for AC %d", __FUNCTION__, acType);
1844
1845 if (!hdd_wmm_is_active(pAdapter) || !(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->bImplicitQosEnabled)
1846 {
1847 // either we don't want QoS or the AP doesn't support QoS
1848 // or we don't want to do implicit QoS
1849 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1850 "%s: QoS not configured on both ends ", __FUNCTION__);
1851
1852 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
1853 *pGranted = VOS_TRUE;
1854 return VOS_STATUS_SUCCESS;
1855 }
1856
1857 // do we already have an implicit QoS request pending for this AC?
1858 if ((pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded) ||
1859 (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessPending))
1860 {
1861 // request already pending so we need to wait for that response
1862 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1863 "%s: Implicit QoS for TL AC %d already scheduled",
1864 __FUNCTION__, acType);
1865
1866 *pGranted = VOS_FALSE;
1867 return VOS_STATUS_SUCCESS;
1868 }
1869
1870 // did we already fail to establish implicit QoS for this AC?
1871 // (if so, access should have been granted when the failure was handled)
1872 if (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessFailed)
1873 {
1874 // request previously failed
1875 // allow access, but we'll be downgraded
1876 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1877 "%s: Implicit QoS for TL AC %d previously failed",
1878 __FUNCTION__, acType);
1879
1880 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
1881 *pGranted = VOS_TRUE;
1882 return VOS_STATUS_SUCCESS;
1883 }
1884
1885 // we need to establish implicit QoS
1886 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1887 "%s: Need to schedule implicit QoS for TL AC %d, pAdapter is %p",
1888 __FUNCTION__, acType, pAdapter);
1889
1890 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded = VOS_TRUE;
1891
1892 pQosContext = kmalloc(sizeof(*pQosContext), GFP_KERNEL);
1893 if (NULL == pQosContext)
1894 {
1895 // no memory for QoS context. Nothing we can do but let data flow
1896 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
1897 "%s: Unable to allocate context", __FUNCTION__);
1898 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
1899 *pGranted = VOS_TRUE;
1900 return VOS_STATUS_SUCCESS;
1901 }
1902
1903 pQosContext->acType = acType;
1904 pQosContext->pAdapter = pAdapter;
1905 pQosContext->qosFlowId = 0;
1906 pQosContext->handle = HDD_WMM_HANDLE_IMPLICIT;
1907 pQosContext->magic = HDD_WMM_CTX_MAGIC;
1908 INIT_WORK(&pQosContext->wmmAcSetupImplicitQos,
1909 hdd_wmm_do_implicit_qos);
1910
1911 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
1912 "%s: Scheduling work for AC %d, context %p",
1913 __FUNCTION__, acType, pQosContext);
1914
1915 schedule_work(&pQosContext->wmmAcSetupImplicitQos);
1916
1917 // caller will need to wait until the work takes place and
1918 // TSPEC negotiation completes
1919 *pGranted = VOS_FALSE;
1920 return VOS_STATUS_SUCCESS;
1921}
1922
1923/**============================================================================
1924 @brief hdd_wmm_assoc() - Function which will handle the housekeeping
1925 required by WMM when association takes place
1926
1927 @param pAdapter : [in] pointer to adapter context
1928 @param pRoamInfo: [in] pointer to roam information
1929 @param eBssType : [in] type of BSS
1930
1931 @return : VOS_STATUS_SUCCESS if succssful
1932 : other values if failure
1933 ===========================================================================*/
1934VOS_STATUS hdd_wmm_assoc( hdd_adapter_t* pAdapter,
1935 tCsrRoamInfo *pRoamInfo,
1936 eCsrRoamBssType eBssType )
1937{
1938 tANI_U8 uapsdMask;
1939 VOS_STATUS status;
1940
1941 // when we associate we need to notify TL if it needs to enable
1942 // UAPSD for any access categories
1943
1944 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1945 "%s: Entered", __FUNCTION__);
1946
1947 if (pRoamInfo->fReassocReq)
1948 {
1949 // when we reassociate we should continue to use whatever
1950 // parameters were previously established. if we are
1951 // reassociating due to a U-APSD change for a particular
1952 // Access Category, then the change will be communicated
1953 // to HDD via the QoS callback associated with the given
1954 // flow, and U-APSD parameters will be updated there
1955
1956 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1957 "%s: Reassoc so no work, Exiting", __FUNCTION__);
1958
1959 return VOS_STATUS_SUCCESS;
1960 }
1961
1962 // get the negotiated UAPSD Mask
1963 uapsdMask = pRoamInfo->u.pConnectedProfile->modifyProfileFields.uapsd_mask;
1964
1965 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
1966 "%s: U-APSD mask is 0x%02x", __FUNCTION__, (int) uapsdMask);
1967
1968 if (uapsdMask & HDD_AC_VO)
1969 {
1970 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1971 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
1972 WLANTL_AC_VO,
1973 7,
1974 7,
1975 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv,
1976 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv,
1977 WLANTL_BI_DIR );
1978
1979 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
1980 }
1981
1982 if (uapsdMask & HDD_AC_VI)
1983 {
1984 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1985 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
1986 WLANTL_AC_VI,
1987 5,
1988 5,
1989 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv,
1990 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv,
1991 WLANTL_BI_DIR );
1992
1993 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
1994 }
1995
1996 if (uapsdMask & HDD_AC_BK)
1997 {
1998 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1999 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
2000 WLANTL_AC_BK,
2001 2,
2002 2,
2003 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv,
2004 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv,
2005 WLANTL_BI_DIR );
2006
2007 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
2008 }
2009
2010 if (uapsdMask & HDD_AC_BE)
2011 {
2012 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
2013 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
2014 WLANTL_AC_BE,
2015 3,
2016 3,
2017 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv,
2018 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv,
2019 WLANTL_BI_DIR );
2020
2021 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
2022 }
2023
2024 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2025 "%s: Exiting", __FUNCTION__);
2026
2027 return VOS_STATUS_SUCCESS;
2028}
2029
2030
2031
2032static const v_U8_t acmMaskBit[WLANTL_MAX_AC] =
2033 {
2034 0x4, /* WLANTL_AC_BK */
2035 0x8, /* WLANTL_AC_BE */
2036 0x2, /* WLANTL_AC_VI */
2037 0x1 /* WLANTL_AC_VO */
2038 };
2039
2040/**============================================================================
2041 @brief hdd_wmm_connect() - Function which will handle the housekeeping
2042 required by WMM when a connection is established
2043
2044 @param pAdapter : [in] pointer to adapter context
2045 @param pRoamInfo: [in] pointer to roam information
2046 @param eBssType : [in] type of BSS
2047
2048 @return : VOS_STATUS_SUCCESS if succssful
2049 : other values if failure
2050 ===========================================================================*/
2051VOS_STATUS hdd_wmm_connect( hdd_adapter_t* pAdapter,
2052 tCsrRoamInfo *pRoamInfo,
2053 eCsrRoamBssType eBssType )
2054{
2055 int ac;
2056 v_BOOL_t qap;
2057 v_BOOL_t qosConnection;
2058 v_U8_t acmMask;
2059
2060 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2061 "%s: Entered", __FUNCTION__);
2062
2063 if ((eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType) &&
2064 pRoamInfo &&
2065 pRoamInfo->u.pConnectedProfile)
2066 {
2067 qap = pRoamInfo->u.pConnectedProfile->qap;
2068 qosConnection = pRoamInfo->u.pConnectedProfile->qosConnection;
2069 acmMask = pRoamInfo->u.pConnectedProfile->acm_mask;
2070 }
2071 else
2072 {
2073 qap = VOS_TRUE;
2074 qosConnection = VOS_TRUE;
2075 acmMask = 0x0;
2076 }
2077
2078 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2079 "%s: qap is %d, qosConnection is %d, acmMask is 0x%x",
2080 __FUNCTION__, qap, qosConnection, acmMask);
2081
2082 pAdapter->hddWmmStatus.wmmQap = qap;
2083 pAdapter->hddWmmStatus.wmmQosConnection = qosConnection;
2084
2085 for (ac = 0; ac < WLANTL_MAX_AC; ac++)
2086 {
2087 if (qap &&
2088 qosConnection &&
2089 (acmMask & acmMaskBit[ac]))
2090 {
2091 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2092 "%s: ac %d on",
2093 __FUNCTION__, ac);
2094
2095 // admission is required
2096 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_TRUE;
2097 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_FALSE;
2098 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessGranted = VOS_FALSE;
2099 }
2100 else
2101 {
2102 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2103 "%s: ac %d off",
2104 __FUNCTION__, ac);
2105 // admission is not required so access is allowed
2106 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_FALSE;
2107 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_TRUE;
2108 }
2109
2110 }
2111
2112 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2113 "%s: Exiting", __FUNCTION__);
2114
2115 return VOS_STATUS_SUCCESS;
2116}
2117
2118/**============================================================================
2119 @brief hdd_wmm_get_uapsd_mask() - Function which will calculate the
2120 initial value of the UAPSD mask based upon the device configuration
2121
2122 @param pAdapter : [in] pointer to adapter context
2123 @param pUapsdMask: [in] pointer to where the UAPSD Mask is to be stored
2124
2125 @return : VOS_STATUS_SUCCESS if succssful
2126 : other values if failure
2127 ===========================================================================*/
2128VOS_STATUS hdd_wmm_get_uapsd_mask( hdd_adapter_t* pAdapter,
2129 tANI_U8 *pUapsdMask )
2130{
2131 tANI_U8 uapsdMask;
2132
2133 if (HDD_WMM_USER_MODE_NO_QOS == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
2134 {
2135 // no QOS then no UAPSD
2136 uapsdMask = 0;
2137 }
2138 else
2139 {
2140 // start with the default mask
2141 uapsdMask = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
2142
2143 // disable UAPSD for any ACs with a 0 Service Interval
2144 if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv == 0 )
2145 {
2146 uapsdMask &= ~HDD_AC_VO;
2147 }
2148
2149 if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv == 0 )
2150 {
2151 uapsdMask &= ~HDD_AC_VI;
2152 }
2153
2154 if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv == 0 )
2155 {
2156 uapsdMask &= ~HDD_AC_BK;
2157 }
2158
2159 if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv == 0 )
2160 {
2161 uapsdMask &= ~HDD_AC_BE;
2162 }
2163 }
2164
2165 // return calculated mask
2166 *pUapsdMask = uapsdMask;
2167 return VOS_STATUS_SUCCESS;
2168}
2169
2170
2171/**============================================================================
2172 @brief hdd_wmm_is_active() - Function which will determine if WMM is
2173 active on the current connection
2174
2175 @param pAdapter : [in] pointer to adapter context
2176
2177 @return : VOS_TRUE if WMM is enabled
2178 : VOS_FALSE if WMM is not enabled
2179 ===========================================================================*/
2180v_BOOL_t hdd_wmm_is_active( hdd_adapter_t* pAdapter )
2181{
2182 if ((!pAdapter->hddWmmStatus.wmmQosConnection) ||
2183 (!pAdapter->hddWmmStatus.wmmQap))
2184 {
2185 return VOS_FALSE;
2186 }
2187 else
2188 {
2189 return VOS_TRUE;
2190 }
2191}
2192
2193/**============================================================================
2194 @brief hdd_wmm_addts() - Function which will add a traffic spec at the
2195 request of an application
2196
2197 @param pAdapter : [in] pointer to adapter context
2198 @param handle : [in] handle to uniquely identify a TS
2199 @param pTspec : [in] pointer to the traffic spec
2200
2201 @return : HDD_WLAN_WMM_STATUS_*
2202 ===========================================================================*/
2203hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter,
2204 v_U32_t handle,
2205 sme_QosWmmTspecInfo* pTspec )
2206{
2207 hdd_wmm_qos_context_t *pQosContext;
2208 hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ;
2209#ifndef WLAN_MDM_CODE_REDUCTION_OPT
2210 sme_QosStatusType smeStatus;
2211#endif
2212 v_BOOL_t found = VOS_FALSE;
2213
2214 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2215 "%s: Entered with handle 0x%x", __FUNCTION__, handle);
2216
2217 // see if a context already exists with the given handle
2218 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2219 list_for_each_entry(pQosContext,
2220 &pAdapter->hddWmmStatus.wmmContextList,
2221 node)
2222 {
2223 if (pQosContext->handle == handle)
2224 {
2225 found = VOS_TRUE;
2226 break;
2227 }
2228 }
2229 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2230 if (found)
2231 {
2232 // record with that handle already exists
2233 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
2234 "%s: Record already exists with handle 0x%x",
2235 __FUNCTION__, handle);
2236
2237 /* Application is trying to modify some of the Tspec params. Allow it */
2238 smeStatus = sme_QosModifyReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
2239 pTspec,
2240 pQosContext->qosFlowId);
2241
2242 // need to check the return value and act appropriately
2243 switch (smeStatus)
2244 {
2245 case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
2246 status = HDD_WLAN_WMM_STATUS_MODIFY_PENDING;
2247 break;
2248 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
2249 status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
2250 break;
2251 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
2252 status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
2253 break;
2254 case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
2255 status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
2256 break;
2257 case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
2258 status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
2259 break;
2260 case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
2261 status = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
2262 break;
2263 default:
2264 // we didn't get back one of the SME_QOS_STATUS_MODIFY_* status codes
2265 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
2266 "%s: unexpected SME Status=%d\n", smeStatus );
2267 VOS_ASSERT(0);
2268 return HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
2269 }
2270
2271 // we were successful, save the status
2272 pQosContext->lastStatus = status;
2273 return status;
2274 }
2275
2276 pQosContext = kmalloc(sizeof(*pQosContext), GFP_KERNEL);
2277 if (NULL == pQosContext)
2278 {
2279 // no memory for QoS context. Nothing we can do
2280 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
2281 "%s: Unable to allocate QoS context", __FUNCTION__);
2282 return HDD_WLAN_WMM_STATUS_INTERNAL_FAILURE;
2283 }
2284
2285 // we assume the tspec has already been validated by the caller
2286
2287 pQosContext->handle = handle;
2288 pQosContext->acType = hddWmmUpToAcMap[pTspec->ts_info.up];
2289 pQosContext->pAdapter = pAdapter;
2290 pQosContext->qosFlowId = 0;
2291 pQosContext->magic = HDD_WMM_CTX_MAGIC;
2292
2293 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
2294 "%s: Setting up QoS, context %p",
2295 __FUNCTION__, pQosContext);
2296
2297 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2298 list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
2299 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2300
2301#ifndef WLAN_MDM_CODE_REDUCTION_OPT
2302 smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
2303 pAdapter->sessionId,
2304 pTspec,
2305 hdd_wmm_sme_callback,
2306 pQosContext,
2307 pTspec->ts_info.up,
2308 &pQosContext->qosFlowId);
2309
2310 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
2311 "%s: sme_QosSetupReq returned %d flowid %d",
2312 __FUNCTION__, smeStatus, pQosContext->qosFlowId);
2313
2314 // need to check the return value and act appropriately
2315 switch (smeStatus)
2316 {
2317 case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
2318 status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
2319 break;
2320 case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
2321 status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
2322 break;
2323 case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
2324 status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
2325 break;
2326 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
2327 status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
2328 break;
2329 case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
2330 hdd_wmm_free_context(pQosContext);
2331 return HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
2332 case SME_QOS_STATUS_SETUP_FAILURE_RSP:
2333 // we can't tell the difference between when a request fails because
2334 // AP rejected it versus when SME encounterd an internal error
2335 hdd_wmm_free_context(pQosContext);
2336 return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
2337 case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
2338 hdd_wmm_free_context(pQosContext);
2339 return HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
2340 default:
2341 // we didn't get back one of the SME_QOS_STATUS_SETUP_* status codes
2342 hdd_wmm_free_context(pQosContext);
2343 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
2344 "%s: unexpected SME Status=%d\n", smeStatus );
2345 VOS_ASSERT(0);
2346 return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
2347 }
2348#endif
2349
2350 // we were successful, save the status
2351 pQosContext->lastStatus = status;
2352
2353 return status;
2354}
2355
2356/**============================================================================
2357 @brief hdd_wmm_delts() - Function which will delete a traffic spec at the
2358 request of an application
2359
2360 @param pAdapter : [in] pointer to adapter context
2361 @param handle : [in] handle to uniquely identify a TS
2362
2363 @return : HDD_WLAN_WMM_STATUS_*
2364 ===========================================================================*/
2365hdd_wlan_wmm_status_e hdd_wmm_delts( hdd_adapter_t* pAdapter,
2366 v_U32_t handle )
2367{
2368 hdd_wmm_qos_context_t *pQosContext;
2369 v_BOOL_t found = VOS_FALSE;
2370 WLANTL_ACEnumType acType = 0;
2371 v_U32_t qosFlowId = 0;
2372 hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ;
2373#ifndef WLAN_MDM_CODE_REDUCTION_OPT
2374 sme_QosStatusType smeStatus;
2375#endif
2376
2377 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2378 "%s: Entered with handle 0x%x", __FUNCTION__, handle);
2379
2380 // locate the context with the given handle
2381 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2382 list_for_each_entry(pQosContext,
2383 &pAdapter->hddWmmStatus.wmmContextList,
2384 node)
2385 {
2386 if (pQosContext->handle == handle)
2387 {
2388 found = VOS_TRUE;
2389 acType = pQosContext->acType;
2390 qosFlowId = pQosContext->qosFlowId;
2391 break;
2392 }
2393 }
2394 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2395
2396 if (VOS_FALSE == found)
2397 {
2398 // we didn't find the handle
2399 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2400 "%s: handle 0x%x not found", __FUNCTION__, handle);
2401 return HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
2402 }
2403
2404
2405 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2406 "%s: found handle 0x%x, flow %d, AC %d, context %p",
2407 __FUNCTION__, handle, qosFlowId, acType, pQosContext);
2408
2409#ifndef WLAN_MDM_CODE_REDUCTION_OPT
2410 smeStatus = sme_QosReleaseReq( WLAN_HDD_GET_HAL_CTX(pAdapter), qosFlowId );
2411
2412 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2413 "%s: SME flow %d released, SME status %d",
2414 __FUNCTION__, qosFlowId, smeStatus);
2415
2416 switch(smeStatus)
2417 {
2418 case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
2419 // this flow is the only one on that AC, so go ahead and update
2420 // our TSPEC state for the AC
2421 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcTspecValid = VOS_FALSE;
2422
2423 // need to tell TL to stop trigger timer, etc
2424 hdd_wmm_disable_tl_uapsd(pQosContext);
2425
2426#ifdef FEATURE_WLAN_CCX
2427 // disable the inactivity timer
2428 hdd_wmm_disable_inactivity_timer(pQosContext);
2429#endif
2430 // we are done with this context
2431 hdd_wmm_free_context(pQosContext);
2432
2433 // SME must not fire any more callbacks for this flow since the context
2434 // is no longer valid
2435
2436 return HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
2437
2438 case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
2439 // do nothing as we will get a response from SME
2440 status = HDD_WLAN_WMM_STATUS_RELEASE_PENDING;
2441 break;
2442
2443 case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
2444 // nothing we can do with the existing flow except leave it
2445 status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
2446 break;
2447
2448 case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
2449 // nothing we can do with the existing flow except leave it
2450 status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
2451
2452 default:
2453 // we didn't get back one of the SME_QOS_STATUS_RELEASE_* status codes
2454 VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
2455 "%s: unexpected SME Status=%d\n", smeStatus );
2456 VOS_ASSERT(0);
2457 status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
2458 }
2459
2460#endif
2461 pQosContext->lastStatus = status;
2462 return status;
2463}
2464
2465/**============================================================================
2466 @brief hdd_wmm_checkts() - Function which will return the status of a traffic
2467 spec at the request of an application
2468
2469 @param pAdapter : [in] pointer to adapter context
2470 @param handle : [in] handle to uniquely identify a TS
2471
2472 @return : HDD_WLAN_WMM_STATUS_*
2473 ===========================================================================*/
2474hdd_wlan_wmm_status_e hdd_wmm_checkts( hdd_adapter_t* pAdapter,
2475 v_U32_t handle )
2476{
2477 hdd_wmm_qos_context_t *pQosContext;
2478 hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_LOST;
2479
2480 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2481 "%s: Entered with handle 0x%x", __FUNCTION__, handle);
2482
2483 // locate the context with the given handle
2484 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2485 list_for_each_entry(pQosContext,
2486 &pAdapter->hddWmmStatus.wmmContextList,
2487 node)
2488 {
2489 if (pQosContext->handle == handle)
2490 {
2491 VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
2492 "%s: found handle 0x%x, context %p",
2493 __FUNCTION__, handle, pQosContext);
2494
2495 status = pQosContext->lastStatus;
2496 break;
2497 }
2498 }
2499 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2500 return status;
2501}