blob: 49425696c31ab84553d04d47e5e1b31b13982fb6 [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);
294 vos_list_node_t *anchor = NULL;
295 v_U8_t STAId = WLAN_MAX_STA_COUNT;
296 //Extract the destination address from ethernet frame
297 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
298 int os_status = NETDEV_TX_OK;
299
300 pDestMacAddress = (v_MACADDR_t*)skb->data;
301
302 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
303
c_hpothu6d1d2a32014-03-18 20:17:03 +0530304 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700305 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700306
307 spin_lock_bh( &pAdapter->staInfo_lock );
308 if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
309 {
310 //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
311 //ID used for BC/MC traffic. The station id is registered to TL as well.
312 STAId = pHddApCtx->uBCStaId;
313
314 /* Setting priority for broadcast packets which doesn't go to select_queue function */
315 skb->priority = SME_QOS_WMM_UP_BE;
316 skb->queue_mapping = HDD_LINUX_AC_BE;
317
c_hpothu6d1d2a32014-03-18 20:17:03 +0530318 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800319 "%s: BC/MC packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320 }
321 else
322 {
323 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
324 if (STAId == HDD_WLAN_INVALID_STA_ID)
325 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530326 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700327 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700328 ++pAdapter->stats.tx_dropped;
329 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
330 kfree_skb(skb);
331 goto xmit_done;
332 }
333 else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
334 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530335 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
336 "%s: STA %d is unregistered", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700337 ++pAdapter->stats.tx_dropped;
338 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
339 kfree_skb(skb);
340 goto xmit_done;
341 }
342
343 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
344 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
345 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530346 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700347 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700348 ++pAdapter->stats.tx_dropped;
349 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
350 kfree_skb(skb);
351 goto xmit_done;
352 }
353 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
354 {
355 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
356 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530357 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700358 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700359 ++pAdapter->stats.tx_dropped;
360 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
361 kfree_skb(skb);
362 goto xmit_done;
363 }
364 }
365 }
366
367 //Get TL AC corresponding to Qdisc queue index/AC.
368 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
369 //user priority from IP header, which is already extracted and set from
370 //select_queue call back function
371 up = skb->priority;
372 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
373
c_hpothu6d1d2a32014-03-18 20:17:03 +0530374 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700375 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700376
377 // If the memory differentiation mode is enabled, the memory limit of each queue will be
378 // checked. Over-limit packets will be dropped.
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700379 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700380 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
381 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
382 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530383 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800384 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
386 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
387 txSuspended = VOS_TRUE;
388 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530389
390 /* If 3/4th of the max queue size is used then enable the flag.
391 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
392 if (WLANTL_AC_BE == ac)
393 {
394 if (pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
395 {
396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
397 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
398 pAdapter->aStaInfo[STAId].vosLowResource = VOS_TRUE;
399 }
400 else
401 {
402 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
403 }
404 }
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700405 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700406
407 if (VOS_TRUE == txSuspended)
408 {
409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
410 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700411 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700412 os_status = NETDEV_TX_BUSY;
413 goto xmit_done;
414 }
415
416 //Use the skb->cb field to hold the list node information
417 pktNode = (skb_list_node_t *)&skb->cb;
418
419 //Stick the OS packet inside this node.
420 pktNode->skb = skb;
421
422 //Stick the User Priority inside this node
423 pktNode->userPriority = up;
424
425 INIT_LIST_HEAD(&pktNode->anchor);
426
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700427 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700428 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700429 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700430
431 if ( !VOS_IS_STATUS_SUCCESS( status ) )
432 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530433 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
434 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700435 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
436 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
437 ++pAdapter->stats.tx_dropped;
438 kfree_skb(skb);
439 goto xmit_done;
440 }
441
442 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
443 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Rashmi Ramannacbffcb12014-01-07 13:22:13 +0530444 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700445
446 if (1 == pktListSize)
447 {
448 //Let TL know we have a packet to send for this AC
449 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
450
451 if ( !VOS_IS_STATUS_SUCCESS( status ) )
452 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530453 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
454 "%s: Failed to signal TL for AC=%d STAId =%d",
455 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700456
457 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
458 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
459 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
460 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
461 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
462 ++pAdapter->stats.tx_dropped;
463 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
464 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
465 kfree_skb(skb);
466 goto xmit_done;
467 }
468 }
469 dev->trans_start = jiffies;
470
c_hpothu6d1d2a32014-03-18 20:17:03 +0530471 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
472 "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700473
474xmit_done:
475 spin_unlock_bh( &pAdapter->staInfo_lock );
476 return os_status;
477}
478
479/**============================================================================
480 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
481
482 @param skb : [in] pointer to packet (sk_buff)
483 @param dev : [in] pointer to Libra network device
484 @param STAId : [in] Station Id of Destination Station
485 @param up : [in] User Priority
486
487 @return : NET_XMIT_DROP if packets are dropped
488 : NET_XMIT_SUCCESS if packet is enqueued succesfully
489 ===========================================================================*/
490VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
491 struct net_device *dev,
492 v_U8_t STAId,
493 v_U8_t up)
494{
495 VOS_STATUS status = VOS_STATUS_SUCCESS;
496 skb_list_node_t *pktNode = NULL;
497 v_SIZE_t pktListSize = 0;
498 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
499 v_U8_t ac;
500 vos_list_node_t *anchor = NULL;
501
502 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
503
c_hpothu6d1d2a32014-03-18 20:17:03 +0530504 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700505 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700506
507 spin_lock_bh( &pAdapter->staInfo_lock );
508 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
509 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530510 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530511 "%s: STA %d is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700512 kfree_skb(skb);
513 status = VOS_STATUS_E_FAILURE;
514 goto xmit_end;
515 }
516
517 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
518 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
519 up = SME_QOS_WMM_UP_BE;
520
521 ac = hddWmmUpToAcMap[up];
522 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
c_hpothu6d1d2a32014-03-18 20:17:03 +0530523 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700524 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700525
526 skb->queue_mapping = hddLinuxUpToAcMap[up];
527
528 //Use the skb->cb field to hold the list node information
529 pktNode = (skb_list_node_t *)&skb->cb;
530
531 //Stick the OS packet inside this node.
532 pktNode->skb = skb;
533
534 //Stick the User Priority inside this node
535 pktNode->userPriority = up;
536
537 INIT_LIST_HEAD(&pktNode->anchor);
538
539 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
540 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
541 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
542 pktListSize >= pAdapter->aTxQueueLimit[ac])
543 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530544 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800545 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
547 * SUSPEND should be done based on Threshold. RESUME would be
548 * triggered in fetch cbk after recovery.
549 */
550 kfree_skb(skb);
551 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
552 status = VOS_STATUS_E_FAILURE;
553 goto xmit_end;
554 }
555 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
556 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
557
558 if ( !VOS_IS_STATUS_SUCCESS( status ) )
559 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530560 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
561 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700562 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
563 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
564 ++pAdapter->stats.tx_dropped;
565 kfree_skb(skb);
566 status = VOS_STATUS_E_FAILURE;
567 goto xmit_end;
568 }
569
570 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
571 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
572
573 if (1 == pktListSize)
574 {
575 //Let TL know we have a packet to send for this AC
c_hpothu6d1d2a32014-03-18 20:17:03 +0530576 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
577 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700578
579 if ( !VOS_IS_STATUS_SUCCESS( status ) )
580 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530581 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
582 "%s: Failed to signal TL for AC=%d STAId =%d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700583 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700584
585 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
586 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
587 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
588 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
589 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
590 ++pAdapter->stats.tx_dropped;
591 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
592 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
593 kfree_skb(skb);
594 status = VOS_STATUS_E_FAILURE;
595 goto xmit_end;
596 }
597 }
598
c_hpothu6d1d2a32014-03-18 20:17:03 +0530599 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700600
601xmit_end:
602 spin_unlock_bh( &pAdapter->staInfo_lock );
603 return status;
604}
605
606/**============================================================================
607 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
608 timeout during transmission. Since HDD simply enqueues packet
609 and returns control to OS right away, this would never be invoked
610
611 @param dev : [in] pointer to Libra network device
612 @return : None
613 ===========================================================================*/
614void hdd_softap_tx_timeout(struct net_device *dev)
615{
Mihir Shetef3473692014-06-27 15:13:20 +0530616 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
617 struct netdev_queue *txq;
618 int i = 0;
619
c_hpothu6d1d2a32014-03-18 20:17:03 +0530620 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700621 "%s: Transmission timeout occurred", __func__);
Mihir Shetef3473692014-06-27 15:13:20 +0530622
623 if ( NULL == pAdapter )
624 {
625 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
626 FL("pAdapter is NULL"));
627 VOS_ASSERT(0);
628 return;
629 }
630
631 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
632
633 for (i = 0; i < 8; i++)
634 {
635 txq = netdev_get_tx_queue(dev, i);
636 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
637 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
638 }
639
640 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
641 "carrier state: %d", netif_carrier_ok(dev));
642
643 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
644
645 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
646 HDD_SAP_TX_STALL_SSR_THRESHOLD)
647 {
648 // Driver could not recover, issue SSR
649 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
650 "%s: Cannot recover from Data stall Issue SSR",
651 __func__);
Mihir Shetefd62d9d2014-08-06 15:08:21 +0530652 WLANTL_FatalError();
Mihir Shetef3473692014-06-27 15:13:20 +0530653 return;
654 }
655
656 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
657 * every 5sec. The TL debug spits out a lot of information on the
658 * serial console, if it is called every time *hdd_tx_timeout* is
659 * called then we may get a watchdog bite on the Application
660 * processor, so ratelimit the TL debug logs.
661 */
662 if (__ratelimit(&hdd_softap_tx_timeout_rs))
663 {
664 hdd_wmm_tx_snapshot(pAdapter);
665 WLANTL_TLDebugMessage(VOS_TRUE);
666 }
667
Jeff Johnson295189b2012-06-20 16:38:30 -0700668}
669
670
671/**============================================================================
672 @brief hdd_softap_stats() - Function registered with the Linux OS for
673 device TX/RX statistic
674
675 @param dev : [in] pointer to Libra network device
676
677 @return : pointer to net_device_stats structure
678 ===========================================================================*/
679struct net_device_stats* hdd_softap_stats(struct net_device *dev)
680{
681 hdd_adapter_t* priv = netdev_priv(dev);
682 return &priv->stats;
683}
684
685
686/**============================================================================
687 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
688 modules in HDD
689
690 @param pAdapter : [in] pointer to adapter context
691 @return : VOS_STATUS_E_FAILURE if any errors encountered
692 : VOS_STATUS_SUCCESS otherwise
693 ===========================================================================*/
694VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
695{
696 VOS_STATUS status = VOS_STATUS_SUCCESS;
697 v_SINT_t i = -1;
698 v_SIZE_t size = 0;
699
700 v_U8_t STAId = 0;
701
702 v_U8_t pACWeights[] = {
703 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
704 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
705 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
706 HDD_SOFTAP_VO_WEIGHT_DEFAULT
707 };
Leo Chang64d68bc2013-06-04 15:40:52 -0700708
Jeff Johnson295189b2012-06-20 16:38:30 -0700709 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530710 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700711
712 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
713
714 while (++i != NUM_TX_QUEUES)
715 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
716
717 /* Initial HDD buffer control / flow control fields*/
718 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
719
720 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
721 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
722 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
723 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
724
725 spin_lock_init( &pAdapter->staInfo_lock );
726
727 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
728 {
729 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
730 for (i = 0; i < NUM_TX_QUEUES; i ++)
731 {
732 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
733 }
734 }
735
Yue Ma3ede6052013-08-29 00:33:26 -0700736 /* Update the AC weights suitable for SoftAP mode of operation */
737 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
738
Kiet Lambcf38522013-10-26 18:28:27 +0530739 if (VOS_STATUS_SUCCESS != hdd_start_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700740 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530741 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530742 "%s: failed to start Traffic Monito timer ", __func__ );
743 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700744 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700745 return status;
746}
747
748/**============================================================================
749 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
750 modules in HDD
751
752 @param pAdapter : [in] pointer to adapter context
753 @return : VOS_STATUS_E_FAILURE if any errors encountered
754 : VOS_STATUS_SUCCESS otherwise
755 ===========================================================================*/
756VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
757{
758 VOS_STATUS status = VOS_STATUS_SUCCESS;
Leo Chang64d68bc2013-06-04 15:40:52 -0700759
Kiet Lambcf38522013-10-26 18:28:27 +0530760 if (VOS_STATUS_SUCCESS != hdd_stop_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700761 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530762 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530763 "%s: Fail to Stop Traffic Monito timer", __func__ );
764 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700765 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700766
767 status = hdd_softap_flush_tx_queues(pAdapter);
768
769 return status;
770}
771
772/**============================================================================
773 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
774
775 @param pAdapter : [in] pointer to adapter context
776 @param STAId : [in] Station ID to deinit
777 @return : VOS_STATUS_E_FAILURE if any errors encountered
778 : VOS_STATUS_SUCCESS otherwise
779 ===========================================================================*/
780static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
781{
Jeff Johnson295189b2012-06-20 16:38:30 -0700782 v_U8_t i = -1;
783
784 hdd_list_node_t *anchor = NULL;
785
786 skb_list_node_t *pktNode = NULL;
787 struct sk_buff *skb = NULL;
788
789 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
790 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530791 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700792 }
793
794 for (i = 0; i < NUM_TX_QUEUES; i ++)
795 {
796 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
797 while (true)
798 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530799 if (VOS_STATUS_E_EMPTY !=
800 hdd_list_remove_front(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
801 &anchor))
Jeff Johnson295189b2012-06-20 16:38:30 -0700802 {
803 //If success then we got a valid packet from some AC
804 pktNode = list_entry(anchor, skb_list_node_t, anchor);
805 skb = pktNode->skb;
806 ++pAdapter->stats.tx_dropped;
807 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
808 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
809 kfree_skb(skb);
810 continue;
811 }
812
813 //current list is empty
814 break;
815 }
816 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
817 }
818
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530819 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700820}
821
822/**============================================================================
823 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
824 modules in HDD
825
826 @param pAdapter : [in] pointer to adapter context
827 @param STAId : [in] Station ID to deinit
828 @param pmacAddrSTA : [in] pointer to the MAC address of the station
829 @return : VOS_STATUS_E_FAILURE if any errors encountered
830 : VOS_STATUS_SUCCESS otherwise
831 ===========================================================================*/
832VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
833{
834 v_U8_t i = 0;
835 spin_lock_bh( &pAdapter->staInfo_lock );
836 if (pAdapter->aStaInfo[STAId].isUsed)
837 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530838 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
839 "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 spin_unlock_bh( &pAdapter->staInfo_lock );
841 return VOS_STATUS_E_FAILURE;
842 }
843
844 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
845 for (i = 0; i < NUM_TX_QUEUES; i ++)
846 {
847 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
848 }
849
850 pAdapter->aStaInfo[STAId].isUsed = TRUE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800851 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700852 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
853
854 spin_unlock_bh( &pAdapter->staInfo_lock );
855 return VOS_STATUS_SUCCESS;
856}
857
858/**============================================================================
859 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
860 modules in HDD
861
862 @param pAdapter : [in] pointer to adapter context
863 @param STAId : [in] Station ID to deinit
864 @return : VOS_STATUS_E_FAILURE if any errors encountered
865 : VOS_STATUS_SUCCESS otherwise
866 ===========================================================================*/
867VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
868{
869 VOS_STATUS status = VOS_STATUS_SUCCESS;
870 v_U8_t ac;
871 /**Track whether OS TX queue has been disabled.*/
872 v_BOOL_t txSuspended[NUM_TX_QUEUES];
873 v_U8_t tlAC;
874 hdd_hostapd_state_t *pHostapdState;
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700875 v_U8_t i;
Jeff Johnson295189b2012-06-20 16:38:30 -0700876
877 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
878
879 spin_lock_bh( &pAdapter->staInfo_lock );
880 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
881 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530882 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700883 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700884 spin_unlock_bh( &pAdapter->staInfo_lock );
885 return VOS_STATUS_E_FAILURE;
886 }
887
888 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
889
890 pAdapter->aStaInfo[STAId].isUsed = FALSE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800891 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700892
893 /* if this STA had any of its WMM TX queues suspended, then the
894 associated queue on the network interface was disabled. check
895 to see if that is the case, in which case we need to re-enable
896 the interface queue. but we only do this if the BSS is running
897 since, if the BSS is stopped, all of the interfaces have been
898 stopped and should not be re-enabled */
899
900 if (BSS_START == pHostapdState->bssState)
901 {
902 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
903 {
904 tlAC = hdd_QdiscAcToTlAC[ac];
905 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
906 }
907 }
908 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
909
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700910 /* re-init spin lock, since netdev can still open adapter until
911 * driver gets unloaded
912 */
913 for (i = 0; i < NUM_TX_QUEUES; i ++)
914 {
915 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
916 HDD_TX_QUEUE_MAX_LEN);
917 }
918
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 if (BSS_START == pHostapdState->bssState)
920 {
921 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
922 {
923 if (txSuspended[ac])
924 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530925 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700926 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 netif_wake_subqueue(pAdapter->dev, ac);
928 }
929 }
930 }
931
932 spin_unlock_bh( &pAdapter->staInfo_lock );
933 return status;
934}
935
936/**============================================================================
937 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
938 modules in HDD
939
940 @param pAdapter : [in] pointer to adapter context
941 @return : VOS_STATUS_E_FAILURE if any errors encountered
942 : VOS_STATUS_SUCCESS otherwise
943 ===========================================================================*/
944VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
945{
946 return hdd_softap_flush_tx_queues(pAdapter);
947}
948
949/**============================================================================
950 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
951 to indicate that a packet has been transmitted across the bus
952 succesfully. OS packet resources can be released after this cbk.
953
954 @param vosContext : [in] pointer to VOS context
955 @param pVosPacket : [in] pointer to VOS packet (containing skb)
956 @param vosStatusIn : [in] status of the transmission
957
958 @return : VOS_STATUS_E_FAILURE if any errors encountered
959 : VOS_STATUS_SUCCESS otherwise
960 ===========================================================================*/
961VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
962 vos_pkt_t *pVosPacket,
963 VOS_STATUS vosStatusIn )
964{
965 VOS_STATUS status = VOS_STATUS_SUCCESS;
966 hdd_adapter_t *pAdapter = NULL;
967 void* pOsPkt = NULL;
968
969 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
970 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530971 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
972 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 return VOS_STATUS_E_FAILURE;
974 }
975
976 //Return the skb to the OS
977 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Rajesh Chauhana0516c62014-01-30 16:11:18 -0800978 if ((!VOS_IS_STATUS_SUCCESS(status)) || (!pOsPkt))
Jeff Johnson295189b2012-06-20 16:38:30 -0700979 {
980 //This is bad but still try to free the VOSS resources if we can
c_hpothu6d1d2a32014-03-18 20:17:03 +0530981 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
982 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700983 vos_pkt_return_packet( pVosPacket );
984 return VOS_STATUS_E_FAILURE;
985 }
986
987 //Get the Adapter context.
988 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
989 if(pAdapter == NULL)
990 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530991 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
992 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 }
994 else
995 {
996 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
997 }
998
999 kfree_skb((struct sk_buff *)pOsPkt);
1000
1001 //Return the VOS packet resources.
1002 status = vos_pkt_return_packet( pVosPacket );
1003 if(!VOS_IS_STATUS_SUCCESS( status ))
1004 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301005 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1006 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001007 }
1008
1009 return status;
1010}
1011
1012
1013/**============================================================================
1014 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
1015 fetch a packet for transmission.
1016
1017 @param vosContext : [in] pointer to VOS context
1018 @param staId : [in] Station for which TL is requesting a pkt
1019 @param ac : [in] access category requested by TL
1020 @param pVosPacket : [out] pointer to VOS packet packet pointer
1021 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1022
1023 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1024 : VOS_STATUS_E_FAILURE if any errors encountered
1025 : VOS_STATUS_SUCCESS otherwise
1026 ===========================================================================*/
1027VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1028 v_U8_t *pStaId,
1029 WLANTL_ACEnumType ac,
1030 vos_pkt_t **ppVosPacket,
1031 WLANTL_MetaInfoType *pPktMetaInfo )
1032{
1033 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1034 hdd_adapter_t *pAdapter = NULL;
1035 hdd_list_node_t *anchor = NULL;
1036 skb_list_node_t *pktNode = NULL;
1037 struct sk_buff *skb = NULL;
1038 vos_pkt_t *pVosPacket = NULL;
1039 v_MACADDR_t* pDestMacAddress = NULL;
1040 v_TIME_t timestamp;
1041 v_SIZE_t size = 0;
1042 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1043 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001044 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001045
1046 //Sanity check on inputs
1047 if ( ( NULL == vosContext ) ||
1048 ( NULL == pStaId ) ||
1049 ( NULL == ppVosPacket ) ||
1050 ( NULL == pPktMetaInfo ) )
1051 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301052 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1053 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001054 return VOS_STATUS_E_FAILURE;
1055 }
1056
1057 //Get the HDD context.
1058 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1059 if ( NULL == pHddCtx )
1060 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301061 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1062 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001063 return VOS_STATUS_E_FAILURE;
1064 }
1065
Jeff Johnsonb156c922013-12-05 17:19:46 -08001066 STAId = *pStaId;
1067 if (STAId >= WLAN_MAX_STA_COUNT)
1068 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301069 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001070 "%s: Invalid STAId %d passed by TL", __func__, STAId);
1071 return VOS_STATUS_E_FAILURE;
1072 }
1073
1074 pAdapter = pHddCtx->sta_to_adapter[STAId];
1075 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001076 {
1077 VOS_ASSERT(0);
1078 return VOS_STATUS_E_FAILURE;
1079 }
1080
Jeff Johnsonb156c922013-12-05 17:19:46 -08001081 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
1082 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301083 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001084 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1085 return VOS_STATUS_E_FAILURE;
1086 }
1087
Leo Chang64d68bc2013-06-04 15:40:52 -07001088 /* Monitor traffic */
1089 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1090 {
1091 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1092 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1093 {
1094 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1095 /* It was IDLE mode,
1096 * this is new state, then switch mode from suspend to resume */
1097 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1098 {
1099 hdd_set_wlan_suspend_mode(0);
1100 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1101 pHddCtx->cfg_ini->trafficIdleTimeout);
1102 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1103 }
1104 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1105 }
1106 }
1107
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1109
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 *ppVosPacket = NULL;
1111
1112 //Make sure the AC being asked for is sane
1113 if( ac > WLANTL_MAX_AC || ac < 0)
1114 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301115 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001116 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001117 return VOS_STATUS_E_FAILURE;
1118 }
1119
1120 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1121
c_hpothu6d1d2a32014-03-18 20:17:03 +05301122 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001123 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001124
1125 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1126 //This simplifies the locking and unlocking of Tx queue
1127 status = vos_pkt_wrap_data_packet( &pVosPacket,
1128 VOS_PKT_TYPE_TX_802_3_DATA,
1129 NULL, //OS Pkt is not being passed
1130 hdd_softap_tx_low_resource_cbk,
1131 pAdapter );
1132
1133 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1134 {
1135 //Remember VOS is in a low resource situation
1136 pAdapter->isVosOutOfResource = VOS_TRUE;
1137 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301138 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001139 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001140 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1141 return VOS_STATUS_E_FAILURE;
1142 }
1143
1144 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
1145 as the other branch does.
1146 */
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301147 spin_lock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001148 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1149 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
1150
1151 if (0 == size)
1152 {
1153 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301154 spin_unlock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001155 vos_pkt_return_packet(pVosPacket);
1156 return VOS_STATUS_E_EMPTY;
1157 }
1158
1159 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1160 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301161 spin_unlock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001162
c_hpothu6d1d2a32014-03-18 20:17:03 +05301163 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001164 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001165
1166 if(VOS_STATUS_SUCCESS == status)
1167 {
1168 //If success then we got a valid packet from some AC
1169 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1170 skb = pktNode->skb;
1171 }
1172 else
1173 {
1174 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301175 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001177 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001178 vos_pkt_return_packet(pVosPacket);
1179 return VOS_STATUS_E_FAILURE;
1180 }
1181
1182 //Attach skb to VOS packet.
1183 status = vos_pkt_set_os_packet( pVosPacket, skb );
1184 if (status != VOS_STATUS_SUCCESS)
1185 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301186 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001187 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001188 vos_pkt_return_packet(pVosPacket);
1189 ++pAdapter->stats.tx_dropped;
1190 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1191 kfree_skb(skb);
1192 return VOS_STATUS_E_FAILURE;
1193 }
1194
1195 //Just being paranoid. To be removed later
1196 if(pVosPacket == NULL)
1197 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301198 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001199 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001200 ++pAdapter->stats.tx_dropped;
1201 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1202 kfree_skb(skb);
1203 return VOS_STATUS_E_FAILURE;
1204 }
1205
1206 //Return VOS packet to TL;
1207 *ppVosPacket = pVosPacket;
1208
1209 //Fill out the meta information needed by TL
1210 //FIXME This timestamp is really the time stamp of wrap_data_packet
1211 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1212 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1213 if ( 1 < size )
1214 {
1215 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1216 }
1217 else
1218 {
1219 pPktMetaInfo->bMorePackets = 0;
1220 }
1221
1222 pPktMetaInfo->ucIsEapol = 0;
1223
1224 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
1225 {
1226 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
1227 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301228 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001229 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 pPktMetaInfo->ucIsEapol = 1;
1231 }
1232 }
1233
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001234 if (pHddCtx->cfg_ini->gEnableDebugLog)
1235 {
1236 proto_type = vos_pkt_get_proto_type(skb,
1237 pHddCtx->cfg_ini->gEnableDebugLog);
1238 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1239 {
1240 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1241 "SAP TX EAPOL");
1242 }
1243 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1244 {
1245 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1246 "SAP TX DHCP");
1247 }
1248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001249//xg: @@@@: temporarily disble these. will revisit later
Jeff Johnson295189b2012-06-20 16:38:30 -07001250 {
1251 pPktMetaInfo->ucUP = pktNode->userPriority;
1252 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1253 }
1254
1255 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1256 //Extract the destination address from ethernet frame
1257 pDestMacAddress = (v_MACADDR_t*)skb->data;
1258
1259 // we need 802.3 to 802.11 frame translation
1260 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1261 pPktMetaInfo->ucDisableFrmXtl = 0;
1262 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1263 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1264
1265 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1266 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1267 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301268 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001269 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001270 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1271 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1272 }
1273
1274 // We're giving the packet to TL so consider it transmitted from
1275 // a statistics perspective. We account for it here instead of
1276 // when the packet is returned for two reasons. First, TL will
1277 // manipulate the skb to the point where the len field is not
1278 // accurate, leading to inaccurate byte counts if we account for
1279 // it later. Second, TL does not provide any feedback as to
1280 // whether or not the packet was successfully sent over the air,
1281 // so the packet counts will be the same regardless of where we
1282 // account for them
1283 pAdapter->stats.tx_bytes += skb->len;
1284 ++pAdapter->stats.tx_packets;
1285 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1286 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301287 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001288
c_hpothu6d1d2a32014-03-18 20:17:03 +05301289 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001290 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001291
1292 return status;
1293}
1294
1295
1296/**============================================================================
1297 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1298 case where VOS packets are not available at the time of the call to get
1299 packets. This callback function is invoked by VOS when packets are
1300 available.
1301
1302 @param pVosPacket : [in] pointer to VOS packet
1303 @param userData : [in] opaque user data that was passed initially
1304
1305 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1306 : VOS_STATUS_SUCCESS otherwise
1307 =============================================================================*/
1308VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1309 v_VOID_t *userData )
1310{
1311 VOS_STATUS status;
1312 v_SINT_t i = 0;
1313 v_SIZE_t size = 0;
1314 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1315 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1316
1317 if(pAdapter == NULL)
1318 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301319 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1320 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001321 return VOS_STATUS_E_FAILURE;
1322 }
1323
1324 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1325 //situation. Here we will only signal TL that there is a pending data for a STA.
1326 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1327 vos_pkt_return_packet( pVosPacket );
1328
1329 pAdapter->isVosOutOfResource = VOS_FALSE;
1330
1331 // Indicate to TL that there is pending data if a queue is non empty.
1332 // This Code wasnt included in earlier version which resulted in
1333 // Traffic stalling
1334 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1335 {
1336 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1337 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1338 {
1339 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1340 {
1341 size = 0;
1342 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1343 if ( size > 0 )
1344 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301345 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1346 STAId,
Jeff Johnson295189b2012-06-20 16:38:30 -07001347 (WLANTL_ACEnumType)i );
1348 if( !VOS_IS_STATUS_SUCCESS( status ) )
1349 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301350 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1351 "%s: Failure in indicating pkt to TL for ac=%d", __func__,i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001352 }
1353 }
1354 }
1355 }
1356 }
1357 return VOS_STATUS_SUCCESS;
1358}
1359
1360
1361/**============================================================================
1362 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1363 TL will call this to notify the HDD when one or more packets were
1364 received for a registered STA.
1365
1366 @param vosContext : [in] pointer to VOS context
1367 @param pVosPacketChain : [in] pointer to VOS packet chain
1368 @param staId : [in] Station Id (Adress 1 Index)
1369 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1370
1371 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1372 : VOS_STATUS_SUCCESS otherwise
1373 ===========================================================================*/
1374VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1375 vos_pkt_t *pVosPacketChain,
1376 v_U8_t staId,
1377 WLANTL_RxMetaInfoType* pRxMetaInfo )
1378{
1379 hdd_adapter_t *pAdapter = NULL;
1380 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1381 int rxstat;
1382 struct sk_buff *skb = NULL;
1383 vos_pkt_t* pVosPacket;
1384 vos_pkt_t* pNextVosPacket;
1385 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001386 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001387
1388 //Sanity check on inputs
1389 if ( ( NULL == vosContext ) ||
1390 ( NULL == pVosPacketChain ) ||
1391 ( NULL == pRxMetaInfo ) )
1392 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301393 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1394 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001395 return VOS_STATUS_E_FAILURE;
1396 }
1397
1398 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1399 if ( NULL == pHddCtx )
1400 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301401 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1402 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001403 return VOS_STATUS_E_FAILURE;
1404 }
1405
1406 pAdapter = pHddCtx->sta_to_adapter[staId];
1407 if( NULL == pAdapter )
1408 {
1409 VOS_ASSERT(0);
1410 return VOS_STATUS_E_FAILURE;
1411 }
Leo Chang64d68bc2013-06-04 15:40:52 -07001412
1413 /* Monitor traffic */
1414 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1415 {
1416 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1417 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1418 {
1419 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1420 /* It was IDLE mode,
1421 * this is new state, then switch mode from suspend to resume */
1422 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1423 {
1424 hdd_set_wlan_suspend_mode(0);
1425 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1426 pHddCtx->cfg_ini->trafficIdleTimeout);
1427 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1428 }
1429 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1430 }
1431 }
1432
Jeff Johnson295189b2012-06-20 16:38:30 -07001433 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1434
1435 // walk the chain until all are processed
1436 pVosPacket = pVosPacketChain;
1437 do
1438 {
1439 // get the pointer to the next packet in the chain
1440 // (but don't unlink the packet since we free the entire chain later)
1441 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1442
1443 // both "success" and "empty" are acceptable results
1444 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1445 {
1446 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301447 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1448 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 return VOS_STATUS_E_FAILURE;
1450 }
1451
1452 // Extract the OS packet (skb).
1453 // Tell VOS to detach the OS packet from the VOS packet
1454 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1455 if(!VOS_IS_STATUS_SUCCESS( status ))
1456 {
1457 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301458 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1459 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001460 return VOS_STATUS_E_FAILURE;
1461 }
1462
1463 //hdd_softap_dump_sk_buff(skb);
1464
1465 skb->dev = pAdapter->dev;
1466
1467 if(skb->dev == NULL) {
1468
c_hpothu6d1d2a32014-03-18 20:17:03 +05301469 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_FATAL,
1470 "ERROR!!Invalid netdevice");
Jeff Johnson295189b2012-06-20 16:38:30 -07001471 return VOS_STATUS_E_FAILURE;
1472 }
1473 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1474 ++pAdapter->stats.rx_packets;
1475 pAdapter->stats.rx_bytes += skb->len;
1476
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001477 if (pHddCtx->cfg_ini->gEnableDebugLog)
1478 {
1479 proto_type = vos_pkt_get_proto_type(skb,
1480 pHddCtx->cfg_ini->gEnableDebugLog);
1481 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1482 {
1483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1484 "SAP RX EAPOL");
1485 }
1486 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1487 {
1488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1489 "SAP RX DHCP");
1490 }
1491 }
1492
Jeff Johnson295189b2012-06-20 16:38:30 -07001493 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1494 {
1495 //MC/BC packets. Duplicate a copy of packet
1496 struct sk_buff *pSkbCopy;
1497 hdd_ap_ctx_t *pHddApCtx;
1498
1499 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1500 if (!(pHddApCtx->apDisableIntraBssFwd))
1501 {
1502 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1503 if (pSkbCopy)
1504 {
1505 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1506 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1507 }
1508 }
1509 else
1510 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301511 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001512 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001513 }
1514
1515
1516 } //(WLAN_RX_BCMC_STA_ID == staId)
1517
1518 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1519 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1520 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301521 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001522 "%s: send one packet to kernel", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001523
1524 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001525 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001526#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001527#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001528 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001529#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001530#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001531 rxstat = netif_rx_ni(skb);
1532 if (NET_RX_SUCCESS == rxstat)
1533 {
1534 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001535 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001536 }
1537 else
1538 {
1539 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1540 }
1541 }
1542 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1543 {
1544 kfree_skb(skb);
1545 }
1546 else
1547 {
1548 //loopback traffic
1549 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1550 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1551 }
1552
1553 // now process the next packet in the chain
1554 pVosPacket = pNextVosPacket;
1555
1556 } while (pVosPacket);
1557
1558 //Return the entire VOS packet chain to the resource pool
1559 status = vos_pkt_return_packet( pVosPacketChain );
1560 if(!VOS_IS_STATUS_SUCCESS( status ))
1561 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301562 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1563 "%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001564 }
1565
1566 pAdapter->dev->last_rx = jiffies;
1567
1568 return status;
1569}
1570
1571VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1572{
1573 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301574 hdd_context_t *pHddCtx;
1575 if (NULL == pAdapter)
1576 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301577 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301578 "%s: pAdapter is NULL", __func__);
1579 return VOS_STATUS_E_INVAL;
1580 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001581
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301582 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1583 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301584 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301585 "%s: Invalid pAdapter magic", __func__);
1586 return VOS_STATUS_E_INVAL;
1587 }
1588
1589 pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
c_hpothu6d1d2a32014-03-18 20:17:03 +05301590 //Clear station in TL and then update HDD data structures. This helps
Jeff Johnson295189b2012-06-20 16:38:30 -07001591 //to block RX frames from other station to this station.
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301592 vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001593 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1594 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301595 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001596 "WLANTL_ClearSTAClient() failed to for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001597 "Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001598 staId, vosStatus, vosStatus );
1599 }
1600
1601 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1602 if( VOS_STATUS_E_FAILURE == vosStatus )
1603 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301604 VOS_TRACE ( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001605 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001606 "Status = %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001607 staId, vosStatus, vosStatus );
1608 return( vosStatus );
1609 }
1610
1611 pHddCtx->sta_to_adapter[staId] = NULL;
1612
1613 return( vosStatus );
1614}
1615
1616VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1617 v_BOOL_t fAuthRequired,
1618 v_BOOL_t fPrivacyBit,
1619 v_U8_t staId,
1620 v_U8_t ucastSig,
1621 v_U8_t bcastSig,
1622 v_MACADDR_t *pPeerMacAddress,
1623 v_BOOL_t fWmmEnabled )
1624{
1625 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001626 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1628 hdd_adapter_t *pmonAdapter = NULL;
1629
1630 //eCsrEncryptionType connectedCipherAlgo;
1631 //v_BOOL_t fConnected;
1632
1633 /*
1634 * Clean up old entry if it is not cleaned up properly
1635 */
1636 if ( pAdapter->aStaInfo[staId].isUsed )
1637 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301638 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001639 "clean up old entry for STA %d", staId);
1640 hdd_softap_DeregisterSTA( pAdapter, staId );
1641 }
1642
1643 // Get the Station ID from the one saved during the assocation.
1644
1645 staDesc.ucSTAId = staId;
1646
1647
1648 /*Save the pAdapter Pointer for this staId*/
1649 pHddCtx->sta_to_adapter[staId] = pAdapter;
1650
1651 staDesc.wSTAType = WLAN_STA_SOFTAP;
1652
1653 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1654 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1655 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1656
c_hpothu6d1d2a32014-03-18 20:17:03 +05301657 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001658 "register station");
c_hpothu6d1d2a32014-03-18 20:17:03 +05301659 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001660 "station mac " MAC_ADDRESS_STR,
1661 MAC_ADDR_ARRAY(staDesc.vSTAMACAddress.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301662 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001663 "BSSIDforIBSS " MAC_ADDRESS_STR,
1664 MAC_ADDR_ARRAY(staDesc.vBSSIDforIBSS.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301665 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001666 "SOFTAP SELFMAC " MAC_ADDRESS_STR,
1667 MAC_ADDR_ARRAY(staDesc.vSelfMACAddress.bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07001668
1669 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1670
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 staDesc.ucQosEnabled = fWmmEnabled;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301672 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001673 "HDD SOFTAP register TL QoS_enabled=%d",
1674 staDesc.ucQosEnabled );
1675
1676 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1677
1678
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 // For PRIMA UMA frame translation is not enable yet.
1680 staDesc.ucSwFrameTXXlation = 1;
1681 staDesc.ucSwFrameRXXlation = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07001682 staDesc.ucAddRmvLLC = 1;
1683
1684 // Initialize signatures and state
1685 staDesc.ucUcastSig = ucastSig;
1686 staDesc.ucBcastSig = bcastSig;
1687 staDesc.ucInitState = fAuthRequired ?
1688 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1689
Prathyushaf5442802012-12-12 13:58:11 -08001690 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1691
Jeff Johnson295189b2012-06-20 16:38:30 -07001692 // Register the Station with TL...
c_hpothu6d1d2a32014-03-18 20:17:03 +05301693 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1694 hdd_softap_rx_packet_cbk,
1695 hdd_softap_tx_complete_cbk,
Jeff Johnson295189b2012-06-20 16:38:30 -07001696 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1697
1698 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1699 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301700 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001701 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001702 vosStatus, vosStatus );
1703 return vosStatus;
1704 }
1705
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001706 //Timer value should be in milliseconds
1707 if ( pHddCtx->cfg_ini->dynSplitscan &&
1708 ( VOS_TIMER_STATE_RUNNING !=
1709 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
1710 {
1711 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1712 pHddCtx->cfg_ini->trafficMntrTmrForSplitScan);
1713 }
1714
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1716 // then go to 'authenticated'. For all other authentication types (those that do
1717 // not require upper layer authentication) we can put TL directly into 'authenticated'
1718 // state.
1719
1720 //VOS_ASSERT( fConnected );
1721 pAdapter->aStaInfo[staId].ucSTAId = staId;
1722 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1723
1724 if ( !fAuthRequired )
1725 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301726 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
1727 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
1728 pAdapter->aStaInfo[staId].ucSTAId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001729
1730 // Connections that do not need Upper layer auth, transition TL directly
1731 // to 'Authenticated' state.
1732 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1733 WLANTL_STA_AUTHENTICATED );
1734
1735 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1736 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1737 }
1738 else
1739 {
1740
c_hpothu6d1d2a32014-03-18 20:17:03 +05301741 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001742 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1743
1744 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1745 WLANTL_STA_CONNECTED );
1746 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1747
1748 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1749
1750 }
1751 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1752 if(pmonAdapter)
1753 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301754 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
1755 "Turn on Monitor the carrier");
Jeff Johnson295189b2012-06-20 16:38:30 -07001756 netif_carrier_on(pmonAdapter->dev);
1757 //Enable Tx queue
1758 netif_tx_start_all_queues(pmonAdapter->dev);
1759 }
1760 netif_carrier_on(pAdapter->dev);
1761 //Enable Tx queue
1762 netif_tx_start_all_queues(pAdapter->dev);
1763
1764 return( vosStatus );
1765}
1766
1767VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1768{
1769 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1770 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1771 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1772
1773
1774 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1775 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1776 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1777
1778 return vosStatus;
1779}
1780
1781VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1782{
1783 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1784}
1785
1786VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1787{
Wilson Yangf80a0542013-10-07 13:02:37 -07001788 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001789 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1790 v_U8_t staId = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07001791 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1792
1793 /*bss deregister is not allowed during wlan driver loading or unloading*/
Mihir Shete18156292014-03-11 15:38:30 +05301794 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Wilson Yangf80a0542013-10-07 13:02:37 -07001795 {
1796 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1797 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
1798 return VOS_STATUS_E_PERM;
1799 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001800
1801 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1802
Jeff Johnson43971f52012-07-17 12:26:56 -07001803 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001804 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301805 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001806 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001807 }
1808
1809 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1810 {
1811 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
Jeff Johnson295189b2012-06-20 16:38:30 -07001812 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301813 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1814 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1815 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301816 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001817 "%s: Failed to deregister sta Id %d", __func__, staId);
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301818 }
1819 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001820 }
1821
1822 return vosStatus;
1823}
1824
1825VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1826{
1827 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1828 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1829 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001830
c_hpothu6d1d2a32014-03-18 20:17:03 +05301831 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001832 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001833
Jeff Johnson43971f52012-07-17 12:26:56 -07001834 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001835 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301836 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001837 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001838 return VOS_STATUS_E_FAILURE;
1839 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001840
1841 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1842 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301843 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001844 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001845 return VOS_STATUS_E_FAILURE;
1846 }
1847
1848 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
c_hpothu6d1d2a32014-03-18 20:17:03 +05301849 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001850 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001851
Jeff Johnson43971f52012-07-17 12:26:56 -07001852 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001853 {
1854 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1855 }
1856
c_hpothu6d1d2a32014-03-18 20:17:03 +05301857 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001858 "%s exit",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001859
1860 return vosStatus;
1861}
1862
1863
1864VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1865{
1866 v_U8_t i;
1867
1868 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1869 {
1870 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1871 pAdapter->aStaInfo[i].isUsed)
1872 {
1873 *staId = i;
1874 return VOS_STATUS_SUCCESS;
1875 }
1876 }
1877
1878 return VOS_STATUS_E_FAILURE;
1879}
1880
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301881VOS_STATUS hdd_softap_GetConnectedStaId(hdd_adapter_t *pAdapter, v_U8_t *staId)
1882{
1883 v_U8_t i;
1884
1885 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1886 {
Kiet Lam61589852013-09-19 17:10:58 +05301887 if (pAdapter->aStaInfo[i].isUsed &&
1888 (!vos_is_macaddr_broadcast(&pAdapter->aStaInfo[i].macAddrSTA)))
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301889 {
1890 *staId = i;
1891 return VOS_STATUS_SUCCESS;
1892 }
1893 }
1894
1895 return VOS_STATUS_E_FAILURE;
1896}