blob: 9c35a688765f0fb89013806e471820805ab8e305 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**===========================================================================
43
44 \file wlan_hdd_softap_tx_rx.c
45
46 \brief Linux HDD Tx/RX APIs
47 Copyright 2008 (c) Qualcomm, Incorporated.
48 All Rights Reserved.
49 Qualcomm Confidential and Proprietary.
50
51 ==========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070052
53/*---------------------------------------------------------------------------
54 Include files
55 -------------------------------------------------------------------------*/
56#include <linux/semaphore.h>
57#include <wlan_hdd_tx_rx.h>
58#include <wlan_hdd_softap_tx_rx.h>
59#include <wlan_hdd_dp_utils.h>
60#include <wlan_qct_tl.h>
61#include <linux/netdevice.h>
62#include <linux/skbuff.h>
63#include <linux/etherdevice.h>
64//#include <vos_list.h>
65#include <vos_types.h>
66#include <aniGlobal.h>
67#include <halTypes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070068#include <net/ieee80211_radiotap.h>
69
70
71/*---------------------------------------------------------------------------
72 Preprocessor definitions and constants
73 -------------------------------------------------------------------------*/
74
75/*---------------------------------------------------------------------------
76 Type declarations
77 -------------------------------------------------------------------------*/
78
79/*---------------------------------------------------------------------------
80 Function definitions and documenation
81 -------------------------------------------------------------------------*/
82#if 0
83static void hdd_softap_dump_sk_buff(struct sk_buff * skb)
84{
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070085 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: head = %p ", __func__, skb->head);
86 //VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data);
87 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p ", __func__, skb->tail);
88 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: end = %p ", __func__, skb->end);
89 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: len = %d ", __func__, skb->len);
90 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d ", __func__, skb->data_len);
91 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d\n", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -070092
93 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ",
94 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
95 skb->data[5], skb->data[6], skb->data[7]);
96 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n",
97 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
98 skb->data[13], skb->data[14], skb->data[15]);
99}
100#endif
Leo Chang64d68bc2013-06-04 15:40:52 -0700101
102extern void hdd_set_wlan_suspend_mode(bool suspend);
103
104/**============================================================================
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 {
119 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
120 "%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 {
Kiet Lambcf38522013-10-26 18:28:27 +0530128 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
129 "%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 */
170 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
171 "%s Start Traffic Monitor Timer", __func__);
172 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
173 pHddCtx->cfg_ini->trafficIdleTimeout);
174 }
175 else
176 {
177 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
178 "%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
190 if (0 != status)
191 {
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 {
202 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
203 "%s Stop Traffic Monitor Timer", __func__);
204 vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer);
205 }
206 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
207 "%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 }
212 return status;
213}
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
304 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, 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
318 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700319 "%s: BC/MC packet\n", __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 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700326 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, 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 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530335 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s: STA %d is unregistered", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700336 ++pAdapter->stats.tx_dropped;
337 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
338 kfree_skb(skb);
339 goto xmit_done;
340 }
341
342 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
343 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
344 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700345 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700346 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700347 ++pAdapter->stats.tx_dropped;
348 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
349 kfree_skb(skb);
350 goto xmit_done;
351 }
352 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
353 {
354 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
355 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700356 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700357 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700358 ++pAdapter->stats.tx_dropped;
359 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
360 kfree_skb(skb);
361 goto xmit_done;
362 }
363 }
364 }
365
366 //Get TL AC corresponding to Qdisc queue index/AC.
367 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
368 //user priority from IP header, which is already extracted and set from
369 //select_queue call back function
370 up = skb->priority;
371 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
372
373 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700374 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700375
376 // If the memory differentiation mode is enabled, the memory limit of each queue will be
377 // checked. Over-limit packets will be dropped.
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700378 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700379 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
380 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
381 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700382 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700383 "%s: station %d ac %d queue over limit %d \n", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700384 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
385 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
386 txSuspended = VOS_TRUE;
387 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530388
389 /* If 3/4th of the max queue size is used then enable the flag.
390 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
391 if (WLANTL_AC_BE == ac)
392 {
393 if (pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
394 {
395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
396 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
397 pAdapter->aStaInfo[STAId].vosLowResource = VOS_TRUE;
398 }
399 else
400 {
401 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
402 }
403 }
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700404 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700405
406 if (VOS_TRUE == txSuspended)
407 {
408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
409 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700410 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700411 os_status = NETDEV_TX_BUSY;
412 goto xmit_done;
413 }
414
415 //Use the skb->cb field to hold the list node information
416 pktNode = (skb_list_node_t *)&skb->cb;
417
418 //Stick the OS packet inside this node.
419 pktNode->skb = skb;
420
421 //Stick the User Priority inside this node
422 pktNode->userPriority = up;
423
424 INIT_LIST_HEAD(&pktNode->anchor);
425
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700426 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700427 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700428 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700429
430 if ( !VOS_IS_STATUS_SUCCESS( status ) )
431 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700432 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700433 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
434 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
435 ++pAdapter->stats.tx_dropped;
436 kfree_skb(skb);
437 goto xmit_done;
438 }
439
440 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
441 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
442
443 if (1 == pktListSize)
444 {
445 //Let TL know we have a packet to send for this AC
446 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
447
448 if ( !VOS_IS_STATUS_SUCCESS( status ) )
449 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700450 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d STAId =%d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700451 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700452
453 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
454 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
455 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
456 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
457 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
458 ++pAdapter->stats.tx_dropped;
459 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
460 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
461 kfree_skb(skb);
462 goto xmit_done;
463 }
464 }
465 dev->trans_start = jiffies;
466
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700467 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700468
469xmit_done:
470 spin_unlock_bh( &pAdapter->staInfo_lock );
471 return os_status;
472}
473
474/**============================================================================
475 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
476
477 @param skb : [in] pointer to packet (sk_buff)
478 @param dev : [in] pointer to Libra network device
479 @param STAId : [in] Station Id of Destination Station
480 @param up : [in] User Priority
481
482 @return : NET_XMIT_DROP if packets are dropped
483 : NET_XMIT_SUCCESS if packet is enqueued succesfully
484 ===========================================================================*/
485VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
486 struct net_device *dev,
487 v_U8_t STAId,
488 v_U8_t up)
489{
490 VOS_STATUS status = VOS_STATUS_SUCCESS;
491 skb_list_node_t *pktNode = NULL;
492 v_SIZE_t pktListSize = 0;
493 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
494 v_U8_t ac;
495 vos_list_node_t *anchor = NULL;
496
497 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
498
499 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700500 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700501
502 spin_lock_bh( &pAdapter->staInfo_lock );
503 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
504 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700505 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530506 "%s: STA %d is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700507 kfree_skb(skb);
508 status = VOS_STATUS_E_FAILURE;
509 goto xmit_end;
510 }
511
512 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
513 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
514 up = SME_QOS_WMM_UP_BE;
515
516 ac = hddWmmUpToAcMap[up];
517 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
518 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700519 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700520
521 skb->queue_mapping = hddLinuxUpToAcMap[up];
522
523 //Use the skb->cb field to hold the list node information
524 pktNode = (skb_list_node_t *)&skb->cb;
525
526 //Stick the OS packet inside this node.
527 pktNode->skb = skb;
528
529 //Stick the User Priority inside this node
530 pktNode->userPriority = up;
531
532 INIT_LIST_HEAD(&pktNode->anchor);
533
534 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
535 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
536 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
537 pktListSize >= pAdapter->aTxQueueLimit[ac])
538 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700539 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700540 "%s: station %d ac %d queue over limit %d \n", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700541 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
542 * SUSPEND should be done based on Threshold. RESUME would be
543 * triggered in fetch cbk after recovery.
544 */
545 kfree_skb(skb);
546 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
547 status = VOS_STATUS_E_FAILURE;
548 goto xmit_end;
549 }
550 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
551 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
552
553 if ( !VOS_IS_STATUS_SUCCESS( status ) )
554 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700555 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700556 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
557 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
558 ++pAdapter->stats.tx_dropped;
559 kfree_skb(skb);
560 status = VOS_STATUS_E_FAILURE;
561 goto xmit_end;
562 }
563
564 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
565 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
566
567 if (1 == pktListSize)
568 {
569 //Let TL know we have a packet to send for this AC
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700570 //VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700571 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
572
573 if ( !VOS_IS_STATUS_SUCCESS( status ) )
574 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700575 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d STAId =%d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700576 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700577
578 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
579 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
580 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
581 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
582 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
583 ++pAdapter->stats.tx_dropped;
584 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
585 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
586 kfree_skb(skb);
587 status = VOS_STATUS_E_FAILURE;
588 goto xmit_end;
589 }
590 }
591
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700592 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700593
594xmit_end:
595 spin_unlock_bh( &pAdapter->staInfo_lock );
596 return status;
597}
598
599/**============================================================================
600 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
601 timeout during transmission. Since HDD simply enqueues packet
602 and returns control to OS right away, this would never be invoked
603
604 @param dev : [in] pointer to Libra network device
605 @return : None
606 ===========================================================================*/
607void hdd_softap_tx_timeout(struct net_device *dev)
608{
609 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700610 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 //Getting here implies we disabled the TX queues for too long. Queues are
612 //disabled either because of disassociation or low resource scenarios. In
613 //case of disassociation it is ok to ignore this. But if associated, we have
614 //do possible recovery here
615}
616
617
618/**============================================================================
619 @brief hdd_softap_stats() - Function registered with the Linux OS for
620 device TX/RX statistic
621
622 @param dev : [in] pointer to Libra network device
623
624 @return : pointer to net_device_stats structure
625 ===========================================================================*/
626struct net_device_stats* hdd_softap_stats(struct net_device *dev)
627{
628 hdd_adapter_t* priv = netdev_priv(dev);
629 return &priv->stats;
630}
631
632
633/**============================================================================
634 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
635 modules in HDD
636
637 @param pAdapter : [in] pointer to adapter context
638 @return : VOS_STATUS_E_FAILURE if any errors encountered
639 : VOS_STATUS_SUCCESS otherwise
640 ===========================================================================*/
641VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
642{
643 VOS_STATUS status = VOS_STATUS_SUCCESS;
644 v_SINT_t i = -1;
645 v_SIZE_t size = 0;
646
647 v_U8_t STAId = 0;
648
649 v_U8_t pACWeights[] = {
650 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
651 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
652 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
653 HDD_SOFTAP_VO_WEIGHT_DEFAULT
654 };
Leo Chang64d68bc2013-06-04 15:40:52 -0700655
Jeff Johnson295189b2012-06-20 16:38:30 -0700656 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530657 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700658
659 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
660
661 while (++i != NUM_TX_QUEUES)
662 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
663
664 /* Initial HDD buffer control / flow control fields*/
665 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
666
667 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
668 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
669 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
670 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
671
672 spin_lock_init( &pAdapter->staInfo_lock );
673
674 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
675 {
676 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
677 for (i = 0; i < NUM_TX_QUEUES; i ++)
678 {
679 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
680 }
681 }
682
Yue Ma3ede6052013-08-29 00:33:26 -0700683 /* Update the AC weights suitable for SoftAP mode of operation */
684 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
685
Kiet Lambcf38522013-10-26 18:28:27 +0530686 if (VOS_STATUS_SUCCESS != hdd_start_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700687 {
Kiet Lambcf38522013-10-26 18:28:27 +0530688 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
689 "%s: failed to start Traffic Monito timer ", __func__ );
690 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700691 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700692 return status;
693}
694
695/**============================================================================
696 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
697 modules in HDD
698
699 @param pAdapter : [in] pointer to adapter context
700 @return : VOS_STATUS_E_FAILURE if any errors encountered
701 : VOS_STATUS_SUCCESS otherwise
702 ===========================================================================*/
703VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
704{
705 VOS_STATUS status = VOS_STATUS_SUCCESS;
Leo Chang64d68bc2013-06-04 15:40:52 -0700706
Kiet Lambcf38522013-10-26 18:28:27 +0530707 if (VOS_STATUS_SUCCESS != hdd_stop_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700708 {
Kiet Lambcf38522013-10-26 18:28:27 +0530709 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
710 "%s: Fail to Stop Traffic Monito timer", __func__ );
711 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700712 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700713
714 status = hdd_softap_flush_tx_queues(pAdapter);
715
716 return status;
717}
718
719/**============================================================================
720 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
721
722 @param pAdapter : [in] pointer to adapter context
723 @param STAId : [in] Station ID to deinit
724 @return : VOS_STATUS_E_FAILURE if any errors encountered
725 : VOS_STATUS_SUCCESS otherwise
726 ===========================================================================*/
727static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
728{
729 VOS_STATUS status = VOS_STATUS_SUCCESS;
730 v_U8_t i = -1;
731
732 hdd_list_node_t *anchor = NULL;
733
734 skb_list_node_t *pktNode = NULL;
735 struct sk_buff *skb = NULL;
736
737 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
738 {
739 return status;
740 }
741
742 for (i = 0; i < NUM_TX_QUEUES; i ++)
743 {
744 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
745 while (true)
746 {
747 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
748 if (VOS_STATUS_E_EMPTY != status)
749 {
750 //If success then we got a valid packet from some AC
751 pktNode = list_entry(anchor, skb_list_node_t, anchor);
752 skb = pktNode->skb;
753 ++pAdapter->stats.tx_dropped;
754 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
755 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
756 kfree_skb(skb);
757 continue;
758 }
759
760 //current list is empty
761 break;
762 }
763 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
764 }
765
766 return status;
767}
768
769/**============================================================================
770 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
771 modules in HDD
772
773 @param pAdapter : [in] pointer to adapter context
774 @param STAId : [in] Station ID to deinit
775 @param pmacAddrSTA : [in] pointer to the MAC address of the station
776 @return : VOS_STATUS_E_FAILURE if any errors encountered
777 : VOS_STATUS_SUCCESS otherwise
778 ===========================================================================*/
779VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
780{
781 v_U8_t i = 0;
782 spin_lock_bh( &pAdapter->staInfo_lock );
783 if (pAdapter->aStaInfo[STAId].isUsed)
784 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700785 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700786 spin_unlock_bh( &pAdapter->staInfo_lock );
787 return VOS_STATUS_E_FAILURE;
788 }
789
790 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
791 for (i = 0; i < NUM_TX_QUEUES; i ++)
792 {
793 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
794 }
795
796 pAdapter->aStaInfo[STAId].isUsed = TRUE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800797 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700798 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
799
800 spin_unlock_bh( &pAdapter->staInfo_lock );
801 return VOS_STATUS_SUCCESS;
802}
803
804/**============================================================================
805 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
806 modules in HDD
807
808 @param pAdapter : [in] pointer to adapter context
809 @param STAId : [in] Station ID to deinit
810 @return : VOS_STATUS_E_FAILURE if any errors encountered
811 : VOS_STATUS_SUCCESS otherwise
812 ===========================================================================*/
813VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
814{
815 VOS_STATUS status = VOS_STATUS_SUCCESS;
816 v_U8_t ac;
817 /**Track whether OS TX queue has been disabled.*/
818 v_BOOL_t txSuspended[NUM_TX_QUEUES];
819 v_U8_t tlAC;
820 hdd_hostapd_state_t *pHostapdState;
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700821 v_U8_t i;
Jeff Johnson295189b2012-06-20 16:38:30 -0700822
823 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
824
825 spin_lock_bh( &pAdapter->staInfo_lock );
826 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
827 {
828 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700829 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700830 spin_unlock_bh( &pAdapter->staInfo_lock );
831 return VOS_STATUS_E_FAILURE;
832 }
833
834 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
835
836 pAdapter->aStaInfo[STAId].isUsed = FALSE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800837 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700838
839 /* if this STA had any of its WMM TX queues suspended, then the
840 associated queue on the network interface was disabled. check
841 to see if that is the case, in which case we need to re-enable
842 the interface queue. but we only do this if the BSS is running
843 since, if the BSS is stopped, all of the interfaces have been
844 stopped and should not be re-enabled */
845
846 if (BSS_START == pHostapdState->bssState)
847 {
848 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
849 {
850 tlAC = hdd_QdiscAcToTlAC[ac];
851 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
852 }
853 }
854 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
855
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700856 /* re-init spin lock, since netdev can still open adapter until
857 * driver gets unloaded
858 */
859 for (i = 0; i < NUM_TX_QUEUES; i ++)
860 {
861 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
862 HDD_TX_QUEUE_MAX_LEN);
863 }
864
Jeff Johnson295189b2012-06-20 16:38:30 -0700865 if (BSS_START == pHostapdState->bssState)
866 {
867 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
868 {
869 if (txSuspended[ac])
870 {
871 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700872 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700873 netif_wake_subqueue(pAdapter->dev, ac);
874 }
875 }
876 }
877
878 spin_unlock_bh( &pAdapter->staInfo_lock );
879 return status;
880}
881
882/**============================================================================
883 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
884 modules in HDD
885
886 @param pAdapter : [in] pointer to adapter context
887 @return : VOS_STATUS_E_FAILURE if any errors encountered
888 : VOS_STATUS_SUCCESS otherwise
889 ===========================================================================*/
890VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
891{
892 return hdd_softap_flush_tx_queues(pAdapter);
893}
894
895/**============================================================================
896 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
897 to indicate that a packet has been transmitted across the bus
898 succesfully. OS packet resources can be released after this cbk.
899
900 @param vosContext : [in] pointer to VOS context
901 @param pVosPacket : [in] pointer to VOS packet (containing skb)
902 @param vosStatusIn : [in] status of the transmission
903
904 @return : VOS_STATUS_E_FAILURE if any errors encountered
905 : VOS_STATUS_SUCCESS otherwise
906 ===========================================================================*/
907VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
908 vos_pkt_t *pVosPacket,
909 VOS_STATUS vosStatusIn )
910{
911 VOS_STATUS status = VOS_STATUS_SUCCESS;
912 hdd_adapter_t *pAdapter = NULL;
913 void* pOsPkt = NULL;
914
915 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
916 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700917 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700918 return VOS_STATUS_E_FAILURE;
919 }
920
921 //Return the skb to the OS
922 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
923 if(!VOS_IS_STATUS_SUCCESS( status ))
924 {
925 //This is bad but still try to free the VOSS resources if we can
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700926 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 vos_pkt_return_packet( pVosPacket );
928 return VOS_STATUS_E_FAILURE;
929 }
930
931 //Get the Adapter context.
932 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
933 if(pAdapter == NULL)
934 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700935 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700936 }
937 else
938 {
939 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
940 }
941
942 kfree_skb((struct sk_buff *)pOsPkt);
943
944 //Return the VOS packet resources.
945 status = vos_pkt_return_packet( pVosPacket );
946 if(!VOS_IS_STATUS_SUCCESS( status ))
947 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700948 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700949 }
950
951 return status;
952}
953
954
955/**============================================================================
956 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
957 fetch a packet for transmission.
958
959 @param vosContext : [in] pointer to VOS context
960 @param staId : [in] Station for which TL is requesting a pkt
961 @param ac : [in] access category requested by TL
962 @param pVosPacket : [out] pointer to VOS packet packet pointer
963 @param pPktMetaInfo : [out] pointer to meta info for the pkt
964
965 @return : VOS_STATUS_E_EMPTY if no packets to transmit
966 : VOS_STATUS_E_FAILURE if any errors encountered
967 : VOS_STATUS_SUCCESS otherwise
968 ===========================================================================*/
969VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
970 v_U8_t *pStaId,
971 WLANTL_ACEnumType ac,
972 vos_pkt_t **ppVosPacket,
973 WLANTL_MetaInfoType *pPktMetaInfo )
974{
975 VOS_STATUS status = VOS_STATUS_E_FAILURE;
976 hdd_adapter_t *pAdapter = NULL;
977 hdd_list_node_t *anchor = NULL;
978 skb_list_node_t *pktNode = NULL;
979 struct sk_buff *skb = NULL;
980 vos_pkt_t *pVosPacket = NULL;
981 v_MACADDR_t* pDestMacAddress = NULL;
982 v_TIME_t timestamp;
983 v_SIZE_t size = 0;
984 v_U8_t STAId = WLAN_MAX_STA_COUNT;
985 hdd_context_t *pHddCtx = NULL;
986
987 //Sanity check on inputs
988 if ( ( NULL == vosContext ) ||
989 ( NULL == pStaId ) ||
990 ( NULL == ppVosPacket ) ||
991 ( NULL == pPktMetaInfo ) )
992 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700993 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700994 return VOS_STATUS_E_FAILURE;
995 }
996
997 //Get the HDD context.
998 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
999 if ( NULL == pHddCtx )
1000 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001001 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 return VOS_STATUS_E_FAILURE;
1003 }
1004
1005 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
1006 if( NULL == pAdapter )
1007 {
1008 VOS_ASSERT(0);
1009 return VOS_STATUS_E_FAILURE;
1010 }
1011
Leo Chang64d68bc2013-06-04 15:40:52 -07001012 /* Monitor traffic */
1013 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1014 {
1015 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1016 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1017 {
1018 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1019 /* It was IDLE mode,
1020 * this is new state, then switch mode from suspend to resume */
1021 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1022 {
1023 hdd_set_wlan_suspend_mode(0);
1024 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1025 pHddCtx->cfg_ini->trafficIdleTimeout);
1026 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1027 }
1028 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1029 }
1030 }
1031
Jeff Johnson295189b2012-06-20 16:38:30 -07001032 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1033
1034 STAId = *pStaId;
1035 if (STAId >= WLAN_MAX_STA_COUNT)
1036 {
1037 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001038 "%s: Invalid STAId %d passed by TL", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001039 return VOS_STATUS_E_FAILURE;
1040 }
1041
1042 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
1043 {
1044 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001045 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001046 return VOS_STATUS_E_FAILURE;
1047 }
1048
1049 *ppVosPacket = NULL;
1050
1051 //Make sure the AC being asked for is sane
1052 if( ac > WLANTL_MAX_AC || ac < 0)
1053 {
1054 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001055 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001056 return VOS_STATUS_E_FAILURE;
1057 }
1058
1059 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1060
1061 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001062 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001063
1064 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1065 //This simplifies the locking and unlocking of Tx queue
1066 status = vos_pkt_wrap_data_packet( &pVosPacket,
1067 VOS_PKT_TYPE_TX_802_3_DATA,
1068 NULL, //OS Pkt is not being passed
1069 hdd_softap_tx_low_resource_cbk,
1070 pAdapter );
1071
1072 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1073 {
1074 //Remember VOS is in a low resource situation
1075 pAdapter->isVosOutOfResource = VOS_TRUE;
1076 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
1077 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001078 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001079 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1080 return VOS_STATUS_E_FAILURE;
1081 }
1082
1083 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
1084 as the other branch does.
1085 */
1086 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1087 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
1088
1089 if (0 == size)
1090 {
1091 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1092 vos_pkt_return_packet(pVosPacket);
1093 return VOS_STATUS_E_EMPTY;
1094 }
1095
1096 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1097 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1098
1099 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001100 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001101
1102 if(VOS_STATUS_SUCCESS == status)
1103 {
1104 //If success then we got a valid packet from some AC
1105 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1106 skb = pktNode->skb;
1107 }
1108 else
1109 {
1110 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1111 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1112 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001113 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001114 vos_pkt_return_packet(pVosPacket);
1115 return VOS_STATUS_E_FAILURE;
1116 }
1117
1118 //Attach skb to VOS packet.
1119 status = vos_pkt_set_os_packet( pVosPacket, skb );
1120 if (status != VOS_STATUS_SUCCESS)
1121 {
1122 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001123 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001124 vos_pkt_return_packet(pVosPacket);
1125 ++pAdapter->stats.tx_dropped;
1126 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1127 kfree_skb(skb);
1128 return VOS_STATUS_E_FAILURE;
1129 }
1130
1131 //Just being paranoid. To be removed later
1132 if(pVosPacket == NULL)
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001135 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001136 ++pAdapter->stats.tx_dropped;
1137 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1138 kfree_skb(skb);
1139 return VOS_STATUS_E_FAILURE;
1140 }
1141
1142 //Return VOS packet to TL;
1143 *ppVosPacket = pVosPacket;
1144
1145 //Fill out the meta information needed by TL
1146 //FIXME This timestamp is really the time stamp of wrap_data_packet
1147 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1148 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1149 if ( 1 < size )
1150 {
1151 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1152 }
1153 else
1154 {
1155 pPktMetaInfo->bMorePackets = 0;
1156 }
1157
1158 pPktMetaInfo->ucIsEapol = 0;
1159
1160 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
1161 {
1162 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
1163 {
1164 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001165 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001166 pPktMetaInfo->ucIsEapol = 1;
1167 }
1168 }
1169
1170//xg: @@@@: temporarily disble these. will revisit later
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 {
1172 pPktMetaInfo->ucUP = pktNode->userPriority;
1173 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1174 }
1175
1176 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1177 //Extract the destination address from ethernet frame
1178 pDestMacAddress = (v_MACADDR_t*)skb->data;
1179
1180 // we need 802.3 to 802.11 frame translation
1181 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1182 pPktMetaInfo->ucDisableFrmXtl = 0;
1183 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1184 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1185
1186 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1187 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1188 {
1189 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001190 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001191 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1192 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1193 }
1194
1195 // We're giving the packet to TL so consider it transmitted from
1196 // a statistics perspective. We account for it here instead of
1197 // when the packet is returned for two reasons. First, TL will
1198 // manipulate the skb to the point where the len field is not
1199 // accurate, leading to inaccurate byte counts if we account for
1200 // it later. Second, TL does not provide any feedback as to
1201 // whether or not the packet was successfully sent over the air,
1202 // so the packet counts will be the same regardless of where we
1203 // account for them
1204 pAdapter->stats.tx_bytes += skb->len;
1205 ++pAdapter->stats.tx_packets;
1206 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1207 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1208
1209 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001210 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001211
1212 return status;
1213}
1214
1215
1216/**============================================================================
1217 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1218 case where VOS packets are not available at the time of the call to get
1219 packets. This callback function is invoked by VOS when packets are
1220 available.
1221
1222 @param pVosPacket : [in] pointer to VOS packet
1223 @param userData : [in] opaque user data that was passed initially
1224
1225 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1226 : VOS_STATUS_SUCCESS otherwise
1227 =============================================================================*/
1228VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1229 v_VOID_t *userData )
1230{
1231 VOS_STATUS status;
1232 v_SINT_t i = 0;
1233 v_SIZE_t size = 0;
1234 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1235 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1236
1237 if(pAdapter == NULL)
1238 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001239 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001240 return VOS_STATUS_E_FAILURE;
1241 }
1242
1243 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1244 //situation. Here we will only signal TL that there is a pending data for a STA.
1245 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1246 vos_pkt_return_packet( pVosPacket );
1247
1248 pAdapter->isVosOutOfResource = VOS_FALSE;
1249
1250 // Indicate to TL that there is pending data if a queue is non empty.
1251 // This Code wasnt included in earlier version which resulted in
1252 // Traffic stalling
1253 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1254 {
1255 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1256 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1257 {
1258 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1259 {
1260 size = 0;
1261 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1262 if ( size > 0 )
1263 {
1264 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1265 STAId,
1266 (WLANTL_ACEnumType)i );
1267 if( !VOS_IS_STATUS_SUCCESS( status ) )
1268 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001269 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure in indicating pkt to TL for ac=%d", __func__,i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001270 }
1271 }
1272 }
1273 }
1274 }
1275 return VOS_STATUS_SUCCESS;
1276}
1277
1278
1279/**============================================================================
1280 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1281 TL will call this to notify the HDD when one or more packets were
1282 received for a registered STA.
1283
1284 @param vosContext : [in] pointer to VOS context
1285 @param pVosPacketChain : [in] pointer to VOS packet chain
1286 @param staId : [in] Station Id (Adress 1 Index)
1287 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1288
1289 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1290 : VOS_STATUS_SUCCESS otherwise
1291 ===========================================================================*/
1292VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1293 vos_pkt_t *pVosPacketChain,
1294 v_U8_t staId,
1295 WLANTL_RxMetaInfoType* pRxMetaInfo )
1296{
1297 hdd_adapter_t *pAdapter = NULL;
1298 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1299 int rxstat;
1300 struct sk_buff *skb = NULL;
1301 vos_pkt_t* pVosPacket;
1302 vos_pkt_t* pNextVosPacket;
1303 hdd_context_t *pHddCtx = NULL;
1304
1305 //Sanity check on inputs
1306 if ( ( NULL == vosContext ) ||
1307 ( NULL == pVosPacketChain ) ||
1308 ( NULL == pRxMetaInfo ) )
1309 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001310 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001311 return VOS_STATUS_E_FAILURE;
1312 }
1313
1314 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1315 if ( NULL == pHddCtx )
1316 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001317 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 return VOS_STATUS_E_FAILURE;
1319 }
1320
1321 pAdapter = pHddCtx->sta_to_adapter[staId];
1322 if( NULL == pAdapter )
1323 {
1324 VOS_ASSERT(0);
1325 return VOS_STATUS_E_FAILURE;
1326 }
Leo Chang64d68bc2013-06-04 15:40:52 -07001327
1328 /* Monitor traffic */
1329 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1330 {
1331 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1332 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1333 {
1334 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1335 /* It was IDLE mode,
1336 * this is new state, then switch mode from suspend to resume */
1337 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1338 {
1339 hdd_set_wlan_suspend_mode(0);
1340 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1341 pHddCtx->cfg_ini->trafficIdleTimeout);
1342 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1343 }
1344 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1345 }
1346 }
1347
Jeff Johnson295189b2012-06-20 16:38:30 -07001348 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1349
1350 // walk the chain until all are processed
1351 pVosPacket = pVosPacketChain;
1352 do
1353 {
1354 // get the pointer to the next packet in the chain
1355 // (but don't unlink the packet since we free the entire chain later)
1356 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1357
1358 // both "success" and "empty" are acceptable results
1359 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1360 {
1361 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001362 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001363 return VOS_STATUS_E_FAILURE;
1364 }
1365
1366 // Extract the OS packet (skb).
1367 // Tell VOS to detach the OS packet from the VOS packet
1368 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1369 if(!VOS_IS_STATUS_SUCCESS( status ))
1370 {
1371 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001372 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001373 return VOS_STATUS_E_FAILURE;
1374 }
1375
1376 //hdd_softap_dump_sk_buff(skb);
1377
1378 skb->dev = pAdapter->dev;
1379
1380 if(skb->dev == NULL) {
1381
1382 hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR!!Invalid netdevice\n");
1383 return VOS_STATUS_E_FAILURE;
1384 }
1385 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1386 ++pAdapter->stats.rx_packets;
1387 pAdapter->stats.rx_bytes += skb->len;
1388
1389 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1390 {
1391 //MC/BC packets. Duplicate a copy of packet
1392 struct sk_buff *pSkbCopy;
1393 hdd_ap_ctx_t *pHddApCtx;
1394
1395 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1396 if (!(pHddApCtx->apDisableIntraBssFwd))
1397 {
1398 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1399 if (pSkbCopy)
1400 {
1401 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1402 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1403 }
1404 }
1405 else
1406 {
1407 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001408 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001409 }
1410
1411
1412 } //(WLAN_RX_BCMC_STA_ID == staId)
1413
1414 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1415 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1416 {
1417 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001418 "%s: send one packet to kernel \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001419
1420 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001421 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001422#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001423#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001424 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001425#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001426#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001427 rxstat = netif_rx_ni(skb);
1428 if (NET_RX_SUCCESS == rxstat)
1429 {
1430 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001431 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001432 }
1433 else
1434 {
1435 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1436 }
1437 }
1438 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1439 {
1440 kfree_skb(skb);
1441 }
1442 else
1443 {
1444 //loopback traffic
1445 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1446 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1447 }
1448
1449 // now process the next packet in the chain
1450 pVosPacket = pNextVosPacket;
1451
1452 } while (pVosPacket);
1453
1454 //Return the entire VOS packet chain to the resource pool
1455 status = vos_pkt_return_packet( pVosPacketChain );
1456 if(!VOS_IS_STATUS_SUCCESS( status ))
1457 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001458 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001459 }
1460
1461 pAdapter->dev->last_rx = jiffies;
1462
1463 return status;
1464}
1465
1466VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1467{
1468 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301469 hdd_context_t *pHddCtx;
1470 if (NULL == pAdapter)
1471 {
1472 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1473 "%s: pAdapter is NULL", __func__);
1474 return VOS_STATUS_E_INVAL;
1475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001476
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301477 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1478 {
1479 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1480 "%s: Invalid pAdapter magic", __func__);
1481 return VOS_STATUS_E_INVAL;
1482 }
1483
1484 pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001485 //Clear station in TL and then update HDD data structures. This helps
1486 //to block RX frames from other station to this station.
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301487 vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001488 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1489 {
1490 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1491 "WLANTL_ClearSTAClient() failed to for staID %d. "
1492 "Status= %d [0x%08lX]",
1493 staId, vosStatus, vosStatus );
1494 }
1495
1496 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1497 if( VOS_STATUS_E_FAILURE == vosStatus )
1498 {
1499 VOS_TRACE ( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1500 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
1501 "Status = %d [0x%08lX]",
1502 staId, vosStatus, vosStatus );
1503 return( vosStatus );
1504 }
1505
1506 pHddCtx->sta_to_adapter[staId] = NULL;
1507
1508 return( vosStatus );
1509}
1510
1511VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1512 v_BOOL_t fAuthRequired,
1513 v_BOOL_t fPrivacyBit,
1514 v_U8_t staId,
1515 v_U8_t ucastSig,
1516 v_U8_t bcastSig,
1517 v_MACADDR_t *pPeerMacAddress,
1518 v_BOOL_t fWmmEnabled )
1519{
1520 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001521 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1523 hdd_adapter_t *pmonAdapter = NULL;
1524
1525 //eCsrEncryptionType connectedCipherAlgo;
1526 //v_BOOL_t fConnected;
1527
1528 /*
1529 * Clean up old entry if it is not cleaned up properly
1530 */
1531 if ( pAdapter->aStaInfo[staId].isUsed )
1532 {
1533 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1534 "clean up old entry for STA %d", staId);
1535 hdd_softap_DeregisterSTA( pAdapter, staId );
1536 }
1537
1538 // Get the Station ID from the one saved during the assocation.
1539
1540 staDesc.ucSTAId = staId;
1541
1542
1543 /*Save the pAdapter Pointer for this staId*/
1544 pHddCtx->sta_to_adapter[staId] = pAdapter;
1545
1546 staDesc.wSTAType = WLAN_STA_SOFTAP;
1547
1548 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1549 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1550 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1551
1552 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1553 "register station \n");
1554 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1555 "station mac %02x:%02x:%02x:%02x:%02x:%02x",
1556 staDesc.vSTAMACAddress.bytes[0],
1557 staDesc.vSTAMACAddress.bytes[1],
1558 staDesc.vSTAMACAddress.bytes[2],
1559 staDesc.vSTAMACAddress.bytes[3],
1560 staDesc.vSTAMACAddress.bytes[4],
1561 staDesc.vSTAMACAddress.bytes[5]);
1562 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1563 "BSSIDforIBSS %02x:%02x:%02x:%02x:%02x:%02x",
1564 staDesc.vBSSIDforIBSS.bytes[0],
1565 staDesc.vBSSIDforIBSS.bytes[1],
1566 staDesc.vBSSIDforIBSS.bytes[2],
1567 staDesc.vBSSIDforIBSS.bytes[3],
1568 staDesc.vBSSIDforIBSS.bytes[4],
1569 staDesc.vBSSIDforIBSS.bytes[5]);
1570 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1571 "SOFTAP SELFMAC %02x:%02x:%02x:%02x:%02x:%02x",
1572 staDesc.vSelfMACAddress.bytes[0],
1573 staDesc.vSelfMACAddress.bytes[1],
1574 staDesc.vSelfMACAddress.bytes[2],
1575 staDesc.vSelfMACAddress.bytes[3],
1576 staDesc.vSelfMACAddress.bytes[4],
1577 staDesc.vSelfMACAddress.bytes[5]);
1578
1579 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1580
Jeff Johnson295189b2012-06-20 16:38:30 -07001581 staDesc.ucQosEnabled = fWmmEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07001582 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1583 "HDD SOFTAP register TL QoS_enabled=%d",
1584 staDesc.ucQosEnabled );
1585
1586 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1587
1588
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 // For PRIMA UMA frame translation is not enable yet.
1590 staDesc.ucSwFrameTXXlation = 1;
1591 staDesc.ucSwFrameRXXlation = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 staDesc.ucAddRmvLLC = 1;
1593
1594 // Initialize signatures and state
1595 staDesc.ucUcastSig = ucastSig;
1596 staDesc.ucBcastSig = bcastSig;
1597 staDesc.ucInitState = fAuthRequired ?
1598 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1599
Prathyushaf5442802012-12-12 13:58:11 -08001600 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1601
Jeff Johnson295189b2012-06-20 16:38:30 -07001602 // Register the Station with TL...
1603 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1604 hdd_softap_rx_packet_cbk,
1605 hdd_softap_tx_complete_cbk,
1606 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1607
1608 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1609 {
1610 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1611 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08lX]",
1612 vosStatus, vosStatus );
1613 return vosStatus;
1614 }
1615
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001616 //Timer value should be in milliseconds
1617 if ( pHddCtx->cfg_ini->dynSplitscan &&
1618 ( VOS_TIMER_STATE_RUNNING !=
1619 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
1620 {
1621 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1622 pHddCtx->cfg_ini->trafficMntrTmrForSplitScan);
1623 }
1624
Jeff Johnson295189b2012-06-20 16:38:30 -07001625 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1626 // then go to 'authenticated'. For all other authentication types (those that do
1627 // not require upper layer authentication) we can put TL directly into 'authenticated'
1628 // state.
1629
1630 //VOS_ASSERT( fConnected );
1631 pAdapter->aStaInfo[staId].ucSTAId = staId;
1632 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1633
1634 if ( !fAuthRequired )
1635 {
1636 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1637 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1638
1639 // Connections that do not need Upper layer auth, transition TL directly
1640 // to 'Authenticated' state.
1641 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1642 WLANTL_STA_AUTHENTICATED );
1643
1644 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1645 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1646 }
1647 else
1648 {
1649
1650 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1651 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1652
1653 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1654 WLANTL_STA_CONNECTED );
1655 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1656
1657 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1658
1659 }
1660 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1661 if(pmonAdapter)
1662 {
1663 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Turn on Monitor the carrier\n");
1664 netif_carrier_on(pmonAdapter->dev);
1665 //Enable Tx queue
1666 netif_tx_start_all_queues(pmonAdapter->dev);
1667 }
1668 netif_carrier_on(pAdapter->dev);
1669 //Enable Tx queue
1670 netif_tx_start_all_queues(pAdapter->dev);
1671
1672 return( vosStatus );
1673}
1674
1675VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1676{
1677 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1678 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1679 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1680
1681
1682 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1683 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1684 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1685
1686 return vosStatus;
1687}
1688
1689VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1690{
1691 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1692}
1693
1694VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1695{
Wilson Yangf80a0542013-10-07 13:02:37 -07001696 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1698 v_U8_t staId = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07001699 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1700
1701 /*bss deregister is not allowed during wlan driver loading or unloading*/
1702 if (pHddCtx->isLoadUnloadInProgress)
1703 {
1704 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1705 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
1706 return VOS_STATUS_E_PERM;
1707 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001708
1709 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1710
Jeff Johnson43971f52012-07-17 12:26:56 -07001711 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001712 {
1713 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001714 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 }
1716
1717 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1718 {
1719 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
1720 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1721
Jeff Johnson43971f52012-07-17 12:26:56 -07001722 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001723 {
1724 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001725 "%s: Failed to deregister sta Id %d", __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001726 }
1727 }
1728
1729 return vosStatus;
1730}
1731
1732VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1733{
1734 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1735 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1736 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001737
1738 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001739 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001740
Jeff Johnson43971f52012-07-17 12:26:56 -07001741 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001742 {
1743 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001744 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001745 return VOS_STATUS_E_FAILURE;
1746 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001747
1748 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1749 {
1750 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001751 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001752 return VOS_STATUS_E_FAILURE;
1753 }
1754
1755 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
1756 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001757 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001758
Jeff Johnson43971f52012-07-17 12:26:56 -07001759 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001760 {
1761 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1762 }
1763
1764 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001765 "%s exit\n",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001766
1767 return vosStatus;
1768}
1769
1770
1771VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1772{
1773 v_U8_t i;
1774
1775 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1776 {
1777 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1778 pAdapter->aStaInfo[i].isUsed)
1779 {
1780 *staId = i;
1781 return VOS_STATUS_SUCCESS;
1782 }
1783 }
1784
1785 return VOS_STATUS_E_FAILURE;
1786}
1787
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301788VOS_STATUS hdd_softap_GetConnectedStaId(hdd_adapter_t *pAdapter, v_U8_t *staId)
1789{
1790 v_U8_t i;
1791
1792 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1793 {
Kiet Lam61589852013-09-19 17:10:58 +05301794 if (pAdapter->aStaInfo[i].isUsed &&
1795 (!vos_is_macaddr_broadcast(&pAdapter->aStaInfo[i].macAddrSTA)))
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301796 {
1797 *staId = i;
1798 return VOS_STATUS_SUCCESS;
1799 }
1800 }
1801
1802 return VOS_STATUS_E_FAILURE;
1803}