blob: 7326079bf7060d8f91dba5d7b6098a1639119fd7 [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 {
128 hdd_set_wlan_suspend_mode(1);
129 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0);
130 }
131 else
132 {
133 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
134 pHddCtx->cfg_ini->trafficIdleTimeout);
135 }
136
137 return;
138}
139
Jeff Johnson295189b2012-06-20 16:38:30 -0700140/**============================================================================
141 @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
142
143 @param pAdapter : [in] pointer to adapter context
144 @return : VOS_STATUS_E_FAILURE if any errors encountered
145 : VOS_STATUS_SUCCESS otherwise
146 ===========================================================================*/
147static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter )
148{
149 VOS_STATUS status = VOS_STATUS_SUCCESS;
150 v_SINT_t i = -1;
151 v_U8_t STAId = 0;
152 hdd_list_node_t *anchor = NULL;
153 skb_list_node_t *pktNode = NULL;
154 struct sk_buff *skb = NULL;
155
156 spin_lock_bh( &pAdapter->staInfo_lock );
157 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
158 {
159 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
160 {
161 continue;
162 }
163
164 for (i = 0; i < NUM_TX_QUEUES; i ++)
165 {
166 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
167 while (true)
168 {
169 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
170
171 if (VOS_STATUS_E_EMPTY != status)
172 {
173 //If success then we got a valid packet from some AC
174 pktNode = list_entry(anchor, skb_list_node_t, anchor);
175 skb = pktNode->skb;
176 ++pAdapter->stats.tx_dropped;
177 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
178 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
179 kfree_skb(skb);
180 continue;
181 }
182
183 //current list is empty
184 break;
185 }
186 pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE;
187 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
188 }
189 }
190
191 spin_unlock_bh( &pAdapter->staInfo_lock );
192
193 return status;
194}
195
196/**============================================================================
197 @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
198 transmitting packets. There are 2 versions of this function. One that uses
199 locked queue and other that uses lockless queues. Both have been retained to
200 do some performance testing
201
202 @param skb : [in] pointer to OS packet (sk_buff)
203 @param dev : [in] pointer to Libra network device
204
205 @return : NET_XMIT_DROP if packets are dropped
206 : NET_XMIT_SUCCESS if packet is enqueued succesfully
207 ===========================================================================*/
208int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
209{
210 VOS_STATUS status;
211 WLANTL_ACEnumType ac = WLANTL_AC_BE;
212 sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
213 skb_list_node_t *pktNode = NULL;
214 v_SIZE_t pktListSize = 0;
215 v_BOOL_t txSuspended = VOS_FALSE;
216 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
217 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
218 vos_list_node_t *anchor = NULL;
219 v_U8_t STAId = WLAN_MAX_STA_COUNT;
220 //Extract the destination address from ethernet frame
221 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
222 int os_status = NETDEV_TX_OK;
223
224 pDestMacAddress = (v_MACADDR_t*)skb->data;
225
226 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
227
228 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700229 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700230
231 spin_lock_bh( &pAdapter->staInfo_lock );
232 if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
233 {
234 //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
235 //ID used for BC/MC traffic. The station id is registered to TL as well.
236 STAId = pHddApCtx->uBCStaId;
237
238 /* Setting priority for broadcast packets which doesn't go to select_queue function */
239 skb->priority = SME_QOS_WMM_UP_BE;
240 skb->queue_mapping = HDD_LINUX_AC_BE;
241
242 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700243 "%s: BC/MC packet\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700244 }
245 else
246 {
247 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
248 if (STAId == HDD_WLAN_INVALID_STA_ID)
249 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700250 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700251 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 ++pAdapter->stats.tx_dropped;
253 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
254 kfree_skb(skb);
255 goto xmit_done;
256 }
257 else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
258 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530259 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 -0700260 ++pAdapter->stats.tx_dropped;
261 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
262 kfree_skb(skb);
263 goto xmit_done;
264 }
265
266 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
267 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
268 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700269 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700270 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700271 ++pAdapter->stats.tx_dropped;
272 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
273 kfree_skb(skb);
274 goto xmit_done;
275 }
276 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
277 {
278 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
279 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700280 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700281 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700282 ++pAdapter->stats.tx_dropped;
283 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
284 kfree_skb(skb);
285 goto xmit_done;
286 }
287 }
288 }
289
290 //Get TL AC corresponding to Qdisc queue index/AC.
291 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
292 //user priority from IP header, which is already extracted and set from
293 //select_queue call back function
294 up = skb->priority;
295 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
296
297 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700298 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700299
300 // If the memory differentiation mode is enabled, the memory limit of each queue will be
301 // checked. Over-limit packets will be dropped.
302 spin_lock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
303 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
304 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
305 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700306 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700307 "%s: station %d ac %d queue over limit %d \n", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
309 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
310 txSuspended = VOS_TRUE;
311 }
312 spin_unlock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
313
314 if (VOS_TRUE == txSuspended)
315 {
316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
317 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700318 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700319 os_status = NETDEV_TX_BUSY;
320 goto xmit_done;
321 }
322
323 //Use the skb->cb field to hold the list node information
324 pktNode = (skb_list_node_t *)&skb->cb;
325
326 //Stick the OS packet inside this node.
327 pktNode->skb = skb;
328
329 //Stick the User Priority inside this node
330 pktNode->userPriority = up;
331
332 INIT_LIST_HEAD(&pktNode->anchor);
333
334 spin_lock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
335 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
336 spin_unlock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
337
338 if ( !VOS_IS_STATUS_SUCCESS( status ) )
339 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700340 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 -0700341 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
342 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
343 ++pAdapter->stats.tx_dropped;
344 kfree_skb(skb);
345 goto xmit_done;
346 }
347
348 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
349 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
350
351 if (1 == pktListSize)
352 {
353 //Let TL know we have a packet to send for this AC
354 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
355
356 if ( !VOS_IS_STATUS_SUCCESS( status ) )
357 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700358 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 -0700359 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700360
361 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
362 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
363 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
364 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
365 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
366 ++pAdapter->stats.tx_dropped;
367 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
368 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
369 kfree_skb(skb);
370 goto xmit_done;
371 }
372 }
373 dev->trans_start = jiffies;
374
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700375 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700376
377xmit_done:
378 spin_unlock_bh( &pAdapter->staInfo_lock );
379 return os_status;
380}
381
382/**============================================================================
383 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
384
385 @param skb : [in] pointer to packet (sk_buff)
386 @param dev : [in] pointer to Libra network device
387 @param STAId : [in] Station Id of Destination Station
388 @param up : [in] User Priority
389
390 @return : NET_XMIT_DROP if packets are dropped
391 : NET_XMIT_SUCCESS if packet is enqueued succesfully
392 ===========================================================================*/
393VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
394 struct net_device *dev,
395 v_U8_t STAId,
396 v_U8_t up)
397{
398 VOS_STATUS status = VOS_STATUS_SUCCESS;
399 skb_list_node_t *pktNode = NULL;
400 v_SIZE_t pktListSize = 0;
401 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
402 v_U8_t ac;
403 vos_list_node_t *anchor = NULL;
404
405 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
406
407 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700408 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700409
410 spin_lock_bh( &pAdapter->staInfo_lock );
411 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
412 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700413 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530414 "%s: STA %d is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700415 kfree_skb(skb);
416 status = VOS_STATUS_E_FAILURE;
417 goto xmit_end;
418 }
419
420 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
421 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
422 up = SME_QOS_WMM_UP_BE;
423
424 ac = hddWmmUpToAcMap[up];
425 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
426 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700427 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700428
429 skb->queue_mapping = hddLinuxUpToAcMap[up];
430
431 //Use the skb->cb field to hold the list node information
432 pktNode = (skb_list_node_t *)&skb->cb;
433
434 //Stick the OS packet inside this node.
435 pktNode->skb = skb;
436
437 //Stick the User Priority inside this node
438 pktNode->userPriority = up;
439
440 INIT_LIST_HEAD(&pktNode->anchor);
441
442 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
443 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
444 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
445 pktListSize >= pAdapter->aTxQueueLimit[ac])
446 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700447 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700448 "%s: station %d ac %d queue over limit %d \n", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
450 * SUSPEND should be done based on Threshold. RESUME would be
451 * triggered in fetch cbk after recovery.
452 */
453 kfree_skb(skb);
454 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
455 status = VOS_STATUS_E_FAILURE;
456 goto xmit_end;
457 }
458 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
459 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
460
461 if ( !VOS_IS_STATUS_SUCCESS( status ) )
462 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700463 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 -0700464 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
465 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
466 ++pAdapter->stats.tx_dropped;
467 kfree_skb(skb);
468 status = VOS_STATUS_E_FAILURE;
469 goto xmit_end;
470 }
471
472 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
473 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
474
475 if (1 == pktListSize)
476 {
477 //Let TL know we have a packet to send for this AC
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700478 //VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700479 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
480
481 if ( !VOS_IS_STATUS_SUCCESS( status ) )
482 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700483 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 -0700484 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700485
486 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
487 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
488 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
489 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
490 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
491 ++pAdapter->stats.tx_dropped;
492 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
493 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
494 kfree_skb(skb);
495 status = VOS_STATUS_E_FAILURE;
496 goto xmit_end;
497 }
498 }
499
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700500 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700501
502xmit_end:
503 spin_unlock_bh( &pAdapter->staInfo_lock );
504 return status;
505}
506
507/**============================================================================
508 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
509 timeout during transmission. Since HDD simply enqueues packet
510 and returns control to OS right away, this would never be invoked
511
512 @param dev : [in] pointer to Libra network device
513 @return : None
514 ===========================================================================*/
515void hdd_softap_tx_timeout(struct net_device *dev)
516{
517 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700518 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700519 //Getting here implies we disabled the TX queues for too long. Queues are
520 //disabled either because of disassociation or low resource scenarios. In
521 //case of disassociation it is ok to ignore this. But if associated, we have
522 //do possible recovery here
523}
524
525
526/**============================================================================
527 @brief hdd_softap_stats() - Function registered with the Linux OS for
528 device TX/RX statistic
529
530 @param dev : [in] pointer to Libra network device
531
532 @return : pointer to net_device_stats structure
533 ===========================================================================*/
534struct net_device_stats* hdd_softap_stats(struct net_device *dev)
535{
536 hdd_adapter_t* priv = netdev_priv(dev);
537 return &priv->stats;
538}
539
540
541/**============================================================================
542 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
543 modules in HDD
544
545 @param pAdapter : [in] pointer to adapter context
546 @return : VOS_STATUS_E_FAILURE if any errors encountered
547 : VOS_STATUS_SUCCESS otherwise
548 ===========================================================================*/
549VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
550{
551 VOS_STATUS status = VOS_STATUS_SUCCESS;
552 v_SINT_t i = -1;
553 v_SIZE_t size = 0;
554
555 v_U8_t STAId = 0;
556
557 v_U8_t pACWeights[] = {
558 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
559 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
560 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
561 HDD_SOFTAP_VO_WEIGHT_DEFAULT
562 };
Leo Chang64d68bc2013-06-04 15:40:52 -0700563
564 hdd_context_t *pHddCtx = NULL;
565
Jeff Johnson295189b2012-06-20 16:38:30 -0700566 pAdapter->isVosOutOfResource = VOS_FALSE;
567
568 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
569
570 while (++i != NUM_TX_QUEUES)
571 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
572
573 /* Initial HDD buffer control / flow control fields*/
574 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
575
576 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
577 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
578 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
579 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
580
581 spin_lock_init( &pAdapter->staInfo_lock );
582
583 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
584 {
585 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
586 for (i = 0; i < NUM_TX_QUEUES; i ++)
587 {
588 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
589 }
590 }
591
592 /* Update the AC weights suitable for SoftAP mode of operation */
593 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
594
Leo Chang64d68bc2013-06-04 15:40:52 -0700595 /* Initialize SAP/P2P-GO traffin monitor */
596 pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
597 if (NULL == pHddCtx)
598 {
599 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
600 "%s: Invalid HDD cntxt", __func__ );
601 return VOS_STATUS_E_INVAL;
602 }
603 if ((pHddCtx->cfg_ini->enableTrafficMonitor) &&
604 (!pHddCtx->traffic_monitor.isInitialized))
605 {
606 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
607 vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer,
608 VOS_TIMER_TYPE_SW,
609 hdd_softap_traffic_monitor_timeout_handler,
610 pHddCtx);
611 vos_lock_init(&pHddCtx->traffic_monitor.trafficLock);
612 pHddCtx->traffic_monitor.isInitialized = 1;
613 pHddCtx->traffic_monitor.lastFrameTs = 0;
614 /* Start traffic monitor timer here
615 * If no AP assoc, immediatly go into suspend */
616 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
617 pHddCtx->cfg_ini->trafficIdleTimeout);
618 }
619
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 return status;
621}
622
623/**============================================================================
624 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
625 modules in HDD
626
627 @param pAdapter : [in] pointer to adapter context
628 @return : VOS_STATUS_E_FAILURE if any errors encountered
629 : VOS_STATUS_SUCCESS otherwise
630 ===========================================================================*/
631VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
632{
633 VOS_STATUS status = VOS_STATUS_SUCCESS;
Leo Chang64d68bc2013-06-04 15:40:52 -0700634 hdd_context_t *pHddCtx = NULL;
635
636 pHddCtx = (hdd_context_t *)pAdapter->pHddCtx;
637 if (NULL == pHddCtx)
638 {
639 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
640 "%s: Invalid HDD cntxt", __func__ );
641 return VOS_STATUS_E_INVAL;
642 }
643 if (pHddCtx->traffic_monitor.isInitialized)
644 {
645 if (VOS_TIMER_STATE_STOPPED !=
646 vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer))
647 {
648 vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer);
649 }
650 vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer);
651 vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock);
652 pHddCtx->traffic_monitor.isInitialized = 0;
653 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700654
655 status = hdd_softap_flush_tx_queues(pAdapter);
656
657 return status;
658}
659
660/**============================================================================
661 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
662
663 @param pAdapter : [in] pointer to adapter context
664 @param STAId : [in] Station ID to deinit
665 @return : VOS_STATUS_E_FAILURE if any errors encountered
666 : VOS_STATUS_SUCCESS otherwise
667 ===========================================================================*/
668static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
669{
670 VOS_STATUS status = VOS_STATUS_SUCCESS;
671 v_U8_t i = -1;
672
673 hdd_list_node_t *anchor = NULL;
674
675 skb_list_node_t *pktNode = NULL;
676 struct sk_buff *skb = NULL;
677
678 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
679 {
680 return status;
681 }
682
683 for (i = 0; i < NUM_TX_QUEUES; i ++)
684 {
685 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
686 while (true)
687 {
688 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
689 if (VOS_STATUS_E_EMPTY != status)
690 {
691 //If success then we got a valid packet from some AC
692 pktNode = list_entry(anchor, skb_list_node_t, anchor);
693 skb = pktNode->skb;
694 ++pAdapter->stats.tx_dropped;
695 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
696 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
697 kfree_skb(skb);
698 continue;
699 }
700
701 //current list is empty
702 break;
703 }
704 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
705 }
706
707 return status;
708}
709
710/**============================================================================
711 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
712 modules in HDD
713
714 @param pAdapter : [in] pointer to adapter context
715 @param STAId : [in] Station ID to deinit
716 @param pmacAddrSTA : [in] pointer to the MAC address of the station
717 @return : VOS_STATUS_E_FAILURE if any errors encountered
718 : VOS_STATUS_SUCCESS otherwise
719 ===========================================================================*/
720VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
721{
722 v_U8_t i = 0;
723 spin_lock_bh( &pAdapter->staInfo_lock );
724 if (pAdapter->aStaInfo[STAId].isUsed)
725 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700726 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 spin_unlock_bh( &pAdapter->staInfo_lock );
728 return VOS_STATUS_E_FAILURE;
729 }
730
731 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
732 for (i = 0; i < NUM_TX_QUEUES; i ++)
733 {
734 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
735 }
736
737 pAdapter->aStaInfo[STAId].isUsed = TRUE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800738 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700739 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
740
741 spin_unlock_bh( &pAdapter->staInfo_lock );
742 return VOS_STATUS_SUCCESS;
743}
744
745/**============================================================================
746 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
747 modules in HDD
748
749 @param pAdapter : [in] pointer to adapter context
750 @param STAId : [in] Station ID to deinit
751 @return : VOS_STATUS_E_FAILURE if any errors encountered
752 : VOS_STATUS_SUCCESS otherwise
753 ===========================================================================*/
754VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
755{
756 VOS_STATUS status = VOS_STATUS_SUCCESS;
757 v_U8_t ac;
758 /**Track whether OS TX queue has been disabled.*/
759 v_BOOL_t txSuspended[NUM_TX_QUEUES];
760 v_U8_t tlAC;
761 hdd_hostapd_state_t *pHostapdState;
762
763 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
764
765 spin_lock_bh( &pAdapter->staInfo_lock );
766 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
767 {
768 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700769 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700770 spin_unlock_bh( &pAdapter->staInfo_lock );
771 return VOS_STATUS_E_FAILURE;
772 }
773
774 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
775
776 pAdapter->aStaInfo[STAId].isUsed = FALSE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800777 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700778
779 /* if this STA had any of its WMM TX queues suspended, then the
780 associated queue on the network interface was disabled. check
781 to see if that is the case, in which case we need to re-enable
782 the interface queue. but we only do this if the BSS is running
783 since, if the BSS is stopped, all of the interfaces have been
784 stopped and should not be re-enabled */
785
786 if (BSS_START == pHostapdState->bssState)
787 {
788 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
789 {
790 tlAC = hdd_QdiscAcToTlAC[ac];
791 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
792 }
793 }
794 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
795
796 if (BSS_START == pHostapdState->bssState)
797 {
798 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
799 {
800 if (txSuspended[ac])
801 {
802 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700803 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700804 netif_wake_subqueue(pAdapter->dev, ac);
805 }
806 }
807 }
808
809 spin_unlock_bh( &pAdapter->staInfo_lock );
810 return status;
811}
812
813/**============================================================================
814 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
815 modules in HDD
816
817 @param pAdapter : [in] pointer to adapter context
818 @return : VOS_STATUS_E_FAILURE if any errors encountered
819 : VOS_STATUS_SUCCESS otherwise
820 ===========================================================================*/
821VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
822{
823 return hdd_softap_flush_tx_queues(pAdapter);
824}
825
826/**============================================================================
827 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
828 to indicate that a packet has been transmitted across the bus
829 succesfully. OS packet resources can be released after this cbk.
830
831 @param vosContext : [in] pointer to VOS context
832 @param pVosPacket : [in] pointer to VOS packet (containing skb)
833 @param vosStatusIn : [in] status of the transmission
834
835 @return : VOS_STATUS_E_FAILURE if any errors encountered
836 : VOS_STATUS_SUCCESS otherwise
837 ===========================================================================*/
838VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
839 vos_pkt_t *pVosPacket,
840 VOS_STATUS vosStatusIn )
841{
842 VOS_STATUS status = VOS_STATUS_SUCCESS;
843 hdd_adapter_t *pAdapter = NULL;
844 void* pOsPkt = NULL;
845
846 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
847 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700848 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700849 return VOS_STATUS_E_FAILURE;
850 }
851
852 //Return the skb to the OS
853 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
854 if(!VOS_IS_STATUS_SUCCESS( status ))
855 {
856 //This is bad but still try to free the VOSS resources if we can
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700857 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 -0700858 vos_pkt_return_packet( pVosPacket );
859 return VOS_STATUS_E_FAILURE;
860 }
861
862 //Get the Adapter context.
863 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
864 if(pAdapter == NULL)
865 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700866 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 -0700867 }
868 else
869 {
870 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
871 }
872
873 kfree_skb((struct sk_buff *)pOsPkt);
874
875 //Return the VOS packet resources.
876 status = vos_pkt_return_packet( pVosPacket );
877 if(!VOS_IS_STATUS_SUCCESS( status ))
878 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700879 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 -0700880 }
881
882 return status;
883}
884
885
886/**============================================================================
887 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
888 fetch a packet for transmission.
889
890 @param vosContext : [in] pointer to VOS context
891 @param staId : [in] Station for which TL is requesting a pkt
892 @param ac : [in] access category requested by TL
893 @param pVosPacket : [out] pointer to VOS packet packet pointer
894 @param pPktMetaInfo : [out] pointer to meta info for the pkt
895
896 @return : VOS_STATUS_E_EMPTY if no packets to transmit
897 : VOS_STATUS_E_FAILURE if any errors encountered
898 : VOS_STATUS_SUCCESS otherwise
899 ===========================================================================*/
900VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
901 v_U8_t *pStaId,
902 WLANTL_ACEnumType ac,
903 vos_pkt_t **ppVosPacket,
904 WLANTL_MetaInfoType *pPktMetaInfo )
905{
906 VOS_STATUS status = VOS_STATUS_E_FAILURE;
907 hdd_adapter_t *pAdapter = NULL;
908 hdd_list_node_t *anchor = NULL;
909 skb_list_node_t *pktNode = NULL;
910 struct sk_buff *skb = NULL;
911 vos_pkt_t *pVosPacket = NULL;
912 v_MACADDR_t* pDestMacAddress = NULL;
913 v_TIME_t timestamp;
914 v_SIZE_t size = 0;
915 v_U8_t STAId = WLAN_MAX_STA_COUNT;
916 hdd_context_t *pHddCtx = NULL;
917
918 //Sanity check on inputs
919 if ( ( NULL == vosContext ) ||
920 ( NULL == pStaId ) ||
921 ( NULL == ppVosPacket ) ||
922 ( NULL == pPktMetaInfo ) )
923 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700924 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700925 return VOS_STATUS_E_FAILURE;
926 }
927
928 //Get the HDD context.
929 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
930 if ( NULL == pHddCtx )
931 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700932 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 -0700933 return VOS_STATUS_E_FAILURE;
934 }
935
936 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
937 if( NULL == pAdapter )
938 {
939 VOS_ASSERT(0);
940 return VOS_STATUS_E_FAILURE;
941 }
942
Leo Chang64d68bc2013-06-04 15:40:52 -0700943 /* Monitor traffic */
944 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
945 {
946 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
947 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
948 {
949 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
950 /* It was IDLE mode,
951 * this is new state, then switch mode from suspend to resume */
952 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
953 {
954 hdd_set_wlan_suspend_mode(0);
955 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
956 pHddCtx->cfg_ini->trafficIdleTimeout);
957 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
958 }
959 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
960 }
961 }
962
Jeff Johnson295189b2012-06-20 16:38:30 -0700963 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
964
965 STAId = *pStaId;
966 if (STAId >= WLAN_MAX_STA_COUNT)
967 {
968 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700969 "%s: Invalid STAId %d passed by TL", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700970 return VOS_STATUS_E_FAILURE;
971 }
972
973 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
974 {
975 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700976 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700977 return VOS_STATUS_E_FAILURE;
978 }
979
980 *ppVosPacket = NULL;
981
982 //Make sure the AC being asked for is sane
983 if( ac > WLANTL_MAX_AC || ac < 0)
984 {
985 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700986 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700987 return VOS_STATUS_E_FAILURE;
988 }
989
990 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
991
992 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700993 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700994
995 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
996 //This simplifies the locking and unlocking of Tx queue
997 status = vos_pkt_wrap_data_packet( &pVosPacket,
998 VOS_PKT_TYPE_TX_802_3_DATA,
999 NULL, //OS Pkt is not being passed
1000 hdd_softap_tx_low_resource_cbk,
1001 pAdapter );
1002
1003 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1004 {
1005 //Remember VOS is in a low resource situation
1006 pAdapter->isVosOutOfResource = VOS_TRUE;
1007 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
1008 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001009 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001010 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1011 return VOS_STATUS_E_FAILURE;
1012 }
1013
1014 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
1015 as the other branch does.
1016 */
1017 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1018 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
1019
1020 if (0 == size)
1021 {
1022 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1023 vos_pkt_return_packet(pVosPacket);
1024 return VOS_STATUS_E_EMPTY;
1025 }
1026
1027 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1028 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1029
1030 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001031 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001032
1033 if(VOS_STATUS_SUCCESS == status)
1034 {
1035 //If success then we got a valid packet from some AC
1036 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1037 skb = pktNode->skb;
1038 }
1039 else
1040 {
1041 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1042 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1043 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001044 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001045 vos_pkt_return_packet(pVosPacket);
1046 return VOS_STATUS_E_FAILURE;
1047 }
1048
1049 //Attach skb to VOS packet.
1050 status = vos_pkt_set_os_packet( pVosPacket, skb );
1051 if (status != VOS_STATUS_SUCCESS)
1052 {
1053 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001054 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001055 vos_pkt_return_packet(pVosPacket);
1056 ++pAdapter->stats.tx_dropped;
1057 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1058 kfree_skb(skb);
1059 return VOS_STATUS_E_FAILURE;
1060 }
1061
1062 //Just being paranoid. To be removed later
1063 if(pVosPacket == NULL)
1064 {
1065 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001066 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 ++pAdapter->stats.tx_dropped;
1068 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1069 kfree_skb(skb);
1070 return VOS_STATUS_E_FAILURE;
1071 }
1072
1073 //Return VOS packet to TL;
1074 *ppVosPacket = pVosPacket;
1075
1076 //Fill out the meta information needed by TL
1077 //FIXME This timestamp is really the time stamp of wrap_data_packet
1078 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1079 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1080 if ( 1 < size )
1081 {
1082 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1083 }
1084 else
1085 {
1086 pPktMetaInfo->bMorePackets = 0;
1087 }
1088
1089 pPktMetaInfo->ucIsEapol = 0;
1090
1091 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
1092 {
1093 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
1094 {
1095 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001096 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001097 pPktMetaInfo->ucIsEapol = 1;
1098 }
1099 }
1100
1101//xg: @@@@: temporarily disble these. will revisit later
Jeff Johnson295189b2012-06-20 16:38:30 -07001102 {
1103 pPktMetaInfo->ucUP = pktNode->userPriority;
1104 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1105 }
1106
1107 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1108 //Extract the destination address from ethernet frame
1109 pDestMacAddress = (v_MACADDR_t*)skb->data;
1110
1111 // we need 802.3 to 802.11 frame translation
1112 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1113 pPktMetaInfo->ucDisableFrmXtl = 0;
1114 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1115 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1116
1117 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1118 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1119 {
1120 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001121 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001122 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1123 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1124 }
1125
1126 // We're giving the packet to TL so consider it transmitted from
1127 // a statistics perspective. We account for it here instead of
1128 // when the packet is returned for two reasons. First, TL will
1129 // manipulate the skb to the point where the len field is not
1130 // accurate, leading to inaccurate byte counts if we account for
1131 // it later. Second, TL does not provide any feedback as to
1132 // whether or not the packet was successfully sent over the air,
1133 // so the packet counts will be the same regardless of where we
1134 // account for them
1135 pAdapter->stats.tx_bytes += skb->len;
1136 ++pAdapter->stats.tx_packets;
1137 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1138 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1139
1140 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001141 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001142
1143 return status;
1144}
1145
1146
1147/**============================================================================
1148 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1149 case where VOS packets are not available at the time of the call to get
1150 packets. This callback function is invoked by VOS when packets are
1151 available.
1152
1153 @param pVosPacket : [in] pointer to VOS packet
1154 @param userData : [in] opaque user data that was passed initially
1155
1156 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1157 : VOS_STATUS_SUCCESS otherwise
1158 =============================================================================*/
1159VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1160 v_VOID_t *userData )
1161{
1162 VOS_STATUS status;
1163 v_SINT_t i = 0;
1164 v_SIZE_t size = 0;
1165 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1166 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1167
1168 if(pAdapter == NULL)
1169 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001170 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 -07001171 return VOS_STATUS_E_FAILURE;
1172 }
1173
1174 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1175 //situation. Here we will only signal TL that there is a pending data for a STA.
1176 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1177 vos_pkt_return_packet( pVosPacket );
1178
1179 pAdapter->isVosOutOfResource = VOS_FALSE;
1180
1181 // Indicate to TL that there is pending data if a queue is non empty.
1182 // This Code wasnt included in earlier version which resulted in
1183 // Traffic stalling
1184 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1185 {
1186 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1187 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1188 {
1189 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1190 {
1191 size = 0;
1192 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1193 if ( size > 0 )
1194 {
1195 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1196 STAId,
1197 (WLANTL_ACEnumType)i );
1198 if( !VOS_IS_STATUS_SUCCESS( status ) )
1199 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001200 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 -07001201 }
1202 }
1203 }
1204 }
1205 }
1206 return VOS_STATUS_SUCCESS;
1207}
1208
1209
1210/**============================================================================
1211 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1212 TL will call this to notify the HDD when one or more packets were
1213 received for a registered STA.
1214
1215 @param vosContext : [in] pointer to VOS context
1216 @param pVosPacketChain : [in] pointer to VOS packet chain
1217 @param staId : [in] Station Id (Adress 1 Index)
1218 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1219
1220 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1221 : VOS_STATUS_SUCCESS otherwise
1222 ===========================================================================*/
1223VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1224 vos_pkt_t *pVosPacketChain,
1225 v_U8_t staId,
1226 WLANTL_RxMetaInfoType* pRxMetaInfo )
1227{
1228 hdd_adapter_t *pAdapter = NULL;
1229 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1230 int rxstat;
1231 struct sk_buff *skb = NULL;
1232 vos_pkt_t* pVosPacket;
1233 vos_pkt_t* pNextVosPacket;
1234 hdd_context_t *pHddCtx = NULL;
1235
1236 //Sanity check on inputs
1237 if ( ( NULL == vosContext ) ||
1238 ( NULL == pVosPacketChain ) ||
1239 ( NULL == pRxMetaInfo ) )
1240 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001241 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001242 return VOS_STATUS_E_FAILURE;
1243 }
1244
1245 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1246 if ( NULL == pHddCtx )
1247 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001248 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 -07001249 return VOS_STATUS_E_FAILURE;
1250 }
1251
1252 pAdapter = pHddCtx->sta_to_adapter[staId];
1253 if( NULL == pAdapter )
1254 {
1255 VOS_ASSERT(0);
1256 return VOS_STATUS_E_FAILURE;
1257 }
Leo Chang64d68bc2013-06-04 15:40:52 -07001258
1259 /* Monitor traffic */
1260 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1261 {
1262 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1263 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1264 {
1265 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1266 /* It was IDLE mode,
1267 * this is new state, then switch mode from suspend to resume */
1268 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1269 {
1270 hdd_set_wlan_suspend_mode(0);
1271 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1272 pHddCtx->cfg_ini->trafficIdleTimeout);
1273 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1274 }
1275 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1276 }
1277 }
1278
Jeff Johnson295189b2012-06-20 16:38:30 -07001279 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1280
1281 // walk the chain until all are processed
1282 pVosPacket = pVosPacketChain;
1283 do
1284 {
1285 // get the pointer to the next packet in the chain
1286 // (but don't unlink the packet since we free the entire chain later)
1287 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1288
1289 // both "success" and "empty" are acceptable results
1290 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1291 {
1292 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001293 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001294 return VOS_STATUS_E_FAILURE;
1295 }
1296
1297 // Extract the OS packet (skb).
1298 // Tell VOS to detach the OS packet from the VOS packet
1299 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1300 if(!VOS_IS_STATUS_SUCCESS( status ))
1301 {
1302 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001303 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 -07001304 return VOS_STATUS_E_FAILURE;
1305 }
1306
1307 //hdd_softap_dump_sk_buff(skb);
1308
1309 skb->dev = pAdapter->dev;
1310
1311 if(skb->dev == NULL) {
1312
1313 hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR!!Invalid netdevice\n");
1314 return VOS_STATUS_E_FAILURE;
1315 }
1316 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1317 ++pAdapter->stats.rx_packets;
1318 pAdapter->stats.rx_bytes += skb->len;
1319
1320 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1321 {
1322 //MC/BC packets. Duplicate a copy of packet
1323 struct sk_buff *pSkbCopy;
1324 hdd_ap_ctx_t *pHddApCtx;
1325
1326 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1327 if (!(pHddApCtx->apDisableIntraBssFwd))
1328 {
1329 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1330 if (pSkbCopy)
1331 {
1332 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1333 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1334 }
1335 }
1336 else
1337 {
1338 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001339 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001340 }
1341
1342
1343 } //(WLAN_RX_BCMC_STA_ID == staId)
1344
1345 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1346 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1347 {
1348 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001349 "%s: send one packet to kernel \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001350
1351 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001352 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001353#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001354#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001355 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001356#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001357#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001358 rxstat = netif_rx_ni(skb);
1359 if (NET_RX_SUCCESS == rxstat)
1360 {
1361 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
1362 }
1363 else
1364 {
1365 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1366 }
1367 }
1368 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1369 {
1370 kfree_skb(skb);
1371 }
1372 else
1373 {
1374 //loopback traffic
1375 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1376 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1377 }
1378
1379 // now process the next packet in the chain
1380 pVosPacket = pNextVosPacket;
1381
1382 } while (pVosPacket);
1383
1384 //Return the entire VOS packet chain to the resource pool
1385 status = vos_pkt_return_packet( pVosPacketChain );
1386 if(!VOS_IS_STATUS_SUCCESS( status ))
1387 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001388 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001389 }
1390
1391 pAdapter->dev->last_rx = jiffies;
1392
1393 return status;
1394}
1395
1396VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1397{
1398 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301399 hdd_context_t *pHddCtx;
1400 if (NULL == pAdapter)
1401 {
1402 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1403 "%s: pAdapter is NULL", __func__);
1404 return VOS_STATUS_E_INVAL;
1405 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001406
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301407 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1408 {
1409 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1410 "%s: Invalid pAdapter magic", __func__);
1411 return VOS_STATUS_E_INVAL;
1412 }
1413
1414 pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001415 //Clear station in TL and then update HDD data structures. This helps
1416 //to block RX frames from other station to this station.
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301417 vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001418 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1419 {
1420 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1421 "WLANTL_ClearSTAClient() failed to for staID %d. "
1422 "Status= %d [0x%08lX]",
1423 staId, vosStatus, vosStatus );
1424 }
1425
1426 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1427 if( VOS_STATUS_E_FAILURE == vosStatus )
1428 {
1429 VOS_TRACE ( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1430 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
1431 "Status = %d [0x%08lX]",
1432 staId, vosStatus, vosStatus );
1433 return( vosStatus );
1434 }
1435
1436 pHddCtx->sta_to_adapter[staId] = NULL;
1437
1438 return( vosStatus );
1439}
1440
1441VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1442 v_BOOL_t fAuthRequired,
1443 v_BOOL_t fPrivacyBit,
1444 v_U8_t staId,
1445 v_U8_t ucastSig,
1446 v_U8_t bcastSig,
1447 v_MACADDR_t *pPeerMacAddress,
1448 v_BOOL_t fWmmEnabled )
1449{
1450 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001451 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001452 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1453 hdd_adapter_t *pmonAdapter = NULL;
1454
1455 //eCsrEncryptionType connectedCipherAlgo;
1456 //v_BOOL_t fConnected;
1457
1458 /*
1459 * Clean up old entry if it is not cleaned up properly
1460 */
1461 if ( pAdapter->aStaInfo[staId].isUsed )
1462 {
1463 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1464 "clean up old entry for STA %d", staId);
1465 hdd_softap_DeregisterSTA( pAdapter, staId );
1466 }
1467
1468 // Get the Station ID from the one saved during the assocation.
1469
1470 staDesc.ucSTAId = staId;
1471
1472
1473 /*Save the pAdapter Pointer for this staId*/
1474 pHddCtx->sta_to_adapter[staId] = pAdapter;
1475
1476 staDesc.wSTAType = WLAN_STA_SOFTAP;
1477
1478 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1479 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1480 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1481
1482 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1483 "register station \n");
1484 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1485 "station mac %02x:%02x:%02x:%02x:%02x:%02x",
1486 staDesc.vSTAMACAddress.bytes[0],
1487 staDesc.vSTAMACAddress.bytes[1],
1488 staDesc.vSTAMACAddress.bytes[2],
1489 staDesc.vSTAMACAddress.bytes[3],
1490 staDesc.vSTAMACAddress.bytes[4],
1491 staDesc.vSTAMACAddress.bytes[5]);
1492 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1493 "BSSIDforIBSS %02x:%02x:%02x:%02x:%02x:%02x",
1494 staDesc.vBSSIDforIBSS.bytes[0],
1495 staDesc.vBSSIDforIBSS.bytes[1],
1496 staDesc.vBSSIDforIBSS.bytes[2],
1497 staDesc.vBSSIDforIBSS.bytes[3],
1498 staDesc.vBSSIDforIBSS.bytes[4],
1499 staDesc.vBSSIDforIBSS.bytes[5]);
1500 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1501 "SOFTAP SELFMAC %02x:%02x:%02x:%02x:%02x:%02x",
1502 staDesc.vSelfMACAddress.bytes[0],
1503 staDesc.vSelfMACAddress.bytes[1],
1504 staDesc.vSelfMACAddress.bytes[2],
1505 staDesc.vSelfMACAddress.bytes[3],
1506 staDesc.vSelfMACAddress.bytes[4],
1507 staDesc.vSelfMACAddress.bytes[5]);
1508
1509 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1510
Jeff Johnson295189b2012-06-20 16:38:30 -07001511 staDesc.ucQosEnabled = fWmmEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07001512 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1513 "HDD SOFTAP register TL QoS_enabled=%d",
1514 staDesc.ucQosEnabled );
1515
1516 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1517
1518
Jeff Johnson295189b2012-06-20 16:38:30 -07001519 // For PRIMA UMA frame translation is not enable yet.
1520 staDesc.ucSwFrameTXXlation = 1;
1521 staDesc.ucSwFrameRXXlation = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 staDesc.ucAddRmvLLC = 1;
1523
1524 // Initialize signatures and state
1525 staDesc.ucUcastSig = ucastSig;
1526 staDesc.ucBcastSig = bcastSig;
1527 staDesc.ucInitState = fAuthRequired ?
1528 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1529
Prathyushaf5442802012-12-12 13:58:11 -08001530 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1531
Jeff Johnson295189b2012-06-20 16:38:30 -07001532 // Register the Station with TL...
1533 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1534 hdd_softap_rx_packet_cbk,
1535 hdd_softap_tx_complete_cbk,
1536 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1537
1538 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1539 {
1540 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1541 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08lX]",
1542 vosStatus, vosStatus );
1543 return vosStatus;
1544 }
1545
1546 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1547 // then go to 'authenticated'. For all other authentication types (those that do
1548 // not require upper layer authentication) we can put TL directly into 'authenticated'
1549 // state.
1550
1551 //VOS_ASSERT( fConnected );
1552 pAdapter->aStaInfo[staId].ucSTAId = staId;
1553 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1554
1555 if ( !fAuthRequired )
1556 {
1557 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1558 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1559
1560 // Connections that do not need Upper layer auth, transition TL directly
1561 // to 'Authenticated' state.
1562 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1563 WLANTL_STA_AUTHENTICATED );
1564
1565 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1566 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1567 }
1568 else
1569 {
1570
1571 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1572 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1573
1574 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1575 WLANTL_STA_CONNECTED );
1576 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1577
1578 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1579
1580 }
1581 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1582 if(pmonAdapter)
1583 {
1584 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Turn on Monitor the carrier\n");
1585 netif_carrier_on(pmonAdapter->dev);
1586 //Enable Tx queue
1587 netif_tx_start_all_queues(pmonAdapter->dev);
1588 }
1589 netif_carrier_on(pAdapter->dev);
1590 //Enable Tx queue
1591 netif_tx_start_all_queues(pAdapter->dev);
1592
1593 return( vosStatus );
1594}
1595
1596VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1597{
1598 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1599 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1600 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1601
1602
1603 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1604 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1605 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1606
1607 return vosStatus;
1608}
1609
1610VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1611{
1612 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1613}
1614
1615VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1616{
1617 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1618 v_U8_t staId = 0;
1619
1620 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1621
Jeff Johnson43971f52012-07-17 12:26:56 -07001622 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001623 {
1624 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001625 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001626 }
1627
1628 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1629 {
1630 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
1631 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1632
Jeff Johnson43971f52012-07-17 12:26:56 -07001633 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001634 {
1635 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001636 "%s: Failed to deregister sta Id %d", __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001637 }
1638 }
1639
1640 return vosStatus;
1641}
1642
1643VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1644{
1645 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1646 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1647 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001648
1649 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001650 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001651
Jeff Johnson43971f52012-07-17 12:26:56 -07001652 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001653 {
1654 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001655 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001656 return VOS_STATUS_E_FAILURE;
1657 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001658
1659 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1660 {
1661 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001662 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001663 return VOS_STATUS_E_FAILURE;
1664 }
1665
1666 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
1667 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001668 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001669
Jeff Johnson43971f52012-07-17 12:26:56 -07001670 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 {
1672 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1673 }
1674
1675 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001676 "%s exit\n",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001677
1678 return vosStatus;
1679}
1680
1681
1682VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1683{
1684 v_U8_t i;
1685
1686 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1687 {
1688 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1689 pAdapter->aStaInfo[i].isUsed)
1690 {
1691 *staId = i;
1692 return VOS_STATUS_SUCCESS;
1693 }
1694 }
1695
1696 return VOS_STATUS_E_FAILURE;
1697}
1698