blob: a6627bcbe13730d5da96901319d0a0f86d533e8f [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnson1677bbb2017-01-12 08:39:19 -08002 * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: HDD WMM
30 *
31 * This module (wlan_hdd_wmm.h interface + wlan_hdd_wmm.c implementation)
32 * houses all the logic for WMM in HDD.
33 *
34 * On the control path, it has the logic to setup QoS, modify QoS and delete
35 * QoS (QoS here refers to a TSPEC). The setup QoS comes in two flavors: an
36 * explicit application invoked and an internal HDD invoked. The implicit QoS
37 * is for applications that do NOT call the custom QCT WLAN OIDs for QoS but
38 * which DO mark their traffic for priortization. It also has logic to start,
39 * update and stop the U-APSD trigger frame generation. It also has logic to
40 * read WMM related config parameters from the registry.
41 *
42 * On the data path, it has the logic to figure out the WMM AC of an egress
43 * packet and when to signal TL to serve a particular AC queue. It also has the
44 * logic to retrieve a packet based on WMM priority in response to a fetch from
45 * TL.
46 *
47 * The remaining functions are utility functions for information hiding.
48 */
49
50/* Include files */
51#include <linux/netdevice.h>
52#include <linux/skbuff.h>
53#include <linux/etherdevice.h>
54#include <linux/if_vlan.h>
55#include <linux/ip.h>
56#include <linux/semaphore.h>
Govind Singhb7ab5772015-10-08 16:38:37 +053057#include <linux/ipv6.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080058#include <wlan_hdd_tx_rx.h>
59#include <wlan_hdd_wmm.h>
60#include <wlan_hdd_ether.h>
61#include <wlan_hdd_hostapd.h>
62#include <wlan_hdd_softap_tx_rx.h>
63#include <cds_sched.h>
yeshwanth sriram guntukaa1ba9a22017-02-28 16:17:32 +053064#include "sme_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080066#define WLAN_HDD_MAX_DSCP 0x3f
67
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080068#define HDD_WMM_UP_TO_AC_MAP_SIZE 8
69
70const uint8_t hdd_wmm_up_to_ac_map[] = {
71 SME_AC_BE,
72 SME_AC_BK,
73 SME_AC_BK,
74 SME_AC_BE,
75 SME_AC_VI,
76 SME_AC_VI,
77 SME_AC_VO,
78 SME_AC_VO
79};
80
81/**
82 * enum hdd_wmm_linuxac: AC/Queue Index values for Linux Qdisc to
83 * operate on different traffic.
84 */
85#ifdef QCA_LL_TX_FLOW_CONTROL_V2
86enum hdd_wmm_linuxac {
87 HDD_LINUX_AC_VO = 0,
88 HDD_LINUX_AC_VI = 1,
89 HDD_LINUX_AC_BE = 2,
90 HDD_LINUX_AC_BK = 3,
91 HDD_LINUX_AC_HI_PRIO = 4,
92};
93
Jeff Johnson5b8b67d2017-08-29 14:16:53 -070094void wlan_hdd_process_peer_unauthorised_pause(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095{
96 /* Enable HI_PRIO queue */
97 netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VO);
98 netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VI);
99 netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BE);
100 netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BK);
101 netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO);
102
103}
104#else
105enum hdd_wmm_linuxac {
106 HDD_LINUX_AC_VO = 0,
107 HDD_LINUX_AC_VI = 1,
108 HDD_LINUX_AC_BE = 2,
109 HDD_LINUX_AC_BK = 3
110};
111
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700112void wlan_hdd_process_peer_unauthorised_pause(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114}
115#endif
116
117/* Linux based UP -> AC Mapping */
118const uint8_t hdd_linux_up_to_ac_map[HDD_WMM_UP_TO_AC_MAP_SIZE] = {
119 HDD_LINUX_AC_BE,
120 HDD_LINUX_AC_BK,
121 HDD_LINUX_AC_BK,
122 HDD_LINUX_AC_BE,
123 HDD_LINUX_AC_VI,
124 HDD_LINUX_AC_VI,
125 HDD_LINUX_AC_VO,
126 HDD_LINUX_AC_VO
127};
128
129#ifndef WLAN_MDM_CODE_REDUCTION_OPT
130/**
131 * hdd_wmm_enable_tl_uapsd() - function which decides whether and
132 * how to update UAPSD parameters in TL
133 *
134 * @pQosContext: [in] the pointer the QoS instance control block
135 *
136 * Return: None
137 */
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700138static void hdd_wmm_enable_tl_uapsd(struct hdd_wmm_qos_context *pQosContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139{
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700140 struct hdd_adapter *pAdapter = pQosContext->pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141 sme_ac_enum_type acType = pQosContext->acType;
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700142 struct hdd_wmm_ac_status *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
Jeff Johnson1083b6e2017-08-28 11:35:22 -0700143 struct hdd_context *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530144 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145 uint32_t service_interval;
146 uint32_t suspension_interval;
Abhishek Singh12be60f2017-08-11 13:52:42 +0530147 enum sme_qos_wmm_dir_type direction;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148 bool psb;
149
150 /* The TSPEC must be valid */
151 if (pAc->wmmAcTspecValid == false) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700152 hdd_err("Invoked with invalid TSPEC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153 return;
154 }
155 /* determine the service interval */
156 if (pAc->wmmAcTspecInfo.min_service_interval) {
157 service_interval = pAc->wmmAcTspecInfo.min_service_interval;
158 } else if (pAc->wmmAcTspecInfo.max_service_interval) {
159 service_interval = pAc->wmmAcTspecInfo.max_service_interval;
160 } else {
161 /* no service interval is present in the TSPEC */
162 /* this is OK, there just won't be U-APSD */
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700163 hdd_debug("No service interval supplied");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164 service_interval = 0;
165 }
166
167 /* determine the suspension interval & direction */
168 suspension_interval = pAc->wmmAcTspecInfo.suspension_interval;
169 direction = pAc->wmmAcTspecInfo.ts_info.direction;
170 psb = pAc->wmmAcTspecInfo.ts_info.psb;
171
172 /* if we have previously enabled U-APSD, have any params changed? */
173 if ((pAc->wmmAcUapsdInfoValid) &&
174 (pAc->wmmAcUapsdServiceInterval == service_interval) &&
175 (pAc->wmmAcUapsdSuspensionInterval == suspension_interval) &&
176 (pAc->wmmAcUapsdDirection == direction) &&
177 (pAc->wmmAcIsUapsdEnabled == psb)) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700178 hdd_debug("No change in U-APSD parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179 return;
180 }
181 /* everything is in place to notify TL */
182 status =
183 sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))->pcds_context,
184 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->
185 conn_info.staId[0], acType,
186 pAc->wmmAcTspecInfo.ts_info.tid,
187 pAc->wmmAcTspecInfo.ts_info.up,
188 service_interval, suspension_interval,
189 direction, psb, pAdapter->sessionId,
190 pHddCtx->config->DelayedTriggerFrmInt);
191
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530192 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700193 hdd_err("Failed to enable U-APSD for AC=%d", acType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194 return;
195 }
196 /* stash away the parameters that were used */
197 pAc->wmmAcUapsdInfoValid = true;
198 pAc->wmmAcUapsdServiceInterval = service_interval;
199 pAc->wmmAcUapsdSuspensionInterval = suspension_interval;
200 pAc->wmmAcUapsdDirection = direction;
201 pAc->wmmAcIsUapsdEnabled = psb;
202
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700203 hdd_debug("Enabled UAPSD in TL srv_int=%d susp_int=%d dir=%d AC=%d",
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700204 service_interval, suspension_interval, direction, acType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205
206}
207
208/**
209 * hdd_wmm_disable_tl_uapsd() - function which decides whether
210 * to disable UAPSD parameters in TL
211 *
212 * @pQosContext: [in] the pointer the QoS instance control block
213 *
214 * Return: None
215 */
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700216static void hdd_wmm_disable_tl_uapsd(struct hdd_wmm_qos_context *pQosContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217{
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700218 struct hdd_adapter *pAdapter = pQosContext->pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 sme_ac_enum_type acType = pQosContext->acType;
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700220 struct hdd_wmm_ac_status *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530221 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222
223 /* have we previously enabled UAPSD? */
224 if (pAc->wmmAcUapsdInfoValid == true) {
Sreelakshmi Konamkie1ce5622015-11-23 15:04:05 +0530225 status =
226 sme_disable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))->
227 pcds_context,
228 (WLAN_HDD_GET_STATION_CTX_PTR
229 (pAdapter))->conn_info.staId[0],
230 acType, pAdapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530232 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700233 hdd_err("Failed to disable U-APSD for AC=%d", acType);
Sreelakshmi Konamkie1ce5622015-11-23 15:04:05 +0530234 } else {
235 /* TL no longer has valid UAPSD info */
236 pAc->wmmAcUapsdInfoValid = false;
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700237 hdd_debug("Disabled UAPSD in TL for AC=%d", acType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800238 }
239 }
240}
241
242#endif
243
244/**
245 * hdd_wmm_free_context() - function which frees a QoS context
246 *
247 * @pQosContext: [in] the pointer the QoS instance control block
248 *
249 * Return: None
250 */
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700251static void hdd_wmm_free_context(struct hdd_wmm_qos_context *pQosContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252{
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700253 struct hdd_adapter *pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800254
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700255 hdd_debug("Entered, context %p", pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256
257 if (unlikely((NULL == pQosContext) ||
258 (HDD_WMM_CTX_MAGIC != pQosContext->magic))) {
259 /* must have been freed in another thread */
260 return;
261 }
262 /* get pointer to the adapter context */
263 pAdapter = pQosContext->pAdapter;
264
265 /* take the wmmLock since we're manipulating the context list */
266 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
267
268 /* make sure nobody thinks this is a valid context */
269 pQosContext->magic = 0;
270
271 /* unlink the context */
272 list_del(&pQosContext->node);
273
274 /* done manipulating the list */
275 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
276
277 /* reclaim memory */
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -0700278 qdf_mem_free(pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279
280}
281
282#ifndef WLAN_MDM_CODE_REDUCTION_OPT
283/**
284 * hdd_wmm_notify_app() - function which notifies an application
285 * of changes in state of it flow
286 *
287 * @pQosContext: [in] the pointer the QoS instance control block
288 *
289 * Return: None
290 */
291#define MAX_NOTIFY_LEN 50
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700292static void hdd_wmm_notify_app(struct hdd_wmm_qos_context *pQosContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293{
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700294 struct hdd_adapter *pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 union iwreq_data wrqu;
296 char buf[MAX_NOTIFY_LEN + 1];
297
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700298 hdd_debug("Entered, context %p", pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299
300 if (unlikely((NULL == pQosContext) ||
301 (HDD_WMM_CTX_MAGIC != pQosContext->magic))) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700302 hdd_err("Invalid QoS Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800303 return;
304 }
305
306 /* create the event */
307 memset(&wrqu, 0, sizeof(wrqu));
308 memset(buf, 0, sizeof(buf));
309
310 snprintf(buf, MAX_NOTIFY_LEN, "QCOM: TS change[%u: %u]",
311 (unsigned int)pQosContext->handle,
312 (unsigned int)pQosContext->lastStatus);
313
314 wrqu.data.pointer = buf;
315 wrqu.data.length = strlen(buf);
316
317 /* get pointer to the adapter */
318 pAdapter = pQosContext->pAdapter;
319
320 /* send the event */
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700321 hdd_debug("Sending [%s]", buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
323}
324
325#ifdef FEATURE_WLAN_ESE
326/**
327 * hdd_wmm_inactivity_timer_cb() - inactivity timer callback function
328 *
329 * @user_data: opaque user data registered with the timer. In the
330 * case of this timer, the associated wmm QoS context is registered.
331 *
332 * This timer handler function is called for every inactivity interval
333 * per AC. This function gets the current transmitted packets on the
334 * given AC, and checks if there was any TX activity from the previous
335 * interval. If there was no traffic then it would delete the TS that
336 * was negotiated on that AC.
337 *
338 * Return: None
339 */
340static void hdd_wmm_inactivity_timer_cb(void *user_data)
341{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700342 struct hdd_wmm_qos_context *pQosContext = user_data;
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700343 struct hdd_adapter *pAdapter;
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700344 struct hdd_wmm_ac_status *pAc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345 hdd_wlan_wmm_status_e status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530346 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800347 uint32_t currentTrafficCnt = 0;
348 sme_ac_enum_type acType = pQosContext->acType;
349
350 pAdapter = pQosContext->pAdapter;
c_hpothud5009242016-08-18 12:10:36 +0530351 if ((NULL == pAdapter) ||
352 (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
353 hdd_err("invalid pAdapter: %p", pAdapter);
354 return;
355 }
356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
358
359 /* Get the Tx stats for this AC. */
360 currentTrafficCnt =
361 pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->
362 acType];
363
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700364 hdd_warn("WMM inactivity Timer for AC=%d, currentCnt=%d, prevCnt=%d",
365 acType, (int)currentTrafficCnt, (int)pAc->wmmPrevTrafficCnt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366 if (pAc->wmmPrevTrafficCnt == currentTrafficCnt) {
367 /* there is no traffic activity, delete the TSPEC for this AC */
368 status = hdd_wmm_delts(pAdapter, pQosContext->handle);
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700369 hdd_warn("Deleted TS on AC %d, due to inactivity with status = %d!!!",
370 acType, status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 } else {
372 pAc->wmmPrevTrafficCnt = currentTrafficCnt;
Anurag Chouhan210db072016-02-22 18:42:15 +0530373 if (pAc->wmmInactivityTimer.state == QDF_TIMER_STATE_STOPPED) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374 /* Restart the timer */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530375 qdf_status =
Anurag Chouhan210db072016-02-22 18:42:15 +0530376 qdf_mc_timer_start(&pAc->wmmInactivityTimer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 pAc->wmmInactivityTime);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530378 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700379 hdd_err("Restarting inactivity timer failed on AC %d",
380 acType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800381 }
382 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530383 QDF_ASSERT(qdf_mc_timer_get_current_state
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 (&pAc->wmmInactivityTimer) ==
Anurag Chouhan210db072016-02-22 18:42:15 +0530385 QDF_TIMER_STATE_STOPPED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 }
387 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388}
389
390/**
391 * hdd_wmm_enable_inactivity_timer() -
392 * function to enable the traffic inactivity timer for the given AC
393 *
394 * @pQosContext: [in] pointer to pQosContext
395 * @inactivityTime: [in] value of the inactivity interval in millisecs
396 *
397 * When a QoS-Tspec is successfully setup, if the inactivity interval
398 * time specified in the AddTS parameters is non-zero, this function
399 * is invoked to start a traffic inactivity timer for the given AC.
400 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530401 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800402 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530403static QDF_STATUS
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700404hdd_wmm_enable_inactivity_timer(struct hdd_wmm_qos_context *pQosContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405 uint32_t inactivityTime)
406{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530407 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700408 struct hdd_adapter *pAdapter = pQosContext->pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800409 sme_ac_enum_type acType = pQosContext->acType;
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700410 struct hdd_wmm_ac_status *pAc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411
412 pAdapter = pQosContext->pAdapter;
413 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
414
Anurag Chouhan210db072016-02-22 18:42:15 +0530415 qdf_status = qdf_mc_timer_init(&pAc->wmmInactivityTimer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530416 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800417 hdd_wmm_inactivity_timer_cb,
418 pQosContext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530419 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700420 hdd_err("Initializing inactivity timer failed on AC %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 acType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530422 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423 }
424 /* Start the inactivity timer */
Anurag Chouhan210db072016-02-22 18:42:15 +0530425 qdf_status = qdf_mc_timer_start(&pAc->wmmInactivityTimer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800426 inactivityTime);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530427 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700428 hdd_err("Starting inactivity timer failed on AC %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429 acType);
Anurag Chouhan210db072016-02-22 18:42:15 +0530430 qdf_status = qdf_mc_timer_destroy(&pAc->wmmInactivityTimer);
Srinivas Girigowda576b2352017-08-25 14:44:26 -0700431 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432 hdd_err("Failed to destroy inactivity timer");
Srinivas Girigowda576b2352017-08-25 14:44:26 -0700433
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530434 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435 }
436 pAc->wmmInactivityTime = inactivityTime;
437 /* Initialize the current tx traffic count on this AC */
438 pAc->wmmPrevTrafficCnt =
439 pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->
440 acType];
441 pQosContext->is_inactivity_timer_running = true;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530442 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443}
444
445/**
446 * hdd_wmm_disable_inactivity_timer() -
447 * function to disable the traffic inactivity timer for the given AC.
448 *
449 * @pQosContext: [in] pointer to pQosContext
450 *
451 * This function is invoked to disable the traffic inactivity timer
452 * for the given AC. This is normally done when the TS is deleted.
453 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530454 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800455 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530456static QDF_STATUS
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700457hdd_wmm_disable_inactivity_timer(struct hdd_wmm_qos_context *pQosContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458{
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700459 struct hdd_adapter *pAdapter = pQosContext->pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460 sme_ac_enum_type acType = pQosContext->acType;
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700461 struct hdd_wmm_ac_status *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530462 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800463
464 /* Clear the timer and the counter */
465 pAc->wmmInactivityTime = 0;
466 pAc->wmmPrevTrafficCnt = 0;
467
468 if (pQosContext->is_inactivity_timer_running == true) {
469 pQosContext->is_inactivity_timer_running = false;
Anurag Chouhan210db072016-02-22 18:42:15 +0530470 qdf_status = qdf_mc_timer_stop(&pAc->wmmInactivityTimer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530471 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472 hdd_err("Failed to stop inactivity timer");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530473 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 }
Anurag Chouhan210db072016-02-22 18:42:15 +0530475 qdf_status = qdf_mc_timer_destroy(&pAc->wmmInactivityTimer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530476 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477 hdd_err("Failed to destroy inactivity timer:Timer started");
478 }
479
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530480 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481}
482#endif /* FEATURE_WLAN_ESE */
483
484/**
485 * hdd_wmm_sme_callback() - callback for QoS notifications
486 *
487 * @hHal: [in] the HAL handle
488 * @hddCtx : [in] the HDD specified handle
489 * @pCurrentQosInfo : [in] the TSPEC params
490 * @smeStatus : [in] the QoS related SME status
491 * @qosFlowId: [in] the unique identifier of the flow
492 *
493 * This callback is registered by HDD with SME for receiving QoS
494 * notifications. Even though this function has a static scope it
495 * gets called externally through some function pointer magic (so
496 * there is a need for rigorous parameter checking).
497 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530498 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530500static QDF_STATUS hdd_wmm_sme_callback(tHalHandle hHal,
Abhishek Singh12be60f2017-08-11 13:52:42 +0530501 void *hddCtx,
502 struct sme_qos_wmmtspecinfo *pCurrentQosInfo,
503 enum sme_qos_statustype smeStatus,
504 uint32_t qosFlowId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700506 struct hdd_wmm_qos_context *pQosContext = hddCtx;
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700507 struct hdd_adapter *pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 sme_ac_enum_type acType;
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -0700509 struct hdd_wmm_ac_status *pAc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700511 hdd_debug("Entered, context %p", pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512
513 if (unlikely((NULL == pQosContext) ||
514 (HDD_WMM_CTX_MAGIC != pQosContext->magic))) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700515 hdd_err("Invalid QoS Context");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530516 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 }
518
519 pAdapter = pQosContext->pAdapter;
520 acType = pQosContext->acType;
521 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
522
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700523 hdd_debug("status %d flowid %d info %p",
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700524 smeStatus, qosFlowId, pCurrentQosInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525
526 switch (smeStatus) {
527
528 case SME_QOS_STATUS_SETUP_SUCCESS_IND:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700529 hdd_info("Setup is complete");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530
531 /* there will always be a TSPEC returned with this
532 * status, even if a TSPEC is not exchanged OTA
533 */
534 if (pCurrentQosInfo) {
535 pAc->wmmAcTspecValid = true;
536 memcpy(&pAc->wmmAcTspecInfo,
537 pCurrentQosInfo, sizeof(pAc->wmmAcTspecInfo));
538 }
539 pAc->wmmAcAccessAllowed = true;
540 pAc->wmmAcAccessGranted = true;
541 pAc->wmmAcAccessPending = false;
542 pAc->wmmAcAccessFailed = false;
543
544 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
545
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700546 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547
548 /* this was triggered by an application */
549 pQosContext->lastStatus =
550 HDD_WLAN_WMM_STATUS_SETUP_SUCCESS;
551 hdd_wmm_notify_app(pQosContext);
552 }
553
554#ifdef FEATURE_WLAN_ESE
555 /* Check if the inactivity interval is specified */
556 if (pCurrentQosInfo && pCurrentQosInfo->inactivity_interval) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700557 hdd_debug("Inactivity timer value = %d for AC=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 pCurrentQosInfo->inactivity_interval, acType);
559 hdd_wmm_enable_inactivity_timer(pQosContext,
560 pCurrentQosInfo->
561 inactivity_interval);
562 }
563#endif /* FEATURE_WLAN_ESE */
564
565 /* notify TL to enable trigger frames if necessary */
566 hdd_wmm_enable_tl_uapsd(pQosContext);
567
568 break;
569
570 case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700571 hdd_debug("Setup is complete (U-APSD set previously)");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572
573 pAc->wmmAcAccessAllowed = true;
574 pAc->wmmAcAccessGranted = true;
575 pAc->wmmAcAccessPending = false;
576
577 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
578
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700579 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580
581 /* this was triggered by an application */
582 pQosContext->lastStatus =
583 HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
584 hdd_wmm_notify_app(pQosContext);
585 }
586
587 break;
588
589 case SME_QOS_STATUS_SETUP_FAILURE_RSP:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700590 hdd_err("Setup failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 /* QoS setup failed */
592
593 pAc->wmmAcAccessPending = false;
594 pAc->wmmAcAccessFailed = true;
595 pAc->wmmAcAccessAllowed = false;
596 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
597
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700598 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599
600 /* this was triggered by an application */
601 pQosContext->lastStatus =
602 HDD_WLAN_WMM_STATUS_SETUP_FAILED;
603
604 hdd_wmm_notify_app(pQosContext);
605 }
606
607 /* Setting up QoS Failed, QoS context can be released.
608 * SME is releasing this flow information and if HDD
609 * doesn't release this context, next time if
610 * application uses the same handle to set-up QoS, HDD
611 * (as it has QoS context for this handle) will issue
612 * Modify QoS request to SME but SME will reject as now
613 * it has no information for this flow.
614 */
615 hdd_wmm_free_context(pQosContext);
616 break;
617
618 case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700619 hdd_err("Setup Invalid Params, notify TL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 /* QoS setup failed */
621 pAc->wmmAcAccessAllowed = false;
622
623 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) {
624
625 /* we note the failure, but we also mark
626 * access as allowed so that the packets will
627 * flow. Note that the MAC will "do the right
628 * thing"
629 */
630 pAc->wmmAcAccessPending = false;
631 pAc->wmmAcAccessFailed = true;
632 pAc->wmmAcAccessAllowed = true;
633
634 } else {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700635 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636
637 /* this was triggered by an application */
638 pQosContext->lastStatus =
639 HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
640 hdd_wmm_notify_app(pQosContext);
641 }
642 break;
643
644 case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700645 hdd_err("Setup failed, not a QoS AP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700647 hdd_notice("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648
649 /* this was triggered by an application */
650 pQosContext->lastStatus =
651 HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
652 hdd_wmm_notify_app(pQosContext);
653 }
654 break;
655
656 case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700657 hdd_debug("Setup pending");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 /* not a callback status -- ignore if we get it */
659 break;
660
661 case SME_QOS_STATUS_SETUP_MODIFIED_IND:
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700662 hdd_debug("Setup modified");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 if (pCurrentQosInfo) {
664 /* update the TSPEC */
665 pAc->wmmAcTspecValid = true;
666 memcpy(&pAc->wmmAcTspecInfo,
667 pCurrentQosInfo, sizeof(pAc->wmmAcTspecInfo));
668
669 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700670 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671
672 /* this was triggered by an application */
673 pQosContext->lastStatus =
674 HDD_WLAN_WMM_STATUS_MODIFIED;
675 hdd_wmm_notify_app(pQosContext);
676 }
677 /* need to tell TL to update its UAPSD handling */
678 hdd_wmm_enable_tl_uapsd(pQosContext);
679 }
680 break;
681
682 case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
683 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) {
684
685 /* this was triggered by implicit QoS so we
686 * know packets are pending
687 */
688 pAc->wmmAcAccessPending = false;
689 pAc->wmmAcAccessGranted = true;
690 pAc->wmmAcAccessAllowed = true;
691
692 } else {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700693 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694
695 /* this was triggered by an application */
696 pQosContext->lastStatus =
697 HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
698 hdd_wmm_notify_app(pQosContext);
699 }
700 break;
701
702 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
703 /* nothing to do for now */
704 break;
705
706 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700707 hdd_err("Setup successful but U-APSD failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708
709 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) {
710
711 /* QoS setup was successful but setting U=APSD
712 * failed. Since the OTA part of the request
713 * was successful, we don't mark this as a
714 * failure. the packets will flow. Note that
Jeff Johnson1677bbb2017-01-12 08:39:19 -0800715 * the MAC will "do the right thing"
716 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 pAc->wmmAcAccessGranted = true;
718 pAc->wmmAcAccessAllowed = true;
719 pAc->wmmAcAccessFailed = false;
720 pAc->wmmAcAccessPending = false;
721
722 } else {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700723 hdd_notice("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724
725 /* this was triggered by an application */
726 pQosContext->lastStatus =
727 HDD_WLAN_WMM_STATUS_SETUP_UAPSD_SET_FAILED;
728 hdd_wmm_notify_app(pQosContext);
729 }
730
731 /* Since U-APSD portion failed disabled trigger frame
732 * generation
733 */
734 hdd_wmm_disable_tl_uapsd(pQosContext);
735
736 break;
737
738 case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700739 hdd_debug("Release is complete");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800740
741 if (pCurrentQosInfo) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700742 hdd_debug("flows still active");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743
744 /* there is still at least one flow active for
745 * this AC so update the AC state
746 */
747 memcpy(&pAc->wmmAcTspecInfo,
748 pCurrentQosInfo, sizeof(pAc->wmmAcTspecInfo));
749
750 /* need to tell TL to update its UAPSD handling */
751 hdd_wmm_enable_tl_uapsd(pQosContext);
752 } else {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700753 hdd_debug("last flow");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754
755 /* this is the last flow active for this AC so
756 * update the AC state
757 */
758 pAc->wmmAcTspecValid = false;
759
760 /* DELTS is successful, do not allow */
761 pAc->wmmAcAccessAllowed = false;
762
763 /* need to tell TL to update its UAPSD handling */
764 hdd_wmm_disable_tl_uapsd(pQosContext);
765 }
766
767 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700768 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769
770 /* this was triggered by an application */
771 pQosContext->lastStatus =
772 HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
773 hdd_wmm_notify_app(pQosContext);
774 }
775 /* we are done with this flow */
776 hdd_wmm_free_context(pQosContext);
777 break;
778
779 case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700780 hdd_debug("Release failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781
782 /* we don't need to update our state or TL since
783 * nothing has changed
784 */
785 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700786 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787
788 /* this was triggered by an application */
789 pQosContext->lastStatus =
790 HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
791 hdd_wmm_notify_app(pQosContext);
792 }
793
794 break;
795
796 case SME_QOS_STATUS_RELEASE_QOS_LOST_IND:
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700797 hdd_debug("QOS Lost indication received");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798
799 /* current TSPEC is no longer valid */
800 pAc->wmmAcTspecValid = false;
801 /* AP has sent DELTS, do not allow */
802 pAc->wmmAcAccessAllowed = false;
803
804 /* need to tell TL to update its UAPSD handling */
805 hdd_wmm_disable_tl_uapsd(pQosContext);
806
807 if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) {
808 /* we no longer have implicit access granted */
809 pAc->wmmAcAccessGranted = false;
810 pAc->wmmAcAccessFailed = false;
811 } else {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700812 hdd_debug("Explicit Qos, notifying user space");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813
814 /* this was triggered by an application */
815 pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_LOST;
816 hdd_wmm_notify_app(pQosContext);
817 }
818
819 /* we are done with this flow */
820 hdd_wmm_free_context(pQosContext);
821 break;
822
823 case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700824 hdd_info("Release pending");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 /* not a callback status -- ignore if we get it */
826 break;
827
828 case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700829 hdd_err("Release Invalid Params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
831 /* this was triggered by an application */
832 pQosContext->lastStatus =
833 HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
834 hdd_wmm_notify_app(pQosContext);
835 }
836 break;
837
838 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700839 hdd_info("Modification is complete, notify TL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840
841 /* there will always be a TSPEC returned with this
842 * status, even if a TSPEC is not exchanged OTA
843 */
844 if (pCurrentQosInfo) {
845 pAc->wmmAcTspecValid = true;
846 memcpy(&pAc->wmmAcTspecInfo,
847 pCurrentQosInfo, sizeof(pAc->wmmAcTspecInfo));
848 }
849
850 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
851 /* this was triggered by an application */
852 pQosContext->lastStatus =
853 HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS;
854 hdd_wmm_notify_app(pQosContext);
855 }
856 /* notify TL to enable trigger frames if necessary */
857 hdd_wmm_enable_tl_uapsd(pQosContext);
858
859 break;
860
861 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
862 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
863 /* this was triggered by an application */
864 pQosContext->lastStatus =
865 HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
866 hdd_wmm_notify_app(pQosContext);
867 }
868 break;
869
870 case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
871 /* the flow modification failed so we'll leave in
872 * place whatever existed beforehand
873 */
874
875 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
876 /* this was triggered by an application */
877 pQosContext->lastStatus =
878 HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
879 hdd_wmm_notify_app(pQosContext);
880 }
881 break;
882
883 case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700884 hdd_info("modification pending");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800885 /* not a callback status -- ignore if we get it */
886 break;
887
888 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
889 /* the flow modification was successful but no QoS
890 * changes required
891 */
892
893 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
894 /* this was triggered by an application */
895 pQosContext->lastStatus =
896 HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
897 hdd_wmm_notify_app(pQosContext);
898 }
899 break;
900
901 case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
902 /* invalid params -- notify the application */
903 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
904 /* this was triggered by an application */
905 pQosContext->lastStatus =
906 HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
907 hdd_wmm_notify_app(pQosContext);
908 }
909 break;
910
911 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_PENDING:
912 /* nothing to do for now. when APSD is established we'll have work to do */
913 break;
914
915 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700916 hdd_err("Modify successful but U-APSD failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917
918 /* QoS modification was successful but setting U=APSD
919 * failed. This will always be an explicit QoS
920 * instance, so all we can do is notify the
921 * application and let it clean up.
922 */
923 if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) {
924 /* this was triggered by an application */
925 pQosContext->lastStatus =
926 HDD_WLAN_WMM_STATUS_MODIFY_UAPSD_SET_FAILED;
927 hdd_wmm_notify_app(pQosContext);
928 }
929 /* Since U-APSD portion failed disabled trigger frame
930 * generation
931 */
932 hdd_wmm_disable_tl_uapsd(pQosContext);
933
934 break;
935
936 case SME_QOS_STATUS_HANDING_OFF:
937 /* no roaming so we won't see this */
938 break;
939
940 case SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND:
941 /* need to tell TL to stop trigger frame generation */
942 hdd_wmm_disable_tl_uapsd(pQosContext);
943 break;
944
945 case SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND:
946 /* need to tell TL to start sending trigger frames again */
947 hdd_wmm_enable_tl_uapsd(pQosContext);
948 break;
949
950 default:
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700951 hdd_err("unexpected SME Status=%d", smeStatus);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530952 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800953 }
954
955 /* if Tspec only allows downstream traffic then access is not
956 * allowed
957 */
958 if (pAc->wmmAcTspecValid &&
959 (pAc->wmmAcTspecInfo.ts_info.direction ==
960 SME_QOS_WMM_TS_DIR_DOWNLINK)) {
961 pAc->wmmAcAccessAllowed = false;
962 }
963 /* if we have valid Tpsec or if ACM bit is not set, allow access */
964 if ((pAc->wmmAcTspecValid &&
965 (pAc->wmmAcTspecInfo.ts_info.direction !=
966 SME_QOS_WMM_TS_DIR_DOWNLINK)) || !pAc->wmmAcAccessRequired) {
967 pAc->wmmAcAccessAllowed = true;
968 }
969
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -0700970 hdd_debug("complete, access for TL AC %d is%sallowed",
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700971 acType, pAc->wmmAcAccessAllowed ? " " : " not ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530973 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974}
975#endif
976
977/**
978 * hdd_wmmps_helper() - Function to set uapsd psb dynamically
979 *
980 * @pAdapter: [in] pointer to adapter structure
981 * @ptr: [in] pointer to command buffer
982 *
983 * Return: Zero on success, appropriate error on failure.
984 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -0700985int hdd_wmmps_helper(struct hdd_adapter *pAdapter, uint8_t *ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986{
987 if (NULL == pAdapter) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700988 hdd_err("pAdapter is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989 return -EINVAL;
990 }
991 if (NULL == ptr) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -0700992 hdd_err("ptr is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993 return -EINVAL;
994 }
995 /* convert ASCII to integer */
996 pAdapter->configuredPsb = ptr[9] - '0';
997 pAdapter->psbChanged = HDD_PSB_CHANGED;
998
999 return 0;
1000}
1001
1002/**
1003 * __hdd_wmm_do_implicit_qos() - Function which will attempt to setup
1004 * QoS for any AC requiring it.
1005 * @work: [in] pointer to work structure.
1006 *
1007 * Return: none
1008 */
1009static void __hdd_wmm_do_implicit_qos(struct work_struct *work)
1010{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07001011 struct hdd_wmm_qos_context *pQosContext =
1012 container_of(work, struct hdd_wmm_qos_context, wmmAcSetupImplicitQos);
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001013 struct hdd_adapter *pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001014 sme_ac_enum_type acType;
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07001015 struct hdd_wmm_ac_status *pAc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016#ifndef WLAN_MDM_CODE_REDUCTION_OPT
Abhishek Singh12be60f2017-08-11 13:52:42 +05301017 enum sme_qos_statustype smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001018#endif
Abhishek Singh12be60f2017-08-11 13:52:42 +05301019 struct sme_qos_wmmtspecinfo qosInfo;
Jeff Johnson1083b6e2017-08-28 11:35:22 -07001020 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001021
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001022 hdd_debug("Entered, context %p", pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001023
1024 if (unlikely(HDD_WMM_CTX_MAGIC != pQosContext->magic)) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001025 hdd_err("Invalid QoS Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001026 return;
1027 }
1028
1029 pAdapter = pQosContext->pAdapter;
1030
1031 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301032 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001033 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001034
1035 acType = pQosContext->acType;
1036 pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
1037
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001038 hdd_info("pAdapter %p acType %d", pAdapter, acType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039
1040 if (!pAc->wmmAcAccessNeeded) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001041 hdd_err("AC %d doesn't need service", acType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 pQosContext->magic = 0;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -07001043 qdf_mem_free(pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001044 return;
1045 }
1046
1047 pAc->wmmAcAccessPending = true;
1048 pAc->wmmAcAccessNeeded = false;
1049
1050 memset(&qosInfo, 0, sizeof(qosInfo));
1051
1052 qosInfo.ts_info.psb = pAdapter->configuredPsb;
1053
1054 switch (acType) {
1055 case SME_AC_VO:
1056 qosInfo.ts_info.up = SME_QOS_WMM_UP_VO;
1057 /* Check if there is any valid configuration from framework */
1058 if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) {
1059 qosInfo.ts_info.psb =
1060 ((WLAN_HDD_GET_CTX(pAdapter))->config->
1061 UapsdMask & SME_QOS_UAPSD_VO) ? 1 : 0;
1062 }
1063 qosInfo.ts_info.direction =
1064 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcVo;
1065 qosInfo.ts_info.tid = 255;
1066 qosInfo.mean_data_rate =
1067 (WLAN_HDD_GET_CTX(pAdapter))->config->
1068 InfraMeanDataRateAcVo;
1069 qosInfo.min_phy_rate =
1070 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcVo;
1071 qosInfo.min_service_interval =
1072 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdVoSrvIntv;
1073 qosInfo.nominal_msdu_size =
1074 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcVo;
1075 qosInfo.surplus_bw_allowance =
1076 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcVo;
1077 qosInfo.suspension_interval =
1078 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdVoSuspIntv;
1079 break;
1080 case SME_AC_VI:
1081 qosInfo.ts_info.up = SME_QOS_WMM_UP_VI;
1082 /* Check if there is any valid configuration from framework */
1083 if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) {
1084 qosInfo.ts_info.psb =
1085 ((WLAN_HDD_GET_CTX(pAdapter))->config->
1086 UapsdMask & SME_QOS_UAPSD_VI) ? 1 : 0;
1087 }
1088 qosInfo.ts_info.direction =
1089 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcVi;
1090 qosInfo.ts_info.tid = 255;
1091 qosInfo.mean_data_rate =
1092 (WLAN_HDD_GET_CTX(pAdapter))->config->
1093 InfraMeanDataRateAcVi;
1094 qosInfo.min_phy_rate =
1095 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcVi;
1096 qosInfo.min_service_interval =
1097 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdViSrvIntv;
1098 qosInfo.nominal_msdu_size =
1099 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcVi;
1100 qosInfo.surplus_bw_allowance =
1101 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcVi;
1102 qosInfo.suspension_interval =
1103 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdViSuspIntv;
1104 break;
1105 default:
1106 case SME_AC_BE:
1107 qosInfo.ts_info.up = SME_QOS_WMM_UP_BE;
1108 /* Check if there is any valid configuration from framework */
1109 if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) {
1110 qosInfo.ts_info.psb =
1111 ((WLAN_HDD_GET_CTX(pAdapter))->config->
1112 UapsdMask & SME_QOS_UAPSD_BE) ? 1 : 0;
1113 }
1114 qosInfo.ts_info.direction =
1115 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcBe;
1116 qosInfo.ts_info.tid = 255;
1117 qosInfo.mean_data_rate =
1118 (WLAN_HDD_GET_CTX(pAdapter))->config->
1119 InfraMeanDataRateAcBe;
1120 qosInfo.min_phy_rate =
1121 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcBe;
1122 qosInfo.min_service_interval =
1123 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBeSrvIntv;
1124 qosInfo.nominal_msdu_size =
1125 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcBe;
1126 qosInfo.surplus_bw_allowance =
1127 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcBe;
1128 qosInfo.suspension_interval =
1129 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBeSuspIntv;
1130 break;
1131 case SME_AC_BK:
1132 qosInfo.ts_info.up = SME_QOS_WMM_UP_BK;
1133 /* Check if there is any valid configuration from framework */
1134 if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) {
1135 qosInfo.ts_info.psb =
1136 ((WLAN_HDD_GET_CTX(pAdapter))->config->
1137 UapsdMask & SME_QOS_UAPSD_BK) ? 1 : 0;
1138 }
1139 qosInfo.ts_info.direction =
1140 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcBk;
1141 qosInfo.ts_info.tid = 255;
1142 qosInfo.mean_data_rate =
1143 (WLAN_HDD_GET_CTX(pAdapter))->config->
1144 InfraMeanDataRateAcBk;
1145 qosInfo.min_phy_rate =
1146 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcBk;
1147 qosInfo.min_service_interval =
1148 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBkSrvIntv;
1149 qosInfo.nominal_msdu_size =
1150 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcBk;
1151 qosInfo.surplus_bw_allowance =
1152 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcBk;
1153 qosInfo.suspension_interval =
1154 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBkSuspIntv;
1155 break;
1156 }
1157#ifdef FEATURE_WLAN_ESE
1158 qosInfo.inactivity_interval =
1159 (WLAN_HDD_GET_CTX(pAdapter))->config->InfraInactivityInterval;
1160#endif
1161 qosInfo.ts_info.burst_size_defn =
1162 (WLAN_HDD_GET_CTX(pAdapter))->config->burstSizeDefinition;
1163
1164 switch ((WLAN_HDD_GET_CTX(pAdapter))->config->tsInfoAckPolicy) {
1165 case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK:
1166 qosInfo.ts_info.ack_policy =
1167 SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
1168 break;
1169
1170 case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK:
1171 qosInfo.ts_info.ack_policy =
1172 SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
1173 break;
1174
1175 default:
1176 /* unknown */
1177 qosInfo.ts_info.ack_policy =
1178 SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
1179 }
1180
1181 if (qosInfo.ts_info.ack_policy ==
1182 SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK) {
1183 if (!sme_qos_is_ts_info_ack_policy_valid
1184 ((tpAniSirGlobal) WLAN_HDD_GET_HAL_CTX(pAdapter), &qosInfo,
1185 pAdapter->sessionId)) {
1186 qosInfo.ts_info.ack_policy =
1187 SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
1188 }
1189 }
1190
1191 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
1192 list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
1193 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
1194
1195#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1196 smeStatus = sme_qos_setup_req(WLAN_HDD_GET_HAL_CTX(pAdapter),
1197 pAdapter->sessionId,
1198 &qosInfo,
1199 hdd_wmm_sme_callback,
1200 pQosContext,
1201 qosInfo.ts_info.up,
1202 &pQosContext->qosFlowId);
1203
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001204 hdd_debug("sme_qos_setup_req returned %d flowid %d",
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001205 smeStatus, pQosContext->qosFlowId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206
1207 /* need to check the return values and act appropriately */
1208 switch (smeStatus) {
1209 case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
1210 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
1211 /* setup is pending, so no more work to do now. all
1212 * further work will be done in hdd_wmm_sme_callback()
1213 */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001214 hdd_info("Setup is pending, no further work");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215
1216 break;
1217
1218 case SME_QOS_STATUS_SETUP_FAILURE_RSP:
1219 /* we can't tell the difference between when a request
1220 * fails because AP rejected it versus when SME
1221 * encountered an internal error. in either case SME
1222 * won't ever reference this context so free the
1223 * record
1224 */
1225 hdd_wmm_free_context(pQosContext);
1226
1227 /* fall through and start packets flowing */
1228 case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
1229 /* no ACM in effect, no need to setup U-APSD */
1230 case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
1231 /* no ACM in effect, U-APSD is desired but was already setup */
1232
1233 /* for these cases everything is already setup so we
1234 * can signal TL that it has work to do
1235 */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001236 hdd_info("Setup is complete, notify TL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237
1238 pAc->wmmAcAccessAllowed = true;
1239 pAc->wmmAcAccessGranted = true;
1240 pAc->wmmAcAccessPending = false;
1241
1242 break;
1243
1244 default:
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001245 hdd_err("unexpected SME Status=%d", smeStatus);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301246 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001247 }
1248#endif
1249
1250}
1251
1252/**
1253 * hdd_wmm_do_implicit_qos() - SSR wraper function for hdd_wmm_do_implicit_qos
1254 * @work: pointer to work_struct
1255 *
1256 * Return: none
1257 */
1258static void hdd_wmm_do_implicit_qos(struct work_struct *work)
1259{
1260 cds_ssr_protect(__func__);
1261 __hdd_wmm_do_implicit_qos(work);
1262 cds_ssr_unprotect(__func__);
1263}
1264
1265/**
1266 * hdd_wmm_init() - initialize the WMM DSCP configuation
1267 * @pAdapter : [in] pointer to Adapter context
1268 *
1269 * This function will initialize the WMM DSCP configuation of an
1270 * adapter to an initial state. The configuration can later be
1271 * overwritten via application APIs or via QoS Map sent OTA.
1272 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301273 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001275QDF_STATUS hdd_wmm_init(struct hdd_adapter *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276{
Abhishek Singh12be60f2017-08-11 13:52:42 +05301277 enum sme_qos_wmmuptype *hddWmmDscpToUpMap = pAdapter->hddWmmDscpToUpMap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001278 uint8_t dscp;
1279
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001280 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281
1282 /* DSCP to User Priority Lookup Table
1283 * By default use the 3 Precedence bits of DSCP as the User Priority
1284 */
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001285 for (dscp = 0; dscp <= WLAN_HDD_MAX_DSCP; dscp++)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286 hddWmmDscpToUpMap[dscp] = dscp >> 3;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287
1288 /* Special case for Expedited Forwarding (DSCP 46) */
1289 hddWmmDscpToUpMap[46] = SME_QOS_WMM_UP_VO;
1290
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301291 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001292}
1293
1294/**
1295 * hdd_wmm_adapter_init() - initialize the WMM configuration of an adapter
1296 * @pAdapter: [in] pointer to Adapter context
1297 *
1298 * This function will initialize the WMM configuation and status of an
1299 * adapter to an initial state. The configuration can later be
1300 * overwritten via application APIs
1301 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301302 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001304QDF_STATUS hdd_wmm_adapter_init(struct hdd_adapter *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07001306 struct hdd_wmm_ac_status *pAcStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 sme_ac_enum_type acType;
1308
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001309 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310
1311 pAdapter->hddWmmStatus.wmmQap = false;
1312 INIT_LIST_HEAD(&pAdapter->hddWmmStatus.wmmContextList);
1313 mutex_init(&pAdapter->hddWmmStatus.wmmLock);
1314
1315 for (acType = 0; acType < WLAN_MAX_AC; acType++) {
1316 pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
1317 pAcStatus->wmmAcAccessRequired = false;
1318 pAcStatus->wmmAcAccessNeeded = false;
1319 pAcStatus->wmmAcAccessPending = false;
1320 pAcStatus->wmmAcAccessFailed = false;
1321 pAcStatus->wmmAcAccessGranted = false;
1322 pAcStatus->wmmAcAccessAllowed = false;
1323 pAcStatus->wmmAcTspecValid = false;
1324 pAcStatus->wmmAcUapsdInfoValid = false;
1325 }
1326 /* Invalid value(0xff) to indicate psb not configured through
1327 * framework initially.
1328 */
1329 pAdapter->configuredPsb = HDD_PSB_CFG_INVALID;
1330
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301331 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332}
1333
1334/**
1335 * hdd_wmm_adapter_clear() - Function which will clear the WMM status
1336 * for all the ACs
1337 *
1338 * @pAdapter: [in] pointer to Adapter context
1339 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301340 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001342QDF_STATUS hdd_wmm_adapter_clear(struct hdd_adapter *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001343{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07001344 struct hdd_wmm_ac_status *pAcStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001345 sme_ac_enum_type acType;
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001346
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001347 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001348 for (acType = 0; acType < WLAN_MAX_AC; acType++) {
1349 pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
1350 pAcStatus->wmmAcAccessRequired = false;
1351 pAcStatus->wmmAcAccessNeeded = false;
1352 pAcStatus->wmmAcAccessPending = false;
1353 pAcStatus->wmmAcAccessFailed = false;
1354 pAcStatus->wmmAcAccessGranted = false;
1355 pAcStatus->wmmAcAccessAllowed = false;
1356 pAcStatus->wmmAcTspecValid = false;
1357 pAcStatus->wmmAcUapsdInfoValid = false;
1358 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301359 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360}
1361
1362/**
1363 * hdd_wmm_close() - WMM close function
1364 * @pAdapter: [in] pointer to adapter context
1365 *
1366 * Function which will perform any necessary work to to clean up the
1367 * WMM functionality prior to the kernel module unload.
1368 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301369 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001371QDF_STATUS hdd_wmm_adapter_close(struct hdd_adapter *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07001373 struct hdd_wmm_qos_context *pQosContext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001375 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376
1377 /* free any context records that we still have linked */
1378 while (!list_empty(&pAdapter->hddWmmStatus.wmmContextList)) {
1379 pQosContext =
1380 list_first_entry(&pAdapter->hddWmmStatus.wmmContextList,
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07001381 struct hdd_wmm_qos_context, node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382#ifdef FEATURE_WLAN_ESE
1383 hdd_wmm_disable_inactivity_timer(pQosContext);
1384#endif
1385 if (pQosContext->handle == HDD_WMM_HANDLE_IMPLICIT
1386 && pQosContext->magic == HDD_WMM_CTX_MAGIC)
1387 cds_flush_work(&pQosContext->wmmAcSetupImplicitQos);
1388
1389 hdd_wmm_free_context(pQosContext);
1390 }
1391
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301392 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001393}
1394
1395/**
1396 * hdd_wmm_classify_pkt() - Function which will classify an OS packet
Govind Singhb7ab5772015-10-08 16:38:37 +05301397 * into a WMM AC based on DSCP
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 *
Govind Singhb7ab5772015-10-08 16:38:37 +05301399 * @adapter: adapter upon which the packet is being transmitted
1400 * @skb: pointer to network buffer
1401 * @user_pri: user priority of the OS packet
1402 * @is_eapol: eapol packet flag
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001403 *
1404 * Return: None
1405 */
1406static
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001407void hdd_wmm_classify_pkt(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408 struct sk_buff *skb,
Abhishek Singh12be60f2017-08-11 13:52:42 +05301409 enum sme_qos_wmmuptype *user_pri,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001410 bool *is_eapol)
1411{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412 unsigned char dscp;
Govind Singhb7ab5772015-10-08 16:38:37 +05301413 unsigned char tos;
1414 union generic_ethhdr *eth_hdr;
1415 struct iphdr *ip_hdr;
1416 struct ipv6hdr *ipv6hdr;
1417 unsigned char *pkt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418
1419 /* this code is executed for every packet therefore
1420 * all debug code is kept conditional
1421 */
1422
1423#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001424 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001425#endif /* HDD_WMM_DEBUG */
1426
Govind Singhb7ab5772015-10-08 16:38:37 +05301427 pkt = skb->data;
1428 eth_hdr = (union generic_ethhdr *)pkt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429
1430#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001431 hdd_debug("proto is 0x%04x", skb->protocol);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001432#endif /* HDD_WMM_DEBUG */
1433
Govind Singhb7ab5772015-10-08 16:38:37 +05301434 if (eth_hdr->eth_II.h_proto == htons(ETH_P_IP)) {
1435 /* case 1: Ethernet II IP packet */
1436 ip_hdr = (struct iphdr *)&pkt[sizeof(eth_hdr->eth_II)];
1437 tos = ip_hdr->tos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001439 hdd_debug("Ethernet II IP Packet, tos is %d", tos);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440#endif /* HDD_WMM_DEBUG */
1441
Govind Singhb7ab5772015-10-08 16:38:37 +05301442 } else if (eth_hdr->eth_II.h_proto == htons(ETH_P_IPV6)) {
1443 ipv6hdr = ipv6_hdr(skb);
1444 tos = ntohs(*(const __be16 *)ipv6hdr) >> 4;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001445#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001446 hdd_debug("Ethernet II IPv6 Packet, tos is %d", tos);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447#endif /* HDD_WMM_DEBUG */
Govind Singhb7ab5772015-10-08 16:38:37 +05301448 } else if ((ntohs(eth_hdr->eth_II.h_proto) < WLAN_MIN_PROTO) &&
1449 (eth_hdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) &&
1450 (eth_hdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) &&
1451 (eth_hdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) &&
1452 (eth_hdr->eth_8023.h_proto == htons(ETH_P_IP))) {
1453 /* case 2: 802.3 LLC/SNAP IP packet */
1454 ip_hdr = (struct iphdr *)&pkt[sizeof(eth_hdr->eth_8023)];
1455 tos = ip_hdr->tos;
1456#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001457 hdd_debug("802.3 LLC/SNAP IP Packet, tos is %d", tos);
Govind Singhb7ab5772015-10-08 16:38:37 +05301458#endif /* HDD_WMM_DEBUG */
1459 } else if (eth_hdr->eth_II.h_proto == htons(ETH_P_8021Q)) {
1460 /* VLAN tagged */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461
Govind Singhb7ab5772015-10-08 16:38:37 +05301462 if (eth_hdr->eth_IIv.h_vlan_encapsulated_proto ==
1463 htons(ETH_P_IP)) {
1464 /* case 3: Ethernet II vlan-tagged IP packet */
1465 ip_hdr =
1466 (struct iphdr *)
1467 &pkt[sizeof(eth_hdr->eth_IIv)];
1468 tos = ip_hdr->tos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001470 hdd_debug("Ether II VLAN tagged IP Packet, tos is %d",
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001471 tos);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472#endif /* HDD_WMM_DEBUG */
Govind Singhb7ab5772015-10-08 16:38:37 +05301473 } else
1474 if ((ntohs(eth_hdr->eth_IIv.h_vlan_encapsulated_proto)
1475 < WLAN_MIN_PROTO)
1476 && (eth_hdr->eth_8023v.h_snap.dsap ==
1477 WLAN_SNAP_DSAP)
1478 && (eth_hdr->eth_8023v.h_snap.ssap ==
1479 WLAN_SNAP_SSAP)
1480 && (eth_hdr->eth_8023v.h_snap.ctrl ==
1481 WLAN_SNAP_CTRL)
1482 && (eth_hdr->eth_8023v.h_proto ==
1483 htons(ETH_P_IP))) {
1484 /* case 4: 802.3 LLC/SNAP vlan-tagged IP packet */
1485 ip_hdr =
1486 (struct iphdr *)
1487 &pkt[sizeof(eth_hdr->eth_8023v)];
1488 tos = ip_hdr->tos;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001490 hdd_debug("802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d",
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001491 tos);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492#endif /* HDD_WMM_DEBUG */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001493 } else {
1494 /* default */
1495#ifdef HDD_WMM_DEBUG
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001496 hdd_warn("VLAN tagged Unhandled Protocol, using default tos");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001497#endif /* HDD_WMM_DEBUG */
Govind Singhb7ab5772015-10-08 16:38:37 +05301498 tos = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 }
1500 } else {
1501 /* default */
1502#ifdef HDD_WMM_DEBUG
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001503 hdd_warn("Unhandled Protocol, using default tos");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001504#endif /* HDD_WMM_DEBUG */
Govind Singhb7ab5772015-10-08 16:38:37 +05301505 /* Give the highest priority to 802.1x packet */
1506 if (eth_hdr->eth_II.h_proto ==
1507 htons(HDD_ETHERTYPE_802_1_X)) {
1508 tos = 0xC0;
1509 *is_eapol = true;
1510 } else
1511 tos = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001512 }
1513
Govind Singhb7ab5772015-10-08 16:38:37 +05301514 dscp = (tos >> 2) & 0x3f;
1515 *user_pri = adapter->hddWmmDscpToUpMap[dscp];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516
1517#ifdef HDD_WMM_DEBUG
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001518 hdd_debug("tos is %d, dscp is %d, up is %d", tos, dscp, *user_pri);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519#endif /* HDD_WMM_DEBUG */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520}
1521
Jeff Johnsone54e2ae2016-07-18 17:56:20 -07001522/**
1523 * __hdd_get_queue_index() - get queue index
1524 * @up: user priority
1525 *
1526 * Return: queue_index
1527 */
1528static uint16_t __hdd_get_queue_index(uint16_t up)
1529{
1530 if (qdf_unlikely(up >= ARRAY_SIZE(hdd_linux_up_to_ac_map)))
1531 return HDD_LINUX_AC_BE;
1532 return hdd_linux_up_to_ac_map[up];
1533}
1534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535#ifdef QCA_LL_TX_FLOW_CONTROL_V2
1536/**
1537 * hdd_get_queue_index() - get queue index
1538 * @up: user priority
1539 * @is_eapol: is_eapol flag
1540 *
1541 * Return: queue_index
1542 */
1543static
1544uint16_t hdd_get_queue_index(uint16_t up, bool is_eapol)
1545{
Anurag Chouhanc5548422016-02-24 18:33:27 +05301546 if (qdf_unlikely(is_eapol == true))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 return HDD_LINUX_AC_HI_PRIO;
Jeff Johnsone54e2ae2016-07-18 17:56:20 -07001548 return __hdd_get_queue_index(up);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549}
1550#else
1551static
1552uint16_t hdd_get_queue_index(uint16_t up, bool is_eapol)
1553{
Jeff Johnsone54e2ae2016-07-18 17:56:20 -07001554 return __hdd_get_queue_index(up);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555}
1556#endif
1557
1558
1559/**
1560 * hdd_hostapd_select_queue() - Function which will classify the packet
1561 * according to linux qdisc expectation.
1562 *
1563 * @dev: [in] pointer to net_device structure
1564 * @skb: [in] pointer to os packet
1565 *
1566 * Return: Qdisc queue index
1567 */
1568uint16_t hdd_hostapd_select_queue(struct net_device *dev, struct sk_buff *skb
1569#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
1570 , void *accel_priv
1571#endif
1572#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1573 , select_queue_fallback_t fallback
1574#endif
1575
1576)
1577{
Abhishek Singh12be60f2017-08-11 13:52:42 +05301578 enum sme_qos_wmmuptype up = SME_QOS_WMM_UP_BE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 uint16_t queueIndex;
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001580 struct hdd_adapter *adapter = (struct hdd_adapter *) netdev_priv(dev);
Jeff Johnson1083b6e2017-08-28 11:35:22 -07001581 struct hdd_context *hddctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001582 bool is_eapol = false;
Mukul Sharmab3152182015-10-30 20:47:30 +05301583 int status = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001584
Govind Singhb7ab5772015-10-08 16:38:37 +05301585 status = wlan_hdd_validate_context(hddctx);
Mukul Sharmab3152182015-10-30 20:47:30 +05301586
1587 if (status != 0) {
1588 skb->priority = SME_QOS_WMM_UP_BE;
1589 return HDD_LINUX_AC_BE;
1590 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591
Govind Singhb7ab5772015-10-08 16:38:37 +05301592 /* Get the user priority from IP header */
1593 hdd_wmm_classify_pkt(adapter, skb, &up, &is_eapol);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001594 skb->priority = up;
1595 queueIndex = hdd_get_queue_index(skb->priority, is_eapol);
1596
1597 return queueIndex;
1598}
1599
1600/**
1601 * hdd_wmm_select_queue() - Function which will classify the packet
1602 * according to linux qdisc expectation.
1603 *
1604 * @dev: [in] pointer to net_device structure
1605 * @skb: [in] pointer to os packet
1606 *
1607 * Return: Qdisc queue index
1608 */
1609uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb)
1610{
Abhishek Singh12be60f2017-08-11 13:52:42 +05301611 enum sme_qos_wmmuptype up = SME_QOS_WMM_UP_BE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612 uint16_t queueIndex;
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001613 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614 bool is_eapol = false;
Jeff Johnson1083b6e2017-08-28 11:35:22 -07001615 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Mukul Sharmabfd19ba2015-10-30 20:35:35 +05301616 int status;
1617
1618 status = wlan_hdd_validate_context(hdd_ctx);
1619 if (status != 0) {
1620 skb->priority = SME_QOS_WMM_UP_BE;
1621 return HDD_LINUX_AC_BE;
1622 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001623
Govind Singhb7ab5772015-10-08 16:38:37 +05301624 /* Get the user priority from IP header */
1625 hdd_wmm_classify_pkt(pAdapter, skb, &up, &is_eapol);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001626 skb->priority = up;
1627 queueIndex = hdd_get_queue_index(skb->priority, is_eapol);
Govind Singhb7ab5772015-10-08 16:38:37 +05301628
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001629 return queueIndex;
1630}
1631
1632/**
1633 * hdd_wmm_acquire_access_required() - Function which will determine
1634 * acquire admittance for a WMM AC is required or not based on psb configuration
1635 * done in framework
1636 *
1637 * @pAdapter: [in] pointer to adapter structure
1638 * @acType: [in] WMM AC type of OS packet
1639 *
1640 * Return: void
1641 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001642void hdd_wmm_acquire_access_required(struct hdd_adapter *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001643 sme_ac_enum_type acType)
1644{
1645 /* Each bit in the LSB nibble indicates 1 AC.
1646 * Clearing the particular bit in LSB nibble to indicate
1647 * access required
1648 */
1649 switch (acType) {
1650 case SME_AC_BK:
1651 /* clear first bit */
1652 pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_BK_CHANGED_MASK;
1653 break;
1654 case SME_AC_BE:
1655 /* clear second bit */
1656 pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_BE_CHANGED_MASK;
1657 break;
1658 case SME_AC_VI:
1659 /* clear third bit */
1660 pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_VI_CHANGED_MASK;
1661 break;
1662 case SME_AC_VO:
1663 /* clear fourth bit */
1664 pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_VO_CHANGED_MASK;
1665 break;
1666 default:
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001667 hdd_err("Invalid AC Type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668 break;
1669 }
1670}
1671
1672/**
1673 * hdd_wmm_acquire_access() - Function which will attempt to acquire
1674 * admittance for a WMM AC
1675 *
1676 * @pAdapter: [in] pointer to adapter context
1677 * @acType: [in] WMM AC type of OS packet
1678 * @pGranted: [out] pointer to bool flag when indicates if access
1679 * has been granted or not
1680 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301681 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001682 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001683QDF_STATUS hdd_wmm_acquire_access(struct hdd_adapter *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684 sme_ac_enum_type acType, bool *pGranted)
1685{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07001686 struct hdd_wmm_qos_context *pQosContext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001687
Rajeev Kumar3d4b1ef2016-01-29 15:57:26 -08001688 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689 "%s: Entered for AC %d", __func__, acType);
1690
1691 if (!hdd_wmm_is_active(pAdapter) ||
1692 !(WLAN_HDD_GET_CTX(pAdapter))->config->bImplicitQosEnabled ||
1693 !pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessRequired) {
1694 /* either we don't want QoS or the AP doesn't support
1695 * QoS or we don't want to do implicit QoS
1696 */
Rajeev Kumar3d4b1ef2016-01-29 15:57:26 -08001697 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001698 "%s: QoS not configured on both ends ", __func__);
1699
1700 *pGranted =
1701 pAdapter->hddWmmStatus.wmmAcStatus[acType].
1702 wmmAcAccessAllowed;
1703
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301704 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705 }
1706 /* do we already have an implicit QoS request pending for this AC? */
1707 if ((pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded) ||
1708 (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessPending)) {
1709 /* request already pending so we need to wait for that
1710 * response
1711 */
Rajeev Kumar3d4b1ef2016-01-29 15:57:26 -08001712 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001713 "%s: Implicit QoS for TL AC %d already scheduled",
1714 __func__, acType);
1715
1716 *pGranted = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301717 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 }
1719 /* did we already fail to establish implicit QoS for this AC?
1720 * (if so, access should have been granted when the failure
1721 * was handled)
1722 */
1723 if (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessFailed) {
1724 /* request previously failed
1725 * allow access, but we'll be downgraded
1726 */
Rajeev Kumar3d4b1ef2016-01-29 15:57:26 -08001727 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 "%s: Implicit QoS for TL AC %d previously failed",
1729 __func__, acType);
1730
1731 if (!pAdapter->hddWmmStatus.wmmAcStatus[acType].
1732 wmmAcAccessRequired) {
1733 pAdapter->hddWmmStatus.wmmAcStatus[acType].
1734 wmmAcAccessAllowed = true;
1735 *pGranted = true;
1736 } else {
1737 pAdapter->hddWmmStatus.wmmAcStatus[acType].
1738 wmmAcAccessAllowed = false;
1739 *pGranted = false;
1740 }
1741
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301742 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743 }
1744 /* we need to establish implicit QoS */
Rajeev Kumar3d4b1ef2016-01-29 15:57:26 -08001745 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001746 "%s: Need to schedule implicit QoS for TL AC %d, pAdapter is %p",
1747 __func__, acType, pAdapter);
1748
1749 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded = true;
1750
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -07001751 pQosContext = qdf_mem_malloc(sizeof(*pQosContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752 if (NULL == pQosContext) {
1753 /* no memory for QoS context. Nothing we can do but
1754 * let data flow
1755 */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001756 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001757 "%s: Unable to allocate context", __func__);
1758 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed =
1759 true;
1760 *pGranted = true;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301761 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 }
1763
1764 pQosContext->acType = acType;
1765 pQosContext->pAdapter = pAdapter;
1766 pQosContext->qosFlowId = 0;
1767 pQosContext->handle = HDD_WMM_HANDLE_IMPLICIT;
1768 pQosContext->magic = HDD_WMM_CTX_MAGIC;
1769 pQosContext->is_inactivity_timer_running = false;
1770
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771 INIT_WORK(&pQosContext->wmmAcSetupImplicitQos, hdd_wmm_do_implicit_qos);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001772
Rajeev Kumar3d4b1ef2016-01-29 15:57:26 -08001773 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 "%s: Scheduling work for AC %d, context %p",
1775 __func__, acType, pQosContext);
1776
1777 schedule_work(&pQosContext->wmmAcSetupImplicitQos);
1778
1779 /* caller will need to wait until the work takes place and
1780 * TSPEC negotiation completes
1781 */
1782 *pGranted = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301783 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784}
1785
1786/**
1787 * hdd_wmm_assoc() - Function which will handle the housekeeping
1788 * required by WMM when association takes place
1789 *
1790 * @pAdapter: [in] pointer to adapter context
1791 * @pRoamInfo: [in] pointer to roam information
1792 * @eBssType: [in] type of BSS
1793 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301794 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001796QDF_STATUS hdd_wmm_assoc(struct hdd_adapter *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001797 tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType)
1798{
1799 uint8_t uapsdMask;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301800 QDF_STATUS status;
Jeff Johnson1083b6e2017-08-28 11:35:22 -07001801 struct hdd_context *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001802
1803 /* when we associate we need to notify TL if it needs to
1804 * enable UAPSD for any access categories
1805 */
1806
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001807 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808
1809 if (pRoamInfo->fReassocReq) {
1810 /* when we reassociate we should continue to use
1811 * whatever parameters were previously established.
1812 * if we are reassociating due to a U-APSD change for
1813 * a particular Access Category, then the change will
1814 * be communicated to HDD via the QoS callback
1815 * associated with the given flow, and U-APSD
1816 * parameters will be updated there
1817 */
1818
Varun Reddy Yeturudd51e8d2017-05-14 14:51:13 -07001819 hdd_debug("Reassoc so no work, Exiting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301821 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 }
1823 /* get the negotiated UAPSD Mask */
1824 uapsdMask =
1825 pRoamInfo->u.pConnectedProfile->modifyProfileFields.uapsd_mask;
1826
Varun Reddy Yeturudd51e8d2017-05-14 14:51:13 -07001827 hdd_debug("U-APSD mask is 0x%02x", (int)uapsdMask);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001828
1829 if (uapsdMask & HDD_AC_VO) {
1830 status =
1831 sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))->
1832 pcds_context,
1833 (WLAN_HDD_GET_STATION_CTX_PTR
1834 (pAdapter))->conn_info.staId[0],
1835 SME_AC_VO, 7, 7,
1836 pHddCtx->config->InfraUapsdVoSrvIntv,
1837 pHddCtx->config->InfraUapsdVoSuspIntv,
Naveen Rawatd9dd4b32017-07-05 14:32:54 -07001838 SME_QOS_WMM_TS_DIR_BOTH, 1,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839 pAdapter->sessionId,
1840 pHddCtx->config->DelayedTriggerFrmInt);
1841
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301842 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 }
1844
1845 if (uapsdMask & HDD_AC_VI) {
1846 status =
1847 sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))->
1848 pcds_context,
1849 (WLAN_HDD_GET_STATION_CTX_PTR
1850 (pAdapter))->conn_info.staId[0],
1851 SME_AC_VI, 5, 5,
1852 pHddCtx->config->InfraUapsdViSrvIntv,
1853 pHddCtx->config->InfraUapsdViSuspIntv,
Naveen Rawatd9dd4b32017-07-05 14:32:54 -07001854 SME_QOS_WMM_TS_DIR_BOTH, 1,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001855 pAdapter->sessionId,
1856 pHddCtx->config->DelayedTriggerFrmInt);
1857
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301858 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859 }
1860
1861 if (uapsdMask & HDD_AC_BK) {
1862 status =
1863 sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))->
1864 pcds_context,
1865 (WLAN_HDD_GET_STATION_CTX_PTR
1866 (pAdapter))->conn_info.staId[0],
1867 SME_AC_BK, 2, 2,
1868 pHddCtx->config->InfraUapsdBkSrvIntv,
1869 pHddCtx->config->InfraUapsdBkSuspIntv,
Naveen Rawatd9dd4b32017-07-05 14:32:54 -07001870 SME_QOS_WMM_TS_DIR_BOTH, 1,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871 pAdapter->sessionId,
1872 pHddCtx->config->DelayedTriggerFrmInt);
1873
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301874 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 }
1876
1877 if (uapsdMask & HDD_AC_BE) {
1878 status =
1879 sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))->
1880 pcds_context,
1881 (WLAN_HDD_GET_STATION_CTX_PTR
1882 (pAdapter))->conn_info.staId[0],
1883 SME_AC_BE, 3, 3,
1884 pHddCtx->config->InfraUapsdBeSrvIntv,
1885 pHddCtx->config->InfraUapsdBeSuspIntv,
Naveen Rawatd9dd4b32017-07-05 14:32:54 -07001886 SME_QOS_WMM_TS_DIR_BOTH, 1,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 pAdapter->sessionId,
1888 pHddCtx->config->DelayedTriggerFrmInt);
1889
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301890 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 }
1892
1893 status = sme_update_dsc_pto_up_mapping(pHddCtx->hHal,
1894 pAdapter->hddWmmDscpToUpMap,
1895 pAdapter->sessionId);
1896
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001897 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 hdd_wmm_init(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001900 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301902 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903}
1904
1905static const uint8_t acm_mask_bit[WLAN_MAX_AC] = {
1906 0x4, /* SME_AC_BK */
1907 0x8, /* SME_AC_BE */
1908 0x2, /* SME_AC_VI */
1909 0x1 /* SME_AC_VO */
1910};
1911
1912/**
1913 * hdd_wmm_connect() - Function which will handle the housekeeping
1914 * required by WMM when a connection is established
1915 *
1916 * @pAdapter : [in] pointer to adapter context
1917 * @pRoamInfo: [in] pointer to roam information
1918 * @eBssType : [in] type of BSS
1919 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301920 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07001922QDF_STATUS hdd_wmm_connect(struct hdd_adapter *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType)
1924{
1925 int ac;
1926 bool qap;
1927 bool qosConnection;
1928 uint8_t acmMask;
1929
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001930 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931
1932 if ((eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType) &&
1933 pRoamInfo && pRoamInfo->u.pConnectedProfile) {
1934 qap = pRoamInfo->u.pConnectedProfile->qap;
1935 qosConnection = pRoamInfo->u.pConnectedProfile->qosConnection;
1936 acmMask = pRoamInfo->u.pConnectedProfile->acm_mask;
1937 } else {
1938 qap = true;
1939 qosConnection = true;
1940 acmMask = 0x0;
1941 }
1942
Varun Reddy Yeturudd51e8d2017-05-14 14:51:13 -07001943 hdd_debug("qap is %d, qosConnection is %d, acmMask is 0x%x",
Jeff Johnson5ae20e92016-08-19 13:51:48 -07001944 qap, qosConnection, acmMask);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945
1946 pAdapter->hddWmmStatus.wmmQap = qap;
1947 pAdapter->hddWmmStatus.wmmQosConnection = qosConnection;
1948
1949 for (ac = 0; ac < WLAN_MAX_AC; ac++) {
1950 if (qap && qosConnection && (acmMask & acm_mask_bit[ac])) {
Varun Reddy Yeturudd51e8d2017-05-14 14:51:13 -07001951 hdd_debug("ac %d on", ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952
1953 /* admission is required */
1954 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1955 wmmAcAccessRequired = true;
1956 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1957 wmmAcAccessAllowed = false;
1958 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1959 wmmAcAccessGranted = false;
1960 /* after reassoc if we have valid tspec, allow access */
1961 if (pAdapter->hddWmmStatus.wmmAcStatus[ac].
1962 wmmAcTspecValid
1963 && (pAdapter->hddWmmStatus.wmmAcStatus[ac].
1964 wmmAcTspecInfo.ts_info.direction !=
1965 SME_QOS_WMM_TS_DIR_DOWNLINK)) {
1966 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1967 wmmAcAccessAllowed = true;
1968 }
yeshwanth sriram guntukaa1ba9a22017-02-28 16:17:32 +05301969 if (!pRoamInfo->fReassocReq &&
1970 !sme_neighbor_roam_is11r_assoc(
1971 WLAN_HDD_GET_HAL_CTX(pAdapter),
1972 pAdapter->sessionId) &&
1973 !sme_roam_is_ese_assoc(pRoamInfo)) {
1974 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1975 wmmAcTspecValid = false;
1976 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1977 wmmAcAccessAllowed = false;
1978 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 } else {
Varun Reddy Yeturudd51e8d2017-05-14 14:51:13 -07001980 hdd_debug("ac %d off", ac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 /* admission is not required so access is allowed */
1982 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1983 wmmAcAccessRequired = false;
1984 pAdapter->hddWmmStatus.wmmAcStatus[ac].
1985 wmmAcAccessAllowed = true;
1986 }
1987
1988 }
1989
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07001990 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301992 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993}
1994
1995/**
1996 * hdd_wmm_get_uapsd_mask() - Function which will calculate the
1997 * initial value of the UAPSD mask based upon the device configuration
1998 *
1999 * @pAdapter : [in] pointer to adapter context
2000 * @pUapsdMask: [out] pointer to where the UAPSD Mask is to be stored
2001 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302002 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07002004QDF_STATUS hdd_wmm_get_uapsd_mask(struct hdd_adapter *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 uint8_t *pUapsdMask)
2006{
2007 uint8_t uapsdMask;
2008
2009 if (HDD_WMM_USER_MODE_NO_QOS ==
2010 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
2011 /* no QOS then no UAPSD */
2012 uapsdMask = 0;
2013 } else {
2014 /* start with the default mask */
2015 uapsdMask = (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
2016
2017 /* disable UAPSD for any ACs with a 0 Service Interval */
2018 if ((WLAN_HDD_GET_CTX(pAdapter))->config->
2019 InfraUapsdVoSrvIntv == 0) {
2020 uapsdMask &= ~HDD_AC_VO;
2021 }
2022
2023 if ((WLAN_HDD_GET_CTX(pAdapter))->config->
2024 InfraUapsdViSrvIntv == 0) {
2025 uapsdMask &= ~HDD_AC_VI;
2026 }
2027
2028 if ((WLAN_HDD_GET_CTX(pAdapter))->config->
2029 InfraUapsdBkSrvIntv == 0) {
2030 uapsdMask &= ~HDD_AC_BK;
2031 }
2032
2033 if ((WLAN_HDD_GET_CTX(pAdapter))->config->
2034 InfraUapsdBeSrvIntv == 0) {
2035 uapsdMask &= ~HDD_AC_BE;
2036 }
2037 }
2038
2039 /* return calculated mask */
2040 *pUapsdMask = uapsdMask;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302041 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042}
2043
2044/**
2045 * hdd_wmm_is_active() - Function which will determine if WMM is
2046 * active on the current connection
2047 *
2048 * @pAdapter: [in] pointer to adapter context
2049 *
2050 * Return: true if WMM is enabled, false if WMM is not enabled
2051 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07002052bool hdd_wmm_is_active(struct hdd_adapter *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053{
2054 if ((!pAdapter->hddWmmStatus.wmmQosConnection) ||
2055 (!pAdapter->hddWmmStatus.wmmQap)) {
2056 return false;
2057 } else {
2058 return true;
2059 }
2060}
2061
Kabilan Kannanf56f9d52017-04-05 03:31:34 -07002062bool hdd_wmm_is_acm_allowed(struct wlan_objmgr_vdev **vdev)
2063{
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07002064 struct hdd_adapter *adapter;
Kabilan Kannanf56f9d52017-04-05 03:31:34 -07002065 struct hdd_wmm_ac_status *wmm_ac_status;
2066
2067
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07002068 adapter = container_of(vdev, struct hdd_adapter, hdd_vdev);
Kabilan Kannanf56f9d52017-04-05 03:31:34 -07002069 if (NULL == adapter) {
2070 hdd_err("failed, hdd adapter is NULL");
2071 return false;
2072 }
2073 wmm_ac_status = adapter->hddWmmStatus.wmmAcStatus;
2074
2075 if (hdd_wmm_is_active(adapter) &&
2076 !(wmm_ac_status[OL_TX_WMM_AC_VI].wmmAcAccessAllowed))
2077 return false;
2078 return true;
2079}
2080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002081/**
2082 * hdd_wmm_addts() - Function which will add a traffic spec at the
2083 * request of an application
2084 *
2085 * @pAdapter : [in] pointer to adapter context
2086 * @handle : [in] handle to uniquely identify a TS
2087 * @pTspec : [in] pointer to the traffic spec
2088 *
2089 * Return: HDD_WLAN_WMM_STATUS_*
2090 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07002091hdd_wlan_wmm_status_e hdd_wmm_addts(struct hdd_adapter *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 uint32_t handle,
Abhishek Singh12be60f2017-08-11 13:52:42 +05302093 struct sme_qos_wmmtspecinfo *pTspec)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07002095 struct hdd_wmm_qos_context *pQosContext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002096 hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS;
2097#ifndef WLAN_MDM_CODE_REDUCTION_OPT
Abhishek Singh12be60f2017-08-11 13:52:42 +05302098 enum sme_qos_statustype smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099#endif
2100 bool found = false;
2101
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07002102 hdd_debug("Entered with handle 0x%x", handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103
2104 /* see if a context already exists with the given handle */
2105 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2106 list_for_each_entry(pQosContext,
2107 &pAdapter->hddWmmStatus.wmmContextList, node) {
2108 if (pQosContext->handle == handle) {
2109 found = true;
2110 break;
2111 }
2112 }
2113 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2114 if (found) {
2115 /* record with that handle already exists */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002116 hdd_err("Record already exists with handle 0x%x", handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117
2118 /* Application is trying to modify some of the Tspec
2119 * params. Allow it
2120 */
2121 smeStatus = sme_qos_modify_req(WLAN_HDD_GET_HAL_CTX(pAdapter),
2122 pTspec, pQosContext->qosFlowId);
2123
2124 /* need to check the return value and act appropriately */
2125 switch (smeStatus) {
2126 case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
2127 status = HDD_WLAN_WMM_STATUS_MODIFY_PENDING;
2128 break;
2129 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
2130 status =
2131 HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
2132 break;
2133 case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
2134 status =
2135 HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
2136 break;
2137 case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
2138 status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
2139 break;
2140 case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
2141 status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
2142 break;
2143 case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
2144 status = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
2145 break;
2146 default:
2147 /* we didn't get back one of the
2148 * SME_QOS_STATUS_MODIFY_* status codes
2149 */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002150 hdd_err("unexpected SME Status=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002151 smeStatus);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302152 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002153 return HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
2154 }
2155
2156 /* we were successful, save the status */
2157 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2158 if (pQosContext->magic == HDD_WMM_CTX_MAGIC)
2159 pQosContext->lastStatus = status;
2160 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2161
2162 return status;
2163 }
2164
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -07002165 pQosContext = qdf_mem_malloc(sizeof(*pQosContext));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166 if (NULL == pQosContext) {
2167 /* no memory for QoS context. Nothing we can do */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002168 hdd_err("Unable to allocate QoS context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002169 return HDD_WLAN_WMM_STATUS_INTERNAL_FAILURE;
2170 }
2171 /* we assume the tspec has already been validated by the caller */
2172
2173 pQosContext->handle = handle;
2174 if (pTspec->ts_info.up < HDD_WMM_UP_TO_AC_MAP_SIZE)
2175 pQosContext->acType = hdd_wmm_up_to_ac_map[pTspec->ts_info.up];
2176 else {
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002177 hdd_err("ts_info.up (%d) larger than max value (%d), use default acType (%d)",
2178 pTspec->ts_info.up,
2179 HDD_WMM_UP_TO_AC_MAP_SIZE - 1, hdd_wmm_up_to_ac_map[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002180 pQosContext->acType = hdd_wmm_up_to_ac_map[0];
2181 }
2182 pQosContext->pAdapter = pAdapter;
2183 pQosContext->qosFlowId = 0;
2184 pQosContext->magic = HDD_WMM_CTX_MAGIC;
Jeff Johnson962336e2016-10-27 08:05:43 -07002185 pQosContext->is_inactivity_timer_running = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07002187 hdd_debug("Setting up QoS, context %p", pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188
2189 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2190 list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
2191 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2192
2193#ifndef WLAN_MDM_CODE_REDUCTION_OPT
2194 smeStatus = sme_qos_setup_req(WLAN_HDD_GET_HAL_CTX(pAdapter),
2195 pAdapter->sessionId,
2196 pTspec,
2197 hdd_wmm_sme_callback,
2198 pQosContext,
2199 pTspec->ts_info.up,
2200 &pQosContext->qosFlowId);
2201
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07002202 hdd_debug("sme_qos_setup_req returned %d flowid %d",
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002203 smeStatus, pQosContext->qosFlowId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204
2205 /* need to check the return value and act appropriately */
2206 switch (smeStatus) {
2207 case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
2208 status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
2209 break;
2210 case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
2211 status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
2212 break;
2213 case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
2214 status =
2215 HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
2216 break;
2217 case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
2218 status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
2219 break;
2220 case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
2221 hdd_wmm_free_context(pQosContext);
2222 return HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
2223 case SME_QOS_STATUS_SETUP_FAILURE_RSP:
2224 /* we can't tell the difference between when a request
2225 * fails because AP rejected it versus when SME
2226 * encounterd an internal error
2227 */
2228 hdd_wmm_free_context(pQosContext);
2229 return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
2230 case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
2231 hdd_wmm_free_context(pQosContext);
2232 return HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
2233 default:
2234 /* we didn't get back one of the
2235 * SME_QOS_STATUS_SETUP_* status codes
2236 */
2237 hdd_wmm_free_context(pQosContext);
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002238 hdd_err("unexpected SME Status=%d", smeStatus);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302239 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240 return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
2241 }
2242#endif
2243
2244 /* we were successful, save the status */
2245 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2246 if (pQosContext->magic == HDD_WMM_CTX_MAGIC)
2247 pQosContext->lastStatus = status;
2248 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2249
2250 return status;
2251}
2252
2253/**
2254 * hdd_wmm_delts() - Function which will delete a traffic spec at the
2255 * request of an application
2256 *
2257 * @pAdapter: [in] pointer to adapter context
2258 * @handle: [in] handle to uniquely identify a TS
2259 *
2260 * Return: HDD_WLAN_WMM_STATUS_*
2261 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07002262hdd_wlan_wmm_status_e hdd_wmm_delts(struct hdd_adapter *pAdapter, uint32_t handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002263{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07002264 struct hdd_wmm_qos_context *pQosContext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002265 bool found = false;
2266 sme_ac_enum_type acType = 0;
2267 uint32_t qosFlowId = 0;
2268 hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS;
2269#ifndef WLAN_MDM_CODE_REDUCTION_OPT
Abhishek Singh12be60f2017-08-11 13:52:42 +05302270 enum sme_qos_statustype smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002271#endif
2272
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07002273 hdd_debug("Entered with handle 0x%x", handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002274
2275 /* locate the context with the given handle */
2276 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2277 list_for_each_entry(pQosContext,
2278 &pAdapter->hddWmmStatus.wmmContextList, node) {
2279 if (pQosContext->handle == handle) {
2280 found = true;
2281 acType = pQosContext->acType;
2282 qosFlowId = pQosContext->qosFlowId;
2283 break;
2284 }
2285 }
2286 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2287
2288 if (false == found) {
2289 /* we didn't find the handle */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002290 hdd_info("handle 0x%x not found", handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291 return HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
2292 }
2293
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002294 hdd_info("found handle 0x%x, flow %d, AC %d, context %p",
2295 handle, qosFlowId, acType, pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002296
2297#ifndef WLAN_MDM_CODE_REDUCTION_OPT
2298 smeStatus =
Vidyullatha Kanchanapally5d0a83e2016-05-24 16:20:53 +05302299 sme_qos_release_req(WLAN_HDD_GET_HAL_CTX(pAdapter),
2300 pAdapter->sessionId, qosFlowId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002302 hdd_info("SME flow %d released, SME status %d", qosFlowId, smeStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303
2304 switch (smeStatus) {
2305 case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
2306 /* this flow is the only one on that AC, so go ahead
2307 * and update our TSPEC state for the AC
2308 */
2309 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcTspecValid =
2310 false;
Sreelakshmi Konamki9d6b75d2016-02-10 12:17:23 +05302311 pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed =
2312 false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313
2314 /* need to tell TL to stop trigger timer, etc */
2315 hdd_wmm_disable_tl_uapsd(pQosContext);
2316
2317#ifdef FEATURE_WLAN_ESE
2318 /* disable the inactivity timer */
2319 hdd_wmm_disable_inactivity_timer(pQosContext);
2320#endif
2321 /* we are done with this context */
2322 hdd_wmm_free_context(pQosContext);
2323
2324 /* SME must not fire any more callbacks for this flow
2325 * since the context is no longer valid
2326 */
2327
2328 return HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
2329
2330 case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
2331 /* do nothing as we will get a response from SME */
2332 status = HDD_WLAN_WMM_STATUS_RELEASE_PENDING;
2333 break;
2334
2335 case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
2336 /* nothing we can do with the existing flow except leave it */
2337 status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
2338 break;
2339
2340 case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
2341 /* nothing we can do with the existing flow except leave it */
2342 status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
Yingying Tang9fad0ca2016-10-20 23:12:36 +08002343 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344
2345 default:
2346 /* we didn't get back one of the
2347 * SME_QOS_STATUS_RELEASE_* status codes
2348 */
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002349 hdd_err("unexpected SME Status=%d", smeStatus);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302350 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
2352 }
2353
2354#endif
2355 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2356 if (pQosContext->magic == HDD_WMM_CTX_MAGIC)
2357 pQosContext->lastStatus = status;
2358 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2359
2360 return status;
2361}
2362
2363/**
2364 * hdd_wmm_checkts() - Function which will return the status of a traffic
2365 * spec at the request of an application
2366 *
2367 * @pAdapter: [in] pointer to adapter context
2368 * @handle: [in] handle to uniquely identify a TS
2369 *
2370 * Return: HDD_WLAN_WMM_STATUS_*
2371 */
Jeff Johnson5b8b67d2017-08-29 14:16:53 -07002372hdd_wlan_wmm_status_e hdd_wmm_checkts(struct hdd_adapter *pAdapter, uint32_t handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373{
Srinivas Girigowdaea32d6a2017-03-25 00:03:12 -07002374 struct hdd_wmm_qos_context *pQosContext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_LOST;
2376
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07002377 hdd_debug("Entered with handle 0x%x", handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378
2379 /* locate the context with the given handle */
2380 mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
2381 list_for_each_entry(pQosContext,
2382 &pAdapter->hddWmmStatus.wmmContextList, node) {
2383 if (pQosContext->handle == handle) {
Jeff Johnson5ae20e92016-08-19 13:51:48 -07002384 hdd_info("found handle 0x%x, context %p",
2385 handle, pQosContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386
2387 status = pQosContext->lastStatus;
2388 break;
2389 }
2390 }
2391 mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
2392 return status;
2393}