blob: 37411140453a55f5ba60f54aadebe0f900b01d86 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Jeff Johnson295189b2012-06-20 16:38:30 -070026 */
27
28/**===========================================================================
29
30 \file wlan_hdd_softap_tx_rx.c
31
32 \brief Linux HDD Tx/RX APIs
Kiet Lamaa8e15a2014-02-11 23:30:06 -080033 Copyright 2008 (c) Qualcomm, Incorporated.
34 All Rights Reserved.
35 Qualcomm Confidential and Proprietary.
Jeff Johnson295189b2012-06-20 16:38:30 -070036
37 ==========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070038
39/*---------------------------------------------------------------------------
40 Include files
41 -------------------------------------------------------------------------*/
42#include <linux/semaphore.h>
43#include <wlan_hdd_tx_rx.h>
44#include <wlan_hdd_softap_tx_rx.h>
45#include <wlan_hdd_dp_utils.h>
46#include <wlan_qct_tl.h>
47#include <linux/netdevice.h>
48#include <linux/skbuff.h>
49#include <linux/etherdevice.h>
50//#include <vos_list.h>
51#include <vos_types.h>
52#include <aniGlobal.h>
53#include <halTypes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070054#include <net/ieee80211_radiotap.h>
Mihir Shetef3473692014-06-27 15:13:20 +053055#include <linux/ratelimit.h>
56#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
57#include <soc/qcom/subsystem_restart.h>
58#else
59#include <mach/subsystem_restart.h>
60#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070061
62
63/*---------------------------------------------------------------------------
64 Preprocessor definitions and constants
65 -------------------------------------------------------------------------*/
66
67/*---------------------------------------------------------------------------
68 Type declarations
69 -------------------------------------------------------------------------*/
70
71/*---------------------------------------------------------------------------
72 Function definitions and documenation
73 -------------------------------------------------------------------------*/
74#if 0
75static void hdd_softap_dump_sk_buff(struct sk_buff * skb)
76{
c_hpothu6d1d2a32014-03-18 20:17:03 +053077 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
78 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
79 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
80 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
81 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
82 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
83 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -070084
c_hpothu6d1d2a32014-03-18 20:17:03 +053085 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -070086 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
87 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu6d1d2a32014-03-18 20:17:03 +053088 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -070089 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
90 skb->data[13], skb->data[14], skb->data[15]);
91}
92#endif
Leo Chang64d68bc2013-06-04 15:40:52 -070093
94extern void hdd_set_wlan_suspend_mode(bool suspend);
95
Mihir Shetef3473692014-06-27 15:13:20 +053096#define HDD_SAP_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
97#define HDD_SAP_TX_TIMEOUT_RATELIMIT_BURST 1
98#define HDD_SAP_TX_STALL_SSR_THRESHOLD 5
99
100static DEFINE_RATELIMIT_STATE(hdd_softap_tx_timeout_rs, \
101 HDD_SAP_TX_TIMEOUT_RATELIMIT_INTERVAL, \
102 HDD_SAP_TX_TIMEOUT_RATELIMIT_BURST);
103
Leo Chang64d68bc2013-06-04 15:40:52 -0700104/**============================================================================
105 @brief hdd_softap_traffic_monitor_timeout_handler() -
106 SAP/P2P GO traffin monitor timeout handler function
107 If no traffic during programmed time, trigger suspand mode
108
109 @param pUsrData : [in] pointer to hdd context
110 @return : NONE
111 ===========================================================================*/
112void hdd_softap_traffic_monitor_timeout_handler( void *pUsrData )
113{
114 hdd_context_t *pHddCtx = (hdd_context_t *)pUsrData;
115 v_TIME_t currentTS;
116
117 if (NULL == pHddCtx)
118 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530119 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Leo Chang64d68bc2013-06-04 15:40:52 -0700120 "%s: Invalid user data, context", __func__);
121 return;
122 }
123
124 currentTS = vos_timer_get_system_time();
125 if (pHddCtx->cfg_ini->trafficIdleTimeout <
126 (currentTS - pHddCtx->traffic_monitor.lastFrameTs))
127 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530128 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530129 "%s: No Data Activity calling Wlan Suspend", __func__ );
Leo Chang64d68bc2013-06-04 15:40:52 -0700130 hdd_set_wlan_suspend_mode(1);
131 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0);
132 }
133 else
134 {
135 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
136 pHddCtx->cfg_ini->trafficIdleTimeout);
137 }
138
139 return;
140}
141
Kiet Lambcf38522013-10-26 18:28:27 +0530142VOS_STATUS hdd_start_trafficMonitor( hdd_adapter_t *pAdapter )
143{
144
145 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
146 VOS_STATUS status = VOS_STATUS_SUCCESS;
147
148 status = wlan_hdd_validate_context(pHddCtx);
149
150 if (0 != status)
151 {
152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
153 "%s: HDD context is not valid", __func__);
154 return status;
155 }
156
157 if ((pHddCtx->cfg_ini->enableTrafficMonitor) &&
158 (!pHddCtx->traffic_monitor.isInitialized))
159 {
160 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
161 vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer,
162 VOS_TIMER_TYPE_SW,
163 hdd_softap_traffic_monitor_timeout_handler,
164 pHddCtx);
165 vos_lock_init(&pHddCtx->traffic_monitor.trafficLock);
166 pHddCtx->traffic_monitor.isInitialized = 1;
167 pHddCtx->traffic_monitor.lastFrameTs = 0;
168 /* Start traffic monitor timer here
169 * If no AP assoc, immediatly go into suspend */
c_hpothu6d1d2a32014-03-18 20:17:03 +0530170 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530171 "%s Start Traffic Monitor Timer", __func__);
172 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
173 pHddCtx->cfg_ini->trafficIdleTimeout);
174 }
175 else
176 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530177 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530178 "%s Traffic Monitor is not Enable in ini file", __func__);
179 }
180 return status;
181}
182
183VOS_STATUS hdd_stop_trafficMonitor( hdd_adapter_t *pAdapter )
184{
185 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
186 VOS_STATUS status = VOS_STATUS_SUCCESS;
187
188 status = wlan_hdd_validate_context(pHddCtx);
189
Kiet Lamae69d7a2013-11-08 14:38:04 +0530190 if (-ENODEV == status)
Kiet Lambcf38522013-10-26 18:28:27 +0530191 {
192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
193 "%s: HDD context is not valid", __func__);
194 return status;
195 }
196
197 if (pHddCtx->traffic_monitor.isInitialized)
198 {
199 if (VOS_TIMER_STATE_STOPPED !=
200 vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer))
201 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530202 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530203 "%s Stop Traffic Monitor Timer", __func__);
204 vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer);
205 }
c_hpothu6d1d2a32014-03-18 20:17:03 +0530206 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530207 "%s Destroy Traffic Monitor Timer", __func__);
208 vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer);
209 vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock);
210 pHddCtx->traffic_monitor.isInitialized = 0;
211 }
Kiet Lamae69d7a2013-11-08 14:38:04 +0530212 return VOS_STATUS_SUCCESS;
Kiet Lambcf38522013-10-26 18:28:27 +0530213}
214
Jeff Johnson295189b2012-06-20 16:38:30 -0700215/**============================================================================
216 @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
217
218 @param pAdapter : [in] pointer to adapter context
219 @return : VOS_STATUS_E_FAILURE if any errors encountered
220 : VOS_STATUS_SUCCESS otherwise
221 ===========================================================================*/
222static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter )
223{
224 VOS_STATUS status = VOS_STATUS_SUCCESS;
225 v_SINT_t i = -1;
226 v_U8_t STAId = 0;
227 hdd_list_node_t *anchor = NULL;
228 skb_list_node_t *pktNode = NULL;
229 struct sk_buff *skb = NULL;
230
231 spin_lock_bh( &pAdapter->staInfo_lock );
232 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
233 {
234 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
235 {
236 continue;
237 }
238
239 for (i = 0; i < NUM_TX_QUEUES; i ++)
240 {
241 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
242 while (true)
243 {
244 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
245
246 if (VOS_STATUS_E_EMPTY != status)
247 {
248 //If success then we got a valid packet from some AC
249 pktNode = list_entry(anchor, skb_list_node_t, anchor);
250 skb = pktNode->skb;
251 ++pAdapter->stats.tx_dropped;
252 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
253 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
254 kfree_skb(skb);
255 continue;
256 }
257
258 //current list is empty
259 break;
260 }
261 pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE;
262 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
263 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530264 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700265 }
266
267 spin_unlock_bh( &pAdapter->staInfo_lock );
268
269 return status;
270}
271
272/**============================================================================
273 @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
274 transmitting packets. There are 2 versions of this function. One that uses
275 locked queue and other that uses lockless queues. Both have been retained to
276 do some performance testing
277
278 @param skb : [in] pointer to OS packet (sk_buff)
279 @param dev : [in] pointer to Libra network device
280
281 @return : NET_XMIT_DROP if packets are dropped
282 : NET_XMIT_SUCCESS if packet is enqueued succesfully
283 ===========================================================================*/
284int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
285{
286 VOS_STATUS status;
287 WLANTL_ACEnumType ac = WLANTL_AC_BE;
288 sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
289 skb_list_node_t *pktNode = NULL;
290 v_SIZE_t pktListSize = 0;
291 v_BOOL_t txSuspended = VOS_FALSE;
292 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
293 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530294 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 vos_list_node_t *anchor = NULL;
296 v_U8_t STAId = WLAN_MAX_STA_COUNT;
297 //Extract the destination address from ethernet frame
298 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
299 int os_status = NETDEV_TX_OK;
300
301 pDestMacAddress = (v_MACADDR_t*)skb->data;
302
303 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
304
c_hpothu6d1d2a32014-03-18 20:17:03 +0530305 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700306 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700307
308 spin_lock_bh( &pAdapter->staInfo_lock );
309 if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
310 {
311 //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
312 //ID used for BC/MC traffic. The station id is registered to TL as well.
313 STAId = pHddApCtx->uBCStaId;
314
315 /* Setting priority for broadcast packets which doesn't go to select_queue function */
316 skb->priority = SME_QOS_WMM_UP_BE;
317 skb->queue_mapping = HDD_LINUX_AC_BE;
318
c_hpothu6d1d2a32014-03-18 20:17:03 +0530319 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800320 "%s: BC/MC packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 }
322 else
323 {
324 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
325 if (STAId == HDD_WLAN_INVALID_STA_ID)
326 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530327 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700328 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700329 ++pAdapter->stats.tx_dropped;
330 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
331 kfree_skb(skb);
332 goto xmit_done;
333 }
334 else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
335 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530336 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
337 "%s: STA %d is unregistered", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 ++pAdapter->stats.tx_dropped;
339 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
340 kfree_skb(skb);
341 goto xmit_done;
342 }
343
344 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
345 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
346 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530347 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700348 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700349 ++pAdapter->stats.tx_dropped;
350 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
351 kfree_skb(skb);
352 goto xmit_done;
353 }
354 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
355 {
356 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
357 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530358 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700359 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700360 ++pAdapter->stats.tx_dropped;
361 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
362 kfree_skb(skb);
363 goto xmit_done;
364 }
365 }
366 }
367
368 //Get TL AC corresponding to Qdisc queue index/AC.
369 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
370 //user priority from IP header, which is already extracted and set from
371 //select_queue call back function
372 up = skb->priority;
373 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
374
c_hpothu6d1d2a32014-03-18 20:17:03 +0530375 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700376 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700377
Dino Mycled9b7cc12014-09-04 18:43:07 +0530378 if ( ( NULL != pHddCtx ) && pHddCtx->cfg_ini->enableDhcpDebug )
379 {
380 hdd_dump_dhcp_pkt(skb, TX_PATH);
381 }
382
Jeff Johnson295189b2012-06-20 16:38:30 -0700383 // If the memory differentiation mode is enabled, the memory limit of each queue will be
384 // checked. Over-limit packets will be dropped.
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700385 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700386 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
387 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
388 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530389 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800390 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700391 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
392 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
393 txSuspended = VOS_TRUE;
394 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530395
396 /* If 3/4th of the max queue size is used then enable the flag.
397 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
398 if (WLANTL_AC_BE == ac)
399 {
400 if (pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
401 {
402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
403 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
404 pAdapter->aStaInfo[STAId].vosLowResource = VOS_TRUE;
405 }
406 else
407 {
408 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
409 }
410 }
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700411 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700412
413 if (VOS_TRUE == txSuspended)
414 {
415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
416 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700417 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700418 os_status = NETDEV_TX_BUSY;
419 goto xmit_done;
420 }
421
422 //Use the skb->cb field to hold the list node information
423 pktNode = (skb_list_node_t *)&skb->cb;
424
425 //Stick the OS packet inside this node.
426 pktNode->skb = skb;
427
428 //Stick the User Priority inside this node
429 pktNode->userPriority = up;
430
431 INIT_LIST_HEAD(&pktNode->anchor);
432
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700433 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700434 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700435 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700436
437 if ( !VOS_IS_STATUS_SUCCESS( status ) )
438 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530439 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
440 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700441 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
442 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
443 ++pAdapter->stats.tx_dropped;
444 kfree_skb(skb);
445 goto xmit_done;
446 }
447
448 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
449 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Rashmi Ramannacbffcb12014-01-07 13:22:13 +0530450 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700451
452 if (1 == pktListSize)
453 {
454 //Let TL know we have a packet to send for this AC
455 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
456
457 if ( !VOS_IS_STATUS_SUCCESS( status ) )
458 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530459 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
460 "%s: Failed to signal TL for AC=%d STAId =%d",
461 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700462
463 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
464 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
465 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
466 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
467 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
468 ++pAdapter->stats.tx_dropped;
469 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
470 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
471 kfree_skb(skb);
472 goto xmit_done;
473 }
474 }
475 dev->trans_start = jiffies;
476
c_hpothu6d1d2a32014-03-18 20:17:03 +0530477 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
478 "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700479
480xmit_done:
481 spin_unlock_bh( &pAdapter->staInfo_lock );
482 return os_status;
483}
484
485/**============================================================================
486 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
487
488 @param skb : [in] pointer to packet (sk_buff)
489 @param dev : [in] pointer to Libra network device
490 @param STAId : [in] Station Id of Destination Station
491 @param up : [in] User Priority
492
493 @return : NET_XMIT_DROP if packets are dropped
494 : NET_XMIT_SUCCESS if packet is enqueued succesfully
495 ===========================================================================*/
496VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
497 struct net_device *dev,
498 v_U8_t STAId,
499 v_U8_t up)
500{
501 VOS_STATUS status = VOS_STATUS_SUCCESS;
502 skb_list_node_t *pktNode = NULL;
503 v_SIZE_t pktListSize = 0;
504 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
505 v_U8_t ac;
506 vos_list_node_t *anchor = NULL;
507
508 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
509
c_hpothu6d1d2a32014-03-18 20:17:03 +0530510 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700511 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700512
513 spin_lock_bh( &pAdapter->staInfo_lock );
514 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
515 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530516 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530517 "%s: STA %d is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700518 kfree_skb(skb);
519 status = VOS_STATUS_E_FAILURE;
520 goto xmit_end;
521 }
522
523 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
524 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
525 up = SME_QOS_WMM_UP_BE;
526
527 ac = hddWmmUpToAcMap[up];
528 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
c_hpothu6d1d2a32014-03-18 20:17:03 +0530529 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700530 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700531
532 skb->queue_mapping = hddLinuxUpToAcMap[up];
533
534 //Use the skb->cb field to hold the list node information
535 pktNode = (skb_list_node_t *)&skb->cb;
536
537 //Stick the OS packet inside this node.
538 pktNode->skb = skb;
539
540 //Stick the User Priority inside this node
541 pktNode->userPriority = up;
542
543 INIT_LIST_HEAD(&pktNode->anchor);
544
545 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
546 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
547 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
548 pktListSize >= pAdapter->aTxQueueLimit[ac])
549 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530550 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800551 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700552 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
553 * SUSPEND should be done based on Threshold. RESUME would be
554 * triggered in fetch cbk after recovery.
555 */
556 kfree_skb(skb);
557 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
558 status = VOS_STATUS_E_FAILURE;
559 goto xmit_end;
560 }
561 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
562 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
563
564 if ( !VOS_IS_STATUS_SUCCESS( status ) )
565 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530566 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
567 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700568 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
569 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
570 ++pAdapter->stats.tx_dropped;
571 kfree_skb(skb);
572 status = VOS_STATUS_E_FAILURE;
573 goto xmit_end;
574 }
575
576 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
577 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
578
579 if (1 == pktListSize)
580 {
581 //Let TL know we have a packet to send for this AC
c_hpothu6d1d2a32014-03-18 20:17:03 +0530582 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
583 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700584
585 if ( !VOS_IS_STATUS_SUCCESS( status ) )
586 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530587 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
588 "%s: Failed to signal TL for AC=%d STAId =%d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700589 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700590
591 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
592 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
593 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
594 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
595 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
596 ++pAdapter->stats.tx_dropped;
597 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
598 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
599 kfree_skb(skb);
600 status = VOS_STATUS_E_FAILURE;
601 goto xmit_end;
602 }
603 }
604
c_hpothu6d1d2a32014-03-18 20:17:03 +0530605 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700606
607xmit_end:
608 spin_unlock_bh( &pAdapter->staInfo_lock );
609 return status;
610}
611
612/**============================================================================
613 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
614 timeout during transmission. Since HDD simply enqueues packet
615 and returns control to OS right away, this would never be invoked
616
617 @param dev : [in] pointer to Libra network device
618 @return : None
619 ===========================================================================*/
620void hdd_softap_tx_timeout(struct net_device *dev)
621{
Mihir Shetef3473692014-06-27 15:13:20 +0530622 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
623 struct netdev_queue *txq;
624 int i = 0;
625
c_hpothu6d1d2a32014-03-18 20:17:03 +0530626 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700627 "%s: Transmission timeout occurred", __func__);
Mihir Shetef3473692014-06-27 15:13:20 +0530628
629 if ( NULL == pAdapter )
630 {
631 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
632 FL("pAdapter is NULL"));
633 VOS_ASSERT(0);
634 return;
635 }
636
637 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
638
639 for (i = 0; i < 8; i++)
640 {
641 txq = netdev_get_tx_queue(dev, i);
642 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
643 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
644 }
645
646 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
647 "carrier state: %d", netif_carrier_ok(dev));
648
649 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
650
651 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
652 HDD_SAP_TX_STALL_SSR_THRESHOLD)
653 {
654 // Driver could not recover, issue SSR
655 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
656 "%s: Cannot recover from Data stall Issue SSR",
657 __func__);
Mihir Shetefd62d9d2014-08-06 15:08:21 +0530658 WLANTL_FatalError();
Mihir Shetef3473692014-06-27 15:13:20 +0530659 return;
660 }
661
662 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
663 * every 5sec. The TL debug spits out a lot of information on the
664 * serial console, if it is called every time *hdd_tx_timeout* is
665 * called then we may get a watchdog bite on the Application
666 * processor, so ratelimit the TL debug logs.
667 */
668 if (__ratelimit(&hdd_softap_tx_timeout_rs))
669 {
670 hdd_wmm_tx_snapshot(pAdapter);
671 WLANTL_TLDebugMessage(VOS_TRUE);
672 }
673
Jeff Johnson295189b2012-06-20 16:38:30 -0700674}
675
676
677/**============================================================================
678 @brief hdd_softap_stats() - Function registered with the Linux OS for
679 device TX/RX statistic
680
681 @param dev : [in] pointer to Libra network device
682
683 @return : pointer to net_device_stats structure
684 ===========================================================================*/
685struct net_device_stats* hdd_softap_stats(struct net_device *dev)
686{
687 hdd_adapter_t* priv = netdev_priv(dev);
688 return &priv->stats;
689}
690
691
692/**============================================================================
693 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
694 modules in HDD
695
696 @param pAdapter : [in] pointer to adapter context
697 @return : VOS_STATUS_E_FAILURE if any errors encountered
698 : VOS_STATUS_SUCCESS otherwise
699 ===========================================================================*/
700VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
701{
702 VOS_STATUS status = VOS_STATUS_SUCCESS;
703 v_SINT_t i = -1;
704 v_SIZE_t size = 0;
705
706 v_U8_t STAId = 0;
707
708 v_U8_t pACWeights[] = {
709 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
710 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
711 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
712 HDD_SOFTAP_VO_WEIGHT_DEFAULT
713 };
Leo Chang64d68bc2013-06-04 15:40:52 -0700714
Jeff Johnson295189b2012-06-20 16:38:30 -0700715 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530716 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700717
718 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
719
720 while (++i != NUM_TX_QUEUES)
721 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
722
723 /* Initial HDD buffer control / flow control fields*/
724 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
725
726 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
727 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
728 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
729 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
730
731 spin_lock_init( &pAdapter->staInfo_lock );
732
733 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
734 {
735 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
736 for (i = 0; i < NUM_TX_QUEUES; i ++)
737 {
738 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
739 }
740 }
741
Yue Ma3ede6052013-08-29 00:33:26 -0700742 /* Update the AC weights suitable for SoftAP mode of operation */
743 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
744
Kiet Lambcf38522013-10-26 18:28:27 +0530745 if (VOS_STATUS_SUCCESS != hdd_start_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700746 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530747 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530748 "%s: failed to start Traffic Monito timer ", __func__ );
749 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700750 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700751 return status;
752}
753
754/**============================================================================
755 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
756 modules in HDD
757
758 @param pAdapter : [in] pointer to adapter context
759 @return : VOS_STATUS_E_FAILURE if any errors encountered
760 : VOS_STATUS_SUCCESS otherwise
761 ===========================================================================*/
762VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
763{
764 VOS_STATUS status = VOS_STATUS_SUCCESS;
Leo Chang64d68bc2013-06-04 15:40:52 -0700765
Kiet Lambcf38522013-10-26 18:28:27 +0530766 if (VOS_STATUS_SUCCESS != hdd_stop_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700767 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530768 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530769 "%s: Fail to Stop Traffic Monito timer", __func__ );
770 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700771 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700772
773 status = hdd_softap_flush_tx_queues(pAdapter);
774
775 return status;
776}
777
778/**============================================================================
779 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
780
781 @param pAdapter : [in] pointer to adapter context
782 @param STAId : [in] Station ID to deinit
783 @return : VOS_STATUS_E_FAILURE if any errors encountered
784 : VOS_STATUS_SUCCESS otherwise
785 ===========================================================================*/
786static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
787{
Jeff Johnson295189b2012-06-20 16:38:30 -0700788 v_U8_t i = -1;
789
790 hdd_list_node_t *anchor = NULL;
791
792 skb_list_node_t *pktNode = NULL;
793 struct sk_buff *skb = NULL;
794
795 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
796 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530797 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700798 }
799
800 for (i = 0; i < NUM_TX_QUEUES; i ++)
801 {
802 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
803 while (true)
804 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530805 if (VOS_STATUS_E_EMPTY !=
806 hdd_list_remove_front(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
807 &anchor))
Jeff Johnson295189b2012-06-20 16:38:30 -0700808 {
809 //If success then we got a valid packet from some AC
810 pktNode = list_entry(anchor, skb_list_node_t, anchor);
811 skb = pktNode->skb;
812 ++pAdapter->stats.tx_dropped;
813 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
814 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
815 kfree_skb(skb);
816 continue;
817 }
818
819 //current list is empty
820 break;
821 }
822 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
823 }
824
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530825 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700826}
827
828/**============================================================================
829 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
830 modules in HDD
831
832 @param pAdapter : [in] pointer to adapter context
833 @param STAId : [in] Station ID to deinit
834 @param pmacAddrSTA : [in] pointer to the MAC address of the station
835 @return : VOS_STATUS_E_FAILURE if any errors encountered
836 : VOS_STATUS_SUCCESS otherwise
837 ===========================================================================*/
838VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
839{
840 v_U8_t i = 0;
841 spin_lock_bh( &pAdapter->staInfo_lock );
842 if (pAdapter->aStaInfo[STAId].isUsed)
843 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530844 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
845 "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700846 spin_unlock_bh( &pAdapter->staInfo_lock );
847 return VOS_STATUS_E_FAILURE;
848 }
849
850 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
851 for (i = 0; i < NUM_TX_QUEUES; i ++)
852 {
853 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
854 }
855
856 pAdapter->aStaInfo[STAId].isUsed = TRUE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800857 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700858 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
859
860 spin_unlock_bh( &pAdapter->staInfo_lock );
861 return VOS_STATUS_SUCCESS;
862}
863
864/**============================================================================
865 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
866 modules in HDD
867
868 @param pAdapter : [in] pointer to adapter context
869 @param STAId : [in] Station ID to deinit
870 @return : VOS_STATUS_E_FAILURE if any errors encountered
871 : VOS_STATUS_SUCCESS otherwise
872 ===========================================================================*/
873VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
874{
875 VOS_STATUS status = VOS_STATUS_SUCCESS;
876 v_U8_t ac;
877 /**Track whether OS TX queue has been disabled.*/
878 v_BOOL_t txSuspended[NUM_TX_QUEUES];
879 v_U8_t tlAC;
880 hdd_hostapd_state_t *pHostapdState;
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700881 v_U8_t i;
Jeff Johnson295189b2012-06-20 16:38:30 -0700882
883 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
884
885 spin_lock_bh( &pAdapter->staInfo_lock );
886 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
887 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530888 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700889 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700890 spin_unlock_bh( &pAdapter->staInfo_lock );
891 return VOS_STATUS_E_FAILURE;
892 }
893
894 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
895
896 pAdapter->aStaInfo[STAId].isUsed = FALSE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800897 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700898
899 /* if this STA had any of its WMM TX queues suspended, then the
900 associated queue on the network interface was disabled. check
901 to see if that is the case, in which case we need to re-enable
902 the interface queue. but we only do this if the BSS is running
903 since, if the BSS is stopped, all of the interfaces have been
904 stopped and should not be re-enabled */
905
906 if (BSS_START == pHostapdState->bssState)
907 {
908 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
909 {
910 tlAC = hdd_QdiscAcToTlAC[ac];
911 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
912 }
913 }
914 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
915
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700916 /* re-init spin lock, since netdev can still open adapter until
917 * driver gets unloaded
918 */
919 for (i = 0; i < NUM_TX_QUEUES; i ++)
920 {
921 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
922 HDD_TX_QUEUE_MAX_LEN);
923 }
924
Jeff Johnson295189b2012-06-20 16:38:30 -0700925 if (BSS_START == pHostapdState->bssState)
926 {
927 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
928 {
929 if (txSuspended[ac])
930 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530931 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700932 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 netif_wake_subqueue(pAdapter->dev, ac);
934 }
935 }
936 }
937
938 spin_unlock_bh( &pAdapter->staInfo_lock );
939 return status;
940}
941
942/**============================================================================
943 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
944 modules in HDD
945
946 @param pAdapter : [in] pointer to adapter context
947 @return : VOS_STATUS_E_FAILURE if any errors encountered
948 : VOS_STATUS_SUCCESS otherwise
949 ===========================================================================*/
950VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
951{
952 return hdd_softap_flush_tx_queues(pAdapter);
953}
954
955/**============================================================================
956 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
957 to indicate that a packet has been transmitted across the bus
958 succesfully. OS packet resources can be released after this cbk.
959
960 @param vosContext : [in] pointer to VOS context
961 @param pVosPacket : [in] pointer to VOS packet (containing skb)
962 @param vosStatusIn : [in] status of the transmission
963
964 @return : VOS_STATUS_E_FAILURE if any errors encountered
965 : VOS_STATUS_SUCCESS otherwise
966 ===========================================================================*/
967VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
968 vos_pkt_t *pVosPacket,
969 VOS_STATUS vosStatusIn )
970{
971 VOS_STATUS status = VOS_STATUS_SUCCESS;
972 hdd_adapter_t *pAdapter = NULL;
973 void* pOsPkt = NULL;
974
975 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
976 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530977 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
978 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700979 return VOS_STATUS_E_FAILURE;
980 }
981
982 //Return the skb to the OS
983 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Rajesh Chauhana0516c62014-01-30 16:11:18 -0800984 if ((!VOS_IS_STATUS_SUCCESS(status)) || (!pOsPkt))
Jeff Johnson295189b2012-06-20 16:38:30 -0700985 {
986 //This is bad but still try to free the VOSS resources if we can
c_hpothu6d1d2a32014-03-18 20:17:03 +0530987 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
988 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700989 vos_pkt_return_packet( pVosPacket );
990 return VOS_STATUS_E_FAILURE;
991 }
992
993 //Get the Adapter context.
994 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
995 if(pAdapter == NULL)
996 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530997 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
998 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700999 }
1000 else
1001 {
1002 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1003 }
1004
1005 kfree_skb((struct sk_buff *)pOsPkt);
1006
1007 //Return the VOS packet resources.
1008 status = vos_pkt_return_packet( pVosPacket );
1009 if(!VOS_IS_STATUS_SUCCESS( status ))
1010 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301011 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1012 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001013 }
1014
1015 return status;
1016}
1017
1018
1019/**============================================================================
1020 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
1021 fetch a packet for transmission.
1022
1023 @param vosContext : [in] pointer to VOS context
1024 @param staId : [in] Station for which TL is requesting a pkt
1025 @param ac : [in] access category requested by TL
1026 @param pVosPacket : [out] pointer to VOS packet packet pointer
1027 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1028
1029 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1030 : VOS_STATUS_E_FAILURE if any errors encountered
1031 : VOS_STATUS_SUCCESS otherwise
1032 ===========================================================================*/
1033VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1034 v_U8_t *pStaId,
1035 WLANTL_ACEnumType ac,
1036 vos_pkt_t **ppVosPacket,
1037 WLANTL_MetaInfoType *pPktMetaInfo )
1038{
1039 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1040 hdd_adapter_t *pAdapter = NULL;
1041 hdd_list_node_t *anchor = NULL;
1042 skb_list_node_t *pktNode = NULL;
1043 struct sk_buff *skb = NULL;
1044 vos_pkt_t *pVosPacket = NULL;
1045 v_MACADDR_t* pDestMacAddress = NULL;
1046 v_TIME_t timestamp;
1047 v_SIZE_t size = 0;
1048 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1049 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001050 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001051
1052 //Sanity check on inputs
1053 if ( ( NULL == vosContext ) ||
1054 ( NULL == pStaId ) ||
1055 ( NULL == ppVosPacket ) ||
1056 ( NULL == pPktMetaInfo ) )
1057 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301058 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1059 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001060 return VOS_STATUS_E_FAILURE;
1061 }
1062
1063 //Get the HDD context.
1064 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1065 if ( NULL == pHddCtx )
1066 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301067 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1068 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001069 return VOS_STATUS_E_FAILURE;
1070 }
1071
Jeff Johnsonb156c922013-12-05 17:19:46 -08001072 STAId = *pStaId;
1073 if (STAId >= WLAN_MAX_STA_COUNT)
1074 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301075 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001076 "%s: Invalid STAId %d passed by TL", __func__, STAId);
1077 return VOS_STATUS_E_FAILURE;
1078 }
1079
1080 pAdapter = pHddCtx->sta_to_adapter[STAId];
1081 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 {
1083 VOS_ASSERT(0);
1084 return VOS_STATUS_E_FAILURE;
1085 }
1086
Jeff Johnsonb156c922013-12-05 17:19:46 -08001087 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
1088 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301089 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001090 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1091 return VOS_STATUS_E_FAILURE;
1092 }
1093
Leo Chang64d68bc2013-06-04 15:40:52 -07001094 /* Monitor traffic */
1095 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1096 {
1097 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1098 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1099 {
1100 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1101 /* It was IDLE mode,
1102 * this is new state, then switch mode from suspend to resume */
1103 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1104 {
1105 hdd_set_wlan_suspend_mode(0);
1106 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1107 pHddCtx->cfg_ini->trafficIdleTimeout);
1108 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1109 }
1110 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1111 }
1112 }
1113
Jeff Johnson295189b2012-06-20 16:38:30 -07001114 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1115
Jeff Johnson295189b2012-06-20 16:38:30 -07001116 *ppVosPacket = NULL;
1117
1118 //Make sure the AC being asked for is sane
1119 if( ac > WLANTL_MAX_AC || ac < 0)
1120 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301121 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001122 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001123 return VOS_STATUS_E_FAILURE;
1124 }
1125
1126 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1127
c_hpothu6d1d2a32014-03-18 20:17:03 +05301128 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001129 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001130
1131 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1132 //This simplifies the locking and unlocking of Tx queue
1133 status = vos_pkt_wrap_data_packet( &pVosPacket,
1134 VOS_PKT_TYPE_TX_802_3_DATA,
1135 NULL, //OS Pkt is not being passed
1136 hdd_softap_tx_low_resource_cbk,
1137 pAdapter );
1138
1139 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1140 {
1141 //Remember VOS is in a low resource situation
1142 pAdapter->isVosOutOfResource = VOS_TRUE;
1143 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301144 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001145 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001146 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1147 return VOS_STATUS_E_FAILURE;
1148 }
1149
1150 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
1151 as the other branch does.
1152 */
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301153 spin_lock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1155 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
1156
1157 if (0 == size)
1158 {
1159 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301160 spin_unlock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001161 vos_pkt_return_packet(pVosPacket);
1162 return VOS_STATUS_E_EMPTY;
1163 }
1164
1165 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1166 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301167 spin_unlock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001168
c_hpothu6d1d2a32014-03-18 20:17:03 +05301169 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001170 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001171
1172 if(VOS_STATUS_SUCCESS == status)
1173 {
1174 //If success then we got a valid packet from some AC
1175 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1176 skb = pktNode->skb;
1177 }
1178 else
1179 {
1180 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301181 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001182 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001183 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001184 vos_pkt_return_packet(pVosPacket);
1185 return VOS_STATUS_E_FAILURE;
1186 }
1187
1188 //Attach skb to VOS packet.
1189 status = vos_pkt_set_os_packet( pVosPacket, skb );
1190 if (status != VOS_STATUS_SUCCESS)
1191 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301192 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001193 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001194 vos_pkt_return_packet(pVosPacket);
1195 ++pAdapter->stats.tx_dropped;
1196 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1197 kfree_skb(skb);
1198 return VOS_STATUS_E_FAILURE;
1199 }
1200
1201 //Just being paranoid. To be removed later
1202 if(pVosPacket == NULL)
1203 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301204 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001205 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 ++pAdapter->stats.tx_dropped;
1207 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1208 kfree_skb(skb);
1209 return VOS_STATUS_E_FAILURE;
1210 }
1211
1212 //Return VOS packet to TL;
1213 *ppVosPacket = pVosPacket;
1214
1215 //Fill out the meta information needed by TL
1216 //FIXME This timestamp is really the time stamp of wrap_data_packet
1217 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1218 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1219 if ( 1 < size )
1220 {
1221 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1222 }
1223 else
1224 {
1225 pPktMetaInfo->bMorePackets = 0;
1226 }
1227
1228 pPktMetaInfo->ucIsEapol = 0;
1229
1230 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
1231 {
1232 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
1233 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301234 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001235 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001236 pPktMetaInfo->ucIsEapol = 1;
1237 }
1238 }
1239
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001240 if (pHddCtx->cfg_ini->gEnableDebugLog)
1241 {
1242 proto_type = vos_pkt_get_proto_type(skb,
1243 pHddCtx->cfg_ini->gEnableDebugLog);
1244 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1245 {
1246 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1247 "SAP TX EAPOL");
1248 }
1249 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1250 {
1251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1252 "SAP TX DHCP");
1253 }
1254 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001255//xg: @@@@: temporarily disble these. will revisit later
Jeff Johnson295189b2012-06-20 16:38:30 -07001256 {
1257 pPktMetaInfo->ucUP = pktNode->userPriority;
1258 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1259 }
1260
1261 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1262 //Extract the destination address from ethernet frame
1263 pDestMacAddress = (v_MACADDR_t*)skb->data;
1264
1265 // we need 802.3 to 802.11 frame translation
1266 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1267 pPktMetaInfo->ucDisableFrmXtl = 0;
1268 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1269 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1270
1271 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1272 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1273 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301274 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001275 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1277 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1278 }
1279
1280 // We're giving the packet to TL so consider it transmitted from
1281 // a statistics perspective. We account for it here instead of
1282 // when the packet is returned for two reasons. First, TL will
1283 // manipulate the skb to the point where the len field is not
1284 // accurate, leading to inaccurate byte counts if we account for
1285 // it later. Second, TL does not provide any feedback as to
1286 // whether or not the packet was successfully sent over the air,
1287 // so the packet counts will be the same regardless of where we
1288 // account for them
1289 pAdapter->stats.tx_bytes += skb->len;
1290 ++pAdapter->stats.tx_packets;
1291 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1292 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301293 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001294
c_hpothu6d1d2a32014-03-18 20:17:03 +05301295 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001296 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001297
1298 return status;
1299}
1300
1301
1302/**============================================================================
1303 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1304 case where VOS packets are not available at the time of the call to get
1305 packets. This callback function is invoked by VOS when packets are
1306 available.
1307
1308 @param pVosPacket : [in] pointer to VOS packet
1309 @param userData : [in] opaque user data that was passed initially
1310
1311 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1312 : VOS_STATUS_SUCCESS otherwise
1313 =============================================================================*/
1314VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1315 v_VOID_t *userData )
1316{
1317 VOS_STATUS status;
1318 v_SINT_t i = 0;
1319 v_SIZE_t size = 0;
1320 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1321 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1322
1323 if(pAdapter == NULL)
1324 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301325 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1326 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 return VOS_STATUS_E_FAILURE;
1328 }
1329
1330 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1331 //situation. Here we will only signal TL that there is a pending data for a STA.
1332 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1333 vos_pkt_return_packet( pVosPacket );
1334
1335 pAdapter->isVosOutOfResource = VOS_FALSE;
1336
1337 // Indicate to TL that there is pending data if a queue is non empty.
1338 // This Code wasnt included in earlier version which resulted in
1339 // Traffic stalling
1340 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1341 {
1342 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1343 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1344 {
1345 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1346 {
1347 size = 0;
1348 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1349 if ( size > 0 )
1350 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301351 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1352 STAId,
Jeff Johnson295189b2012-06-20 16:38:30 -07001353 (WLANTL_ACEnumType)i );
1354 if( !VOS_IS_STATUS_SUCCESS( status ) )
1355 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301356 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1357 "%s: Failure in indicating pkt to TL for ac=%d", __func__,i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001358 }
1359 }
1360 }
1361 }
1362 }
1363 return VOS_STATUS_SUCCESS;
1364}
1365
1366
1367/**============================================================================
1368 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1369 TL will call this to notify the HDD when one or more packets were
1370 received for a registered STA.
1371
1372 @param vosContext : [in] pointer to VOS context
1373 @param pVosPacketChain : [in] pointer to VOS packet chain
1374 @param staId : [in] Station Id (Adress 1 Index)
1375 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1376
1377 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1378 : VOS_STATUS_SUCCESS otherwise
1379 ===========================================================================*/
1380VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1381 vos_pkt_t *pVosPacketChain,
1382 v_U8_t staId,
1383 WLANTL_RxMetaInfoType* pRxMetaInfo )
1384{
1385 hdd_adapter_t *pAdapter = NULL;
1386 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1387 int rxstat;
1388 struct sk_buff *skb = NULL;
1389 vos_pkt_t* pVosPacket;
1390 vos_pkt_t* pNextVosPacket;
1391 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001392 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001393
1394 //Sanity check on inputs
1395 if ( ( NULL == vosContext ) ||
1396 ( NULL == pVosPacketChain ) ||
1397 ( NULL == pRxMetaInfo ) )
1398 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301399 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1400 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001401 return VOS_STATUS_E_FAILURE;
1402 }
1403
1404 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1405 if ( NULL == pHddCtx )
1406 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301407 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1408 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001409 return VOS_STATUS_E_FAILURE;
1410 }
1411
1412 pAdapter = pHddCtx->sta_to_adapter[staId];
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301413 if( (NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001414 {
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301415 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1416 "%s: invalid adapter or adapter has invalid magic",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001417 VOS_ASSERT(0);
1418 return VOS_STATUS_E_FAILURE;
1419 }
Leo Chang64d68bc2013-06-04 15:40:52 -07001420
1421 /* Monitor traffic */
1422 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1423 {
1424 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1425 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1426 {
1427 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1428 /* It was IDLE mode,
1429 * this is new state, then switch mode from suspend to resume */
1430 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1431 {
1432 hdd_set_wlan_suspend_mode(0);
1433 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1434 pHddCtx->cfg_ini->trafficIdleTimeout);
1435 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1436 }
1437 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1438 }
1439 }
1440
Jeff Johnson295189b2012-06-20 16:38:30 -07001441 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1442
1443 // walk the chain until all are processed
1444 pVosPacket = pVosPacketChain;
1445 do
1446 {
1447 // get the pointer to the next packet in the chain
1448 // (but don't unlink the packet since we free the entire chain later)
1449 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1450
1451 // both "success" and "empty" are acceptable results
1452 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1453 {
1454 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301455 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1456 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001457 return VOS_STATUS_E_FAILURE;
1458 }
1459
1460 // Extract the OS packet (skb).
1461 // Tell VOS to detach the OS packet from the VOS packet
1462 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1463 if(!VOS_IS_STATUS_SUCCESS( status ))
1464 {
1465 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301466 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1467 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001468 return VOS_STATUS_E_FAILURE;
1469 }
1470
1471 //hdd_softap_dump_sk_buff(skb);
1472
1473 skb->dev = pAdapter->dev;
1474
1475 if(skb->dev == NULL) {
1476
c_hpothu6d1d2a32014-03-18 20:17:03 +05301477 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_FATAL,
1478 "ERROR!!Invalid netdevice");
Jeff Johnson295189b2012-06-20 16:38:30 -07001479 return VOS_STATUS_E_FAILURE;
1480 }
1481 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1482 ++pAdapter->stats.rx_packets;
1483 pAdapter->stats.rx_bytes += skb->len;
1484
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001485 if (pHddCtx->cfg_ini->gEnableDebugLog)
1486 {
1487 proto_type = vos_pkt_get_proto_type(skb,
1488 pHddCtx->cfg_ini->gEnableDebugLog);
1489 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1490 {
1491 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1492 "SAP RX EAPOL");
1493 }
1494 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1495 {
1496 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1497 "SAP RX DHCP");
1498 }
1499 }
1500
Jeff Johnson295189b2012-06-20 16:38:30 -07001501 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1502 {
1503 //MC/BC packets. Duplicate a copy of packet
1504 struct sk_buff *pSkbCopy;
1505 hdd_ap_ctx_t *pHddApCtx;
1506
1507 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1508 if (!(pHddApCtx->apDisableIntraBssFwd))
1509 {
1510 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1511 if (pSkbCopy)
1512 {
1513 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1514 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1515 }
1516 }
1517 else
1518 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301519 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001520 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001521 }
1522
1523
1524 } //(WLAN_RX_BCMC_STA_ID == staId)
1525
1526 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1527 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1528 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301529 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001530 "%s: send one packet to kernel", __func__);
Dino Mycled9b7cc12014-09-04 18:43:07 +05301531 if ( pHddCtx->cfg_ini->enableDhcpDebug )
1532 {
1533 hdd_dump_dhcp_pkt(skb, RX_PATH);
1534 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001535
1536 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001537 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001538#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001539#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001540 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001541#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001542#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001543 rxstat = netif_rx_ni(skb);
1544 if (NET_RX_SUCCESS == rxstat)
1545 {
1546 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001547 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001548 }
1549 else
1550 {
1551 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1552 }
1553 }
1554 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1555 {
1556 kfree_skb(skb);
1557 }
1558 else
1559 {
1560 //loopback traffic
1561 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1562 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1563 }
1564
1565 // now process the next packet in the chain
1566 pVosPacket = pNextVosPacket;
1567
1568 } while (pVosPacket);
1569
1570 //Return the entire VOS packet chain to the resource pool
1571 status = vos_pkt_return_packet( pVosPacketChain );
1572 if(!VOS_IS_STATUS_SUCCESS( status ))
1573 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301574 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1575 "%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001576 }
1577
1578 pAdapter->dev->last_rx = jiffies;
1579
1580 return status;
1581}
1582
1583VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1584{
1585 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301586 hdd_context_t *pHddCtx;
1587 if (NULL == pAdapter)
1588 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301589 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301590 "%s: pAdapter is NULL", __func__);
1591 return VOS_STATUS_E_INVAL;
1592 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001593
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301594 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1595 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301596 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301597 "%s: Invalid pAdapter magic", __func__);
1598 return VOS_STATUS_E_INVAL;
1599 }
1600
1601 pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
c_hpothu6d1d2a32014-03-18 20:17:03 +05301602 //Clear station in TL and then update HDD data structures. This helps
Jeff Johnson295189b2012-06-20 16:38:30 -07001603 //to block RX frames from other station to this station.
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301604 vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001605 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1606 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301607 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001608 "WLANTL_ClearSTAClient() failed to for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001609 "Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001610 staId, vosStatus, vosStatus );
1611 }
1612
1613 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1614 if( VOS_STATUS_E_FAILURE == vosStatus )
1615 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301616 VOS_TRACE ( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001618 "Status = %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001619 staId, vosStatus, vosStatus );
1620 return( vosStatus );
1621 }
1622
1623 pHddCtx->sta_to_adapter[staId] = NULL;
1624
1625 return( vosStatus );
1626}
1627
1628VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1629 v_BOOL_t fAuthRequired,
1630 v_BOOL_t fPrivacyBit,
1631 v_U8_t staId,
1632 v_U8_t ucastSig,
1633 v_U8_t bcastSig,
1634 v_MACADDR_t *pPeerMacAddress,
1635 v_BOOL_t fWmmEnabled )
1636{
1637 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001638 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001639 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1640 hdd_adapter_t *pmonAdapter = NULL;
1641
1642 //eCsrEncryptionType connectedCipherAlgo;
1643 //v_BOOL_t fConnected;
1644
1645 /*
1646 * Clean up old entry if it is not cleaned up properly
1647 */
1648 if ( pAdapter->aStaInfo[staId].isUsed )
1649 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301650 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001651 "clean up old entry for STA %d", staId);
1652 hdd_softap_DeregisterSTA( pAdapter, staId );
1653 }
1654
1655 // Get the Station ID from the one saved during the assocation.
1656
1657 staDesc.ucSTAId = staId;
1658
1659
1660 /*Save the pAdapter Pointer for this staId*/
1661 pHddCtx->sta_to_adapter[staId] = pAdapter;
1662
1663 staDesc.wSTAType = WLAN_STA_SOFTAP;
1664
1665 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1666 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1667 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1668
c_hpothu6d1d2a32014-03-18 20:17:03 +05301669 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001670 "register station");
c_hpothu6d1d2a32014-03-18 20:17:03 +05301671 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001672 "station mac " MAC_ADDRESS_STR,
1673 MAC_ADDR_ARRAY(staDesc.vSTAMACAddress.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301674 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001675 "BSSIDforIBSS " MAC_ADDRESS_STR,
1676 MAC_ADDR_ARRAY(staDesc.vBSSIDforIBSS.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301677 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001678 "SOFTAP SELFMAC " MAC_ADDRESS_STR,
1679 MAC_ADDR_ARRAY(staDesc.vSelfMACAddress.bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07001680
1681 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1682
Jeff Johnson295189b2012-06-20 16:38:30 -07001683 staDesc.ucQosEnabled = fWmmEnabled;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301684 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001685 "HDD SOFTAP register TL QoS_enabled=%d",
1686 staDesc.ucQosEnabled );
1687
1688 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1689
1690
Jeff Johnson295189b2012-06-20 16:38:30 -07001691 // For PRIMA UMA frame translation is not enable yet.
1692 staDesc.ucSwFrameTXXlation = 1;
1693 staDesc.ucSwFrameRXXlation = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07001694 staDesc.ucAddRmvLLC = 1;
1695
1696 // Initialize signatures and state
1697 staDesc.ucUcastSig = ucastSig;
1698 staDesc.ucBcastSig = bcastSig;
1699 staDesc.ucInitState = fAuthRequired ?
1700 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1701
Prathyushaf5442802012-12-12 13:58:11 -08001702 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1703
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 // Register the Station with TL...
c_hpothu6d1d2a32014-03-18 20:17:03 +05301705 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1706 hdd_softap_rx_packet_cbk,
1707 hdd_softap_tx_complete_cbk,
Jeff Johnson295189b2012-06-20 16:38:30 -07001708 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1709
1710 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1711 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301712 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001713 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001714 vosStatus, vosStatus );
1715 return vosStatus;
1716 }
1717
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001718 //Timer value should be in milliseconds
1719 if ( pHddCtx->cfg_ini->dynSplitscan &&
1720 ( VOS_TIMER_STATE_RUNNING !=
1721 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
1722 {
1723 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1724 pHddCtx->cfg_ini->trafficMntrTmrForSplitScan);
1725 }
1726
Jeff Johnson295189b2012-06-20 16:38:30 -07001727 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1728 // then go to 'authenticated'. For all other authentication types (those that do
1729 // not require upper layer authentication) we can put TL directly into 'authenticated'
1730 // state.
1731
1732 //VOS_ASSERT( fConnected );
1733 pAdapter->aStaInfo[staId].ucSTAId = staId;
1734 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1735
1736 if ( !fAuthRequired )
1737 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301738 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
1739 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
1740 pAdapter->aStaInfo[staId].ucSTAId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001741
1742 // Connections that do not need Upper layer auth, transition TL directly
1743 // to 'Authenticated' state.
1744 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1745 WLANTL_STA_AUTHENTICATED );
1746
1747 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1748 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1749 }
1750 else
1751 {
1752
c_hpothu6d1d2a32014-03-18 20:17:03 +05301753 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001754 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1755
1756 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1757 WLANTL_STA_CONNECTED );
1758 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1759
1760 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1761
1762 }
1763 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1764 if(pmonAdapter)
1765 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301766 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
1767 "Turn on Monitor the carrier");
Jeff Johnson295189b2012-06-20 16:38:30 -07001768 netif_carrier_on(pmonAdapter->dev);
1769 //Enable Tx queue
1770 netif_tx_start_all_queues(pmonAdapter->dev);
1771 }
1772 netif_carrier_on(pAdapter->dev);
1773 //Enable Tx queue
1774 netif_tx_start_all_queues(pAdapter->dev);
1775
1776 return( vosStatus );
1777}
1778
1779VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1780{
1781 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1782 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1783 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1784
1785
1786 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1787 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1788 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1789
1790 return vosStatus;
1791}
1792
1793VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1794{
1795 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1796}
1797
1798VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1799{
Wilson Yangf80a0542013-10-07 13:02:37 -07001800 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001801 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1802 v_U8_t staId = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07001803 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1804
1805 /*bss deregister is not allowed during wlan driver loading or unloading*/
Mihir Shete18156292014-03-11 15:38:30 +05301806 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Wilson Yangf80a0542013-10-07 13:02:37 -07001807 {
1808 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1809 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
1810 return VOS_STATUS_E_PERM;
1811 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001812
1813 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1814
Jeff Johnson43971f52012-07-17 12:26:56 -07001815 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001816 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301817 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001818 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001819 }
1820
1821 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1822 {
1823 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
Jeff Johnson295189b2012-06-20 16:38:30 -07001824 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301825 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1826 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1827 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301828 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001829 "%s: Failed to deregister sta Id %d", __func__, staId);
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301830 }
1831 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001832 }
1833
1834 return vosStatus;
1835}
1836
1837VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1838{
1839 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1840 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1841 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001842
c_hpothu6d1d2a32014-03-18 20:17:03 +05301843 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001844 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001845
Jeff Johnson43971f52012-07-17 12:26:56 -07001846 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001847 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301848 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001849 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001850 return VOS_STATUS_E_FAILURE;
1851 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001852
1853 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1854 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301855 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001856 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001857 return VOS_STATUS_E_FAILURE;
1858 }
1859
1860 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
c_hpothu6d1d2a32014-03-18 20:17:03 +05301861 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001862 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001863
Jeff Johnson43971f52012-07-17 12:26:56 -07001864 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001865 {
1866 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1867 }
1868
c_hpothu6d1d2a32014-03-18 20:17:03 +05301869 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001870 "%s exit",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001871
1872 return vosStatus;
1873}
1874
1875
1876VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1877{
1878 v_U8_t i;
1879
1880 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1881 {
1882 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1883 pAdapter->aStaInfo[i].isUsed)
1884 {
1885 *staId = i;
1886 return VOS_STATUS_SUCCESS;
1887 }
1888 }
1889
1890 return VOS_STATUS_E_FAILURE;
1891}
1892
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301893VOS_STATUS hdd_softap_GetConnectedStaId(hdd_adapter_t *pAdapter, v_U8_t *staId)
1894{
1895 v_U8_t i;
1896
1897 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1898 {
Kiet Lam61589852013-09-19 17:10:58 +05301899 if (pAdapter->aStaInfo[i].isUsed &&
1900 (!vos_is_macaddr_broadcast(&pAdapter->aStaInfo[i].macAddrSTA)))
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301901 {
1902 *staId = i;
1903 return VOS_STATUS_SUCCESS;
1904 }
1905 }
1906
1907 return VOS_STATUS_E_FAILURE;
1908}