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