blob: c87f42cf022bb8889e15b1a2e3aa267f4b5ee397 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**===========================================================================
23
24 \file wlan_hdd_softap_tx_rx.c
25
26 \brief Linux HDD Tx/RX APIs
27 Copyright 2008 (c) Qualcomm, Incorporated.
28 All Rights Reserved.
29 Qualcomm Confidential and Proprietary.
30
31 ==========================================================================*/
32#ifdef WLAN_SOFTAP_FEATURE
33
34/*---------------------------------------------------------------------------
35 Include files
36 -------------------------------------------------------------------------*/
37#include <linux/semaphore.h>
38#include <wlan_hdd_tx_rx.h>
39#include <wlan_hdd_softap_tx_rx.h>
40#include <wlan_hdd_dp_utils.h>
41#include <wlan_qct_tl.h>
42#include <linux/netdevice.h>
43#include <linux/skbuff.h>
44#include <linux/etherdevice.h>
45//#include <vos_list.h>
46#include <vos_types.h>
47#include <aniGlobal.h>
48#include <halTypes.h>
49#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
50#include <halHddApis.h>
51#endif
52#include <net/ieee80211_radiotap.h>
53
54
55/*---------------------------------------------------------------------------
56 Preprocessor definitions and constants
57 -------------------------------------------------------------------------*/
58
59/*---------------------------------------------------------------------------
60 Type declarations
61 -------------------------------------------------------------------------*/
62
63/*---------------------------------------------------------------------------
64 Function definitions and documenation
65 -------------------------------------------------------------------------*/
66#if 0
67static void hdd_softap_dump_sk_buff(struct sk_buff * skb)
68{
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070069 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: head = %p ", __func__, skb->head);
70 //VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data);
71 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p ", __func__, skb->tail);
72 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: end = %p ", __func__, skb->end);
73 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: len = %d ", __func__, skb->len);
74 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d ", __func__, skb->data_len);
75 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 -070076
77 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 ",
78 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
79 skb->data[5], skb->data[6], skb->data[7]);
80 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",
81 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
82 skb->data[13], skb->data[14], skb->data[15]);
83}
84#endif
85/**============================================================================
86 @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
87
88 @param pAdapter : [in] pointer to adapter context
89 @return : VOS_STATUS_E_FAILURE if any errors encountered
90 : VOS_STATUS_SUCCESS otherwise
91 ===========================================================================*/
92static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter )
93{
94 VOS_STATUS status = VOS_STATUS_SUCCESS;
95 v_SINT_t i = -1;
96 v_U8_t STAId = 0;
97 hdd_list_node_t *anchor = NULL;
98 skb_list_node_t *pktNode = NULL;
99 struct sk_buff *skb = NULL;
100
101 spin_lock_bh( &pAdapter->staInfo_lock );
102 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
103 {
104 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
105 {
106 continue;
107 }
108
109 for (i = 0; i < NUM_TX_QUEUES; i ++)
110 {
111 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
112 while (true)
113 {
114 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
115
116 if (VOS_STATUS_E_EMPTY != status)
117 {
118 //If success then we got a valid packet from some AC
119 pktNode = list_entry(anchor, skb_list_node_t, anchor);
120 skb = pktNode->skb;
121 ++pAdapter->stats.tx_dropped;
122 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
123 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
124 kfree_skb(skb);
125 continue;
126 }
127
128 //current list is empty
129 break;
130 }
131 pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE;
132 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
133 }
134 }
135
136 spin_unlock_bh( &pAdapter->staInfo_lock );
137
138 return status;
139}
140
141/**============================================================================
142 @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
143 transmitting packets. There are 2 versions of this function. One that uses
144 locked queue and other that uses lockless queues. Both have been retained to
145 do some performance testing
146
147 @param skb : [in] pointer to OS packet (sk_buff)
148 @param dev : [in] pointer to Libra network device
149
150 @return : NET_XMIT_DROP if packets are dropped
151 : NET_XMIT_SUCCESS if packet is enqueued succesfully
152 ===========================================================================*/
153int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
154{
155 VOS_STATUS status;
156 WLANTL_ACEnumType ac = WLANTL_AC_BE;
157 sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
158 skb_list_node_t *pktNode = NULL;
159 v_SIZE_t pktListSize = 0;
160 v_BOOL_t txSuspended = VOS_FALSE;
161 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
162 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
163 vos_list_node_t *anchor = NULL;
164 v_U8_t STAId = WLAN_MAX_STA_COUNT;
165 //Extract the destination address from ethernet frame
166 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
167 int os_status = NETDEV_TX_OK;
168
169 pDestMacAddress = (v_MACADDR_t*)skb->data;
170
171 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
172
173 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700174 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176 spin_lock_bh( &pAdapter->staInfo_lock );
177 if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
178 {
179 //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
180 //ID used for BC/MC traffic. The station id is registered to TL as well.
181 STAId = pHddApCtx->uBCStaId;
182
183 /* Setting priority for broadcast packets which doesn't go to select_queue function */
184 skb->priority = SME_QOS_WMM_UP_BE;
185 skb->queue_mapping = HDD_LINUX_AC_BE;
186
187 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700188 "%s: BC/MC packet\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700189 }
190 else
191 {
192 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
193 if (STAId == HDD_WLAN_INVALID_STA_ID)
194 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700195 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700196 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700197 ++pAdapter->stats.tx_dropped;
198 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
199 kfree_skb(skb);
200 goto xmit_done;
201 }
202 else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
203 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700204 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s: STA is unregistered", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700205 ++pAdapter->stats.tx_dropped;
206 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
207 kfree_skb(skb);
208 goto xmit_done;
209 }
210
211 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
212 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
213 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700214 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700215 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700216 ++pAdapter->stats.tx_dropped;
217 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
218 kfree_skb(skb);
219 goto xmit_done;
220 }
221 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
222 {
223 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
224 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700225 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700226 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700227 ++pAdapter->stats.tx_dropped;
228 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
229 kfree_skb(skb);
230 goto xmit_done;
231 }
232 }
233 }
234
235 //Get TL AC corresponding to Qdisc queue index/AC.
236 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
237 //user priority from IP header, which is already extracted and set from
238 //select_queue call back function
239 up = skb->priority;
240 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
241
242 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700243 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700244
245 // If the memory differentiation mode is enabled, the memory limit of each queue will be
246 // checked. Over-limit packets will be dropped.
247 spin_lock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
248 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
249 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
250 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700251 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700252 "%s: station %d ac %d queue over limit %d \n", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700253 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
254 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
255 txSuspended = VOS_TRUE;
256 }
257 spin_unlock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
258
259 if (VOS_TRUE == txSuspended)
260 {
261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
262 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700263 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700264 os_status = NETDEV_TX_BUSY;
265 goto xmit_done;
266 }
267
268 //Use the skb->cb field to hold the list node information
269 pktNode = (skb_list_node_t *)&skb->cb;
270
271 //Stick the OS packet inside this node.
272 pktNode->skb = skb;
273
274 //Stick the User Priority inside this node
275 pktNode->userPriority = up;
276
277 INIT_LIST_HEAD(&pktNode->anchor);
278
279 spin_lock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
280 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
281 spin_unlock(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
282
283 if ( !VOS_IS_STATUS_SUCCESS( status ) )
284 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700285 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 -0700286 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
287 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
288 ++pAdapter->stats.tx_dropped;
289 kfree_skb(skb);
290 goto xmit_done;
291 }
292
293 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
294 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
295
296 if (1 == pktListSize)
297 {
298 //Let TL know we have a packet to send for this AC
299 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
300
301 if ( !VOS_IS_STATUS_SUCCESS( status ) )
302 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700303 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 -0700304 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700305
306 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
307 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
308 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
309 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
310 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
311 ++pAdapter->stats.tx_dropped;
312 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
313 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
314 kfree_skb(skb);
315 goto xmit_done;
316 }
317 }
318 dev->trans_start = jiffies;
319
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700320 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700321
322xmit_done:
323 spin_unlock_bh( &pAdapter->staInfo_lock );
324 return os_status;
325}
326
327/**============================================================================
328 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
329
330 @param skb : [in] pointer to packet (sk_buff)
331 @param dev : [in] pointer to Libra network device
332 @param STAId : [in] Station Id of Destination Station
333 @param up : [in] User Priority
334
335 @return : NET_XMIT_DROP if packets are dropped
336 : NET_XMIT_SUCCESS if packet is enqueued succesfully
337 ===========================================================================*/
338VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
339 struct net_device *dev,
340 v_U8_t STAId,
341 v_U8_t up)
342{
343 VOS_STATUS status = VOS_STATUS_SUCCESS;
344 skb_list_node_t *pktNode = NULL;
345 v_SIZE_t pktListSize = 0;
346 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
347 v_U8_t ac;
348 vos_list_node_t *anchor = NULL;
349
350 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
351
352 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700353 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700354
355 spin_lock_bh( &pAdapter->staInfo_lock );
356 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
357 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700358 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700359 "%s: STA is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700360 kfree_skb(skb);
361 status = VOS_STATUS_E_FAILURE;
362 goto xmit_end;
363 }
364
365 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
366 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
367 up = SME_QOS_WMM_UP_BE;
368
369 ac = hddWmmUpToAcMap[up];
370 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
371 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700372 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700373
374 skb->queue_mapping = hddLinuxUpToAcMap[up];
375
376 //Use the skb->cb field to hold the list node information
377 pktNode = (skb_list_node_t *)&skb->cb;
378
379 //Stick the OS packet inside this node.
380 pktNode->skb = skb;
381
382 //Stick the User Priority inside this node
383 pktNode->userPriority = up;
384
385 INIT_LIST_HEAD(&pktNode->anchor);
386
387 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
388 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
389 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
390 pktListSize >= pAdapter->aTxQueueLimit[ac])
391 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700392 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700393 "%s: station %d ac %d queue over limit %d \n", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700394 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
395 * SUSPEND should be done based on Threshold. RESUME would be
396 * triggered in fetch cbk after recovery.
397 */
398 kfree_skb(skb);
399 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
400 status = VOS_STATUS_E_FAILURE;
401 goto xmit_end;
402 }
403 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
404 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
405
406 if ( !VOS_IS_STATUS_SUCCESS( status ) )
407 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700408 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 -0700409 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
410 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
411 ++pAdapter->stats.tx_dropped;
412 kfree_skb(skb);
413 status = VOS_STATUS_E_FAILURE;
414 goto xmit_end;
415 }
416
417 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
418 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
419
420 if (1 == pktListSize)
421 {
422 //Let TL know we have a packet to send for this AC
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700423 //VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700424 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
425
426 if ( !VOS_IS_STATUS_SUCCESS( status ) )
427 {
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -0700428 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 -0700429 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700430
431 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
432 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
433 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
434 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
435 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
436 ++pAdapter->stats.tx_dropped;
437 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
438 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
439 kfree_skb(skb);
440 status = VOS_STATUS_E_FAILURE;
441 goto xmit_end;
442 }
443 }
444
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700445 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700446
447xmit_end:
448 spin_unlock_bh( &pAdapter->staInfo_lock );
449 return status;
450}
451
452/**============================================================================
453 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
454 timeout during transmission. Since HDD simply enqueues packet
455 and returns control to OS right away, this would never be invoked
456
457 @param dev : [in] pointer to Libra network device
458 @return : None
459 ===========================================================================*/
460void hdd_softap_tx_timeout(struct net_device *dev)
461{
462 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700463 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700464 //Getting here implies we disabled the TX queues for too long. Queues are
465 //disabled either because of disassociation or low resource scenarios. In
466 //case of disassociation it is ok to ignore this. But if associated, we have
467 //do possible recovery here
468}
469
470
471/**============================================================================
472 @brief hdd_softap_stats() - Function registered with the Linux OS for
473 device TX/RX statistic
474
475 @param dev : [in] pointer to Libra network device
476
477 @return : pointer to net_device_stats structure
478 ===========================================================================*/
479struct net_device_stats* hdd_softap_stats(struct net_device *dev)
480{
481 hdd_adapter_t* priv = netdev_priv(dev);
482 return &priv->stats;
483}
484
485
486/**============================================================================
487 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
488 modules in HDD
489
490 @param pAdapter : [in] pointer to adapter context
491 @return : VOS_STATUS_E_FAILURE if any errors encountered
492 : VOS_STATUS_SUCCESS otherwise
493 ===========================================================================*/
494VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
495{
496 VOS_STATUS status = VOS_STATUS_SUCCESS;
497 v_SINT_t i = -1;
498 v_SIZE_t size = 0;
499
500 v_U8_t STAId = 0;
501
502 v_U8_t pACWeights[] = {
503 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
504 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
505 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
506 HDD_SOFTAP_VO_WEIGHT_DEFAULT
507 };
508 pAdapter->isVosOutOfResource = VOS_FALSE;
509
510 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
511
512 while (++i != NUM_TX_QUEUES)
513 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
514
515 /* Initial HDD buffer control / flow control fields*/
516 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
517
518 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
519 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
520 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
521 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
522
523 spin_lock_init( &pAdapter->staInfo_lock );
524
525 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
526 {
527 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
528 for (i = 0; i < NUM_TX_QUEUES; i ++)
529 {
530 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
531 }
532 }
533
534 /* Update the AC weights suitable for SoftAP mode of operation */
535 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
536
537 return status;
538}
539
540/**============================================================================
541 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
542 modules in HDD
543
544 @param pAdapter : [in] pointer to adapter context
545 @return : VOS_STATUS_E_FAILURE if any errors encountered
546 : VOS_STATUS_SUCCESS otherwise
547 ===========================================================================*/
548VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
549{
550 VOS_STATUS status = VOS_STATUS_SUCCESS;
551
552 status = hdd_softap_flush_tx_queues(pAdapter);
553
554 return status;
555}
556
557/**============================================================================
558 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
559
560 @param pAdapter : [in] pointer to adapter context
561 @param STAId : [in] Station ID to deinit
562 @return : VOS_STATUS_E_FAILURE if any errors encountered
563 : VOS_STATUS_SUCCESS otherwise
564 ===========================================================================*/
565static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
566{
567 VOS_STATUS status = VOS_STATUS_SUCCESS;
568 v_U8_t i = -1;
569
570 hdd_list_node_t *anchor = NULL;
571
572 skb_list_node_t *pktNode = NULL;
573 struct sk_buff *skb = NULL;
574
575 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
576 {
577 return status;
578 }
579
580 for (i = 0; i < NUM_TX_QUEUES; i ++)
581 {
582 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
583 while (true)
584 {
585 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
586 if (VOS_STATUS_E_EMPTY != status)
587 {
588 //If success then we got a valid packet from some AC
589 pktNode = list_entry(anchor, skb_list_node_t, anchor);
590 skb = pktNode->skb;
591 ++pAdapter->stats.tx_dropped;
592 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
593 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
594 kfree_skb(skb);
595 continue;
596 }
597
598 //current list is empty
599 break;
600 }
601 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
602 }
603
604 return status;
605}
606
607/**============================================================================
608 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
609 modules in HDD
610
611 @param pAdapter : [in] pointer to adapter context
612 @param STAId : [in] Station ID to deinit
613 @param pmacAddrSTA : [in] pointer to the MAC address of the station
614 @return : VOS_STATUS_E_FAILURE if any errors encountered
615 : VOS_STATUS_SUCCESS otherwise
616 ===========================================================================*/
617VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
618{
619 v_U8_t i = 0;
620 spin_lock_bh( &pAdapter->staInfo_lock );
621 if (pAdapter->aStaInfo[STAId].isUsed)
622 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700623 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700624 spin_unlock_bh( &pAdapter->staInfo_lock );
625 return VOS_STATUS_E_FAILURE;
626 }
627
628 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
629 for (i = 0; i < NUM_TX_QUEUES; i ++)
630 {
631 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
632 }
633
634 pAdapter->aStaInfo[STAId].isUsed = TRUE;
635 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
636
637 spin_unlock_bh( &pAdapter->staInfo_lock );
638 return VOS_STATUS_SUCCESS;
639}
640
641/**============================================================================
642 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
643 modules in HDD
644
645 @param pAdapter : [in] pointer to adapter context
646 @param STAId : [in] Station ID to deinit
647 @return : VOS_STATUS_E_FAILURE if any errors encountered
648 : VOS_STATUS_SUCCESS otherwise
649 ===========================================================================*/
650VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
651{
652 VOS_STATUS status = VOS_STATUS_SUCCESS;
653 v_U8_t ac;
654 /**Track whether OS TX queue has been disabled.*/
655 v_BOOL_t txSuspended[NUM_TX_QUEUES];
656 v_U8_t tlAC;
657 hdd_hostapd_state_t *pHostapdState;
658
659 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
660
661 spin_lock_bh( &pAdapter->staInfo_lock );
662 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
663 {
664 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700665 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700666 spin_unlock_bh( &pAdapter->staInfo_lock );
667 return VOS_STATUS_E_FAILURE;
668 }
669
670 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
671
672 pAdapter->aStaInfo[STAId].isUsed = FALSE;
673
674 /* if this STA had any of its WMM TX queues suspended, then the
675 associated queue on the network interface was disabled. check
676 to see if that is the case, in which case we need to re-enable
677 the interface queue. but we only do this if the BSS is running
678 since, if the BSS is stopped, all of the interfaces have been
679 stopped and should not be re-enabled */
680
681 if (BSS_START == pHostapdState->bssState)
682 {
683 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
684 {
685 tlAC = hdd_QdiscAcToTlAC[ac];
686 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
687 }
688 }
689 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
690
691 if (BSS_START == pHostapdState->bssState)
692 {
693 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
694 {
695 if (txSuspended[ac])
696 {
697 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700698 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700699 netif_wake_subqueue(pAdapter->dev, ac);
700 }
701 }
702 }
703
704 spin_unlock_bh( &pAdapter->staInfo_lock );
705 return status;
706}
707
708/**============================================================================
709 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
710 modules in HDD
711
712 @param pAdapter : [in] pointer to adapter context
713 @return : VOS_STATUS_E_FAILURE if any errors encountered
714 : VOS_STATUS_SUCCESS otherwise
715 ===========================================================================*/
716VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
717{
718 return hdd_softap_flush_tx_queues(pAdapter);
719}
720
721/**============================================================================
722 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
723 to indicate that a packet has been transmitted across the bus
724 succesfully. OS packet resources can be released after this cbk.
725
726 @param vosContext : [in] pointer to VOS context
727 @param pVosPacket : [in] pointer to VOS packet (containing skb)
728 @param vosStatusIn : [in] status of the transmission
729
730 @return : VOS_STATUS_E_FAILURE if any errors encountered
731 : VOS_STATUS_SUCCESS otherwise
732 ===========================================================================*/
733VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
734 vos_pkt_t *pVosPacket,
735 VOS_STATUS vosStatusIn )
736{
737 VOS_STATUS status = VOS_STATUS_SUCCESS;
738 hdd_adapter_t *pAdapter = NULL;
739 void* pOsPkt = NULL;
740
741 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
742 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700743 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700744 return VOS_STATUS_E_FAILURE;
745 }
746
747 //Return the skb to the OS
748 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
749 if(!VOS_IS_STATUS_SUCCESS( status ))
750 {
751 //This is bad but still try to free the VOSS resources if we can
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700752 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 -0700753 vos_pkt_return_packet( pVosPacket );
754 return VOS_STATUS_E_FAILURE;
755 }
756
757 //Get the Adapter context.
758 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
759 if(pAdapter == NULL)
760 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700761 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 -0700762 }
763 else
764 {
765 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
766 }
767
768 kfree_skb((struct sk_buff *)pOsPkt);
769
770 //Return the VOS packet resources.
771 status = vos_pkt_return_packet( pVosPacket );
772 if(!VOS_IS_STATUS_SUCCESS( status ))
773 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700774 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 -0700775 }
776
777 return status;
778}
779
780
781/**============================================================================
782 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
783 fetch a packet for transmission.
784
785 @param vosContext : [in] pointer to VOS context
786 @param staId : [in] Station for which TL is requesting a pkt
787 @param ac : [in] access category requested by TL
788 @param pVosPacket : [out] pointer to VOS packet packet pointer
789 @param pPktMetaInfo : [out] pointer to meta info for the pkt
790
791 @return : VOS_STATUS_E_EMPTY if no packets to transmit
792 : VOS_STATUS_E_FAILURE if any errors encountered
793 : VOS_STATUS_SUCCESS otherwise
794 ===========================================================================*/
795VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
796 v_U8_t *pStaId,
797 WLANTL_ACEnumType ac,
798 vos_pkt_t **ppVosPacket,
799 WLANTL_MetaInfoType *pPktMetaInfo )
800{
801 VOS_STATUS status = VOS_STATUS_E_FAILURE;
802 hdd_adapter_t *pAdapter = NULL;
803 hdd_list_node_t *anchor = NULL;
804 skb_list_node_t *pktNode = NULL;
805 struct sk_buff *skb = NULL;
806 vos_pkt_t *pVosPacket = NULL;
807 v_MACADDR_t* pDestMacAddress = NULL;
808 v_TIME_t timestamp;
809 v_SIZE_t size = 0;
810 v_U8_t STAId = WLAN_MAX_STA_COUNT;
811 hdd_context_t *pHddCtx = NULL;
812
813 //Sanity check on inputs
814 if ( ( NULL == vosContext ) ||
815 ( NULL == pStaId ) ||
816 ( NULL == ppVosPacket ) ||
817 ( NULL == pPktMetaInfo ) )
818 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700819 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700820 return VOS_STATUS_E_FAILURE;
821 }
822
823 //Get the HDD context.
824 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
825 if ( NULL == pHddCtx )
826 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700827 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 -0700828 return VOS_STATUS_E_FAILURE;
829 }
830
831 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
832 if( NULL == pAdapter )
833 {
834 VOS_ASSERT(0);
835 return VOS_STATUS_E_FAILURE;
836 }
837
838 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
839
840 STAId = *pStaId;
841 if (STAId >= WLAN_MAX_STA_COUNT)
842 {
843 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700844 "%s: Invalid STAId %d passed by TL", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700845 return VOS_STATUS_E_FAILURE;
846 }
847
848 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
849 {
850 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700851 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700852 return VOS_STATUS_E_FAILURE;
853 }
854
855 *ppVosPacket = NULL;
856
857 //Make sure the AC being asked for is sane
858 if( ac > WLANTL_MAX_AC || ac < 0)
859 {
860 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700861 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700862 return VOS_STATUS_E_FAILURE;
863 }
864
865 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
866
867 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700868 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700869
870 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
871 //This simplifies the locking and unlocking of Tx queue
872 status = vos_pkt_wrap_data_packet( &pVosPacket,
873 VOS_PKT_TYPE_TX_802_3_DATA,
874 NULL, //OS Pkt is not being passed
875 hdd_softap_tx_low_resource_cbk,
876 pAdapter );
877
878 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
879 {
880 //Remember VOS is in a low resource situation
881 pAdapter->isVosOutOfResource = VOS_TRUE;
882 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
883 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700884 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700885 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
886 return VOS_STATUS_E_FAILURE;
887 }
888
889 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
890 as the other branch does.
891 */
892 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
893 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
894
895 if (0 == size)
896 {
897 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
898 vos_pkt_return_packet(pVosPacket);
899 return VOS_STATUS_E_EMPTY;
900 }
901
902 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
903 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
904
905 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700906 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700907
908 if(VOS_STATUS_SUCCESS == status)
909 {
910 //If success then we got a valid packet from some AC
911 pktNode = list_entry(anchor, skb_list_node_t, anchor);
912 skb = pktNode->skb;
913 }
914 else
915 {
916 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
917 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
918 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700919 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -0700920 vos_pkt_return_packet(pVosPacket);
921 return VOS_STATUS_E_FAILURE;
922 }
923
924 //Attach skb to VOS packet.
925 status = vos_pkt_set_os_packet( pVosPacket, skb );
926 if (status != VOS_STATUS_SUCCESS)
927 {
928 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700929 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700930 vos_pkt_return_packet(pVosPacket);
931 ++pAdapter->stats.tx_dropped;
932 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
933 kfree_skb(skb);
934 return VOS_STATUS_E_FAILURE;
935 }
936
937 //Just being paranoid. To be removed later
938 if(pVosPacket == NULL)
939 {
940 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700941 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700942 ++pAdapter->stats.tx_dropped;
943 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
944 kfree_skb(skb);
945 return VOS_STATUS_E_FAILURE;
946 }
947
948 //Return VOS packet to TL;
949 *ppVosPacket = pVosPacket;
950
951 //Fill out the meta information needed by TL
952 //FIXME This timestamp is really the time stamp of wrap_data_packet
953 vos_pkt_get_timestamp( pVosPacket, &timestamp );
954 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
955 if ( 1 < size )
956 {
957 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
958 }
959 else
960 {
961 pPktMetaInfo->bMorePackets = 0;
962 }
963
964 pPktMetaInfo->ucIsEapol = 0;
965
966 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
967 {
968 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
969 {
970 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700971 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700972 pPktMetaInfo->ucIsEapol = 1;
973 }
974 }
975
976//xg: @@@@: temporarily disble these. will revisit later
977#ifndef WLAN_SOFTAP_FEATURE
978 if(pAdapter->conn_info.uIsAuthenticated == VOS_TRUE)
979 pPktMetaInfo->ucIsEapol = 0;
980 else
981 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
982
983 if ((HDD_WMM_USER_MODE_NO_QOS == pAdapter->cfg_ini->WmmMode) ||
984 (!pAdapter->hddWmmStatus.wmmQap))
985 {
986 // either we don't want QoS or the AP doesn't support QoS
987 pPktMetaInfo->ucUP = 0;
988 pPktMetaInfo->ucTID = 0;
989 }
990 else
991#endif
992 {
993 pPktMetaInfo->ucUP = pktNode->userPriority;
994 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
995 }
996
997 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
998 //Extract the destination address from ethernet frame
999 pDestMacAddress = (v_MACADDR_t*)skb->data;
1000
1001 // we need 802.3 to 802.11 frame translation
1002 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1003 pPktMetaInfo->ucDisableFrmXtl = 0;
1004 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1005 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1006
1007 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1008 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1009 {
1010 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001011 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001012 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1013 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1014 }
1015
1016 // We're giving the packet to TL so consider it transmitted from
1017 // a statistics perspective. We account for it here instead of
1018 // when the packet is returned for two reasons. First, TL will
1019 // manipulate the skb to the point where the len field is not
1020 // accurate, leading to inaccurate byte counts if we account for
1021 // it later. Second, TL does not provide any feedback as to
1022 // whether or not the packet was successfully sent over the air,
1023 // so the packet counts will be the same regardless of where we
1024 // account for them
1025 pAdapter->stats.tx_bytes += skb->len;
1026 ++pAdapter->stats.tx_packets;
1027 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1028 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1029
1030 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001031 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001032
1033 return status;
1034}
1035
1036
1037/**============================================================================
1038 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1039 case where VOS packets are not available at the time of the call to get
1040 packets. This callback function is invoked by VOS when packets are
1041 available.
1042
1043 @param pVosPacket : [in] pointer to VOS packet
1044 @param userData : [in] opaque user data that was passed initially
1045
1046 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1047 : VOS_STATUS_SUCCESS otherwise
1048 =============================================================================*/
1049VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1050 v_VOID_t *userData )
1051{
1052 VOS_STATUS status;
1053 v_SINT_t i = 0;
1054 v_SIZE_t size = 0;
1055 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1056 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1057
1058 if(pAdapter == NULL)
1059 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001060 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 -07001061 return VOS_STATUS_E_FAILURE;
1062 }
1063
1064 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1065 //situation. Here we will only signal TL that there is a pending data for a STA.
1066 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1067 vos_pkt_return_packet( pVosPacket );
1068
1069 pAdapter->isVosOutOfResource = VOS_FALSE;
1070
1071 // Indicate to TL that there is pending data if a queue is non empty.
1072 // This Code wasnt included in earlier version which resulted in
1073 // Traffic stalling
1074 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1075 {
1076 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1077 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1078 {
1079 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1080 {
1081 size = 0;
1082 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1083 if ( size > 0 )
1084 {
1085 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1086 STAId,
1087 (WLANTL_ACEnumType)i );
1088 if( !VOS_IS_STATUS_SUCCESS( status ) )
1089 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001090 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 -07001091 }
1092 }
1093 }
1094 }
1095 }
1096 return VOS_STATUS_SUCCESS;
1097}
1098
1099
1100/**============================================================================
1101 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1102 TL will call this to notify the HDD when one or more packets were
1103 received for a registered STA.
1104
1105 @param vosContext : [in] pointer to VOS context
1106 @param pVosPacketChain : [in] pointer to VOS packet chain
1107 @param staId : [in] Station Id (Adress 1 Index)
1108 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1109
1110 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1111 : VOS_STATUS_SUCCESS otherwise
1112 ===========================================================================*/
1113VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1114 vos_pkt_t *pVosPacketChain,
1115 v_U8_t staId,
1116 WLANTL_RxMetaInfoType* pRxMetaInfo )
1117{
1118 hdd_adapter_t *pAdapter = NULL;
1119 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1120 int rxstat;
1121 struct sk_buff *skb = NULL;
1122 vos_pkt_t* pVosPacket;
1123 vos_pkt_t* pNextVosPacket;
1124 hdd_context_t *pHddCtx = NULL;
1125
1126 //Sanity check on inputs
1127 if ( ( NULL == vosContext ) ||
1128 ( NULL == pVosPacketChain ) ||
1129 ( NULL == pRxMetaInfo ) )
1130 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001131 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001132 return VOS_STATUS_E_FAILURE;
1133 }
1134
1135 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1136 if ( NULL == pHddCtx )
1137 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001138 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 -07001139 return VOS_STATUS_E_FAILURE;
1140 }
1141
1142 pAdapter = pHddCtx->sta_to_adapter[staId];
1143 if( NULL == pAdapter )
1144 {
1145 VOS_ASSERT(0);
1146 return VOS_STATUS_E_FAILURE;
1147 }
1148
1149 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1150
1151 // walk the chain until all are processed
1152 pVosPacket = pVosPacketChain;
1153 do
1154 {
1155 // get the pointer to the next packet in the chain
1156 // (but don't unlink the packet since we free the entire chain later)
1157 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1158
1159 // both "success" and "empty" are acceptable results
1160 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1161 {
1162 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001163 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001164 return VOS_STATUS_E_FAILURE;
1165 }
1166
1167 // Extract the OS packet (skb).
1168 // Tell VOS to detach the OS packet from the VOS packet
1169 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1170 if(!VOS_IS_STATUS_SUCCESS( status ))
1171 {
1172 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001173 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 -07001174 return VOS_STATUS_E_FAILURE;
1175 }
1176
1177 //hdd_softap_dump_sk_buff(skb);
1178
1179 skb->dev = pAdapter->dev;
1180
1181 if(skb->dev == NULL) {
1182
1183 hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR!!Invalid netdevice\n");
1184 return VOS_STATUS_E_FAILURE;
1185 }
1186 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1187 ++pAdapter->stats.rx_packets;
1188 pAdapter->stats.rx_bytes += skb->len;
1189
1190 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1191 {
1192 //MC/BC packets. Duplicate a copy of packet
1193 struct sk_buff *pSkbCopy;
1194 hdd_ap_ctx_t *pHddApCtx;
1195
1196 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1197 if (!(pHddApCtx->apDisableIntraBssFwd))
1198 {
1199 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1200 if (pSkbCopy)
1201 {
1202 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1203 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1204 }
1205 }
1206 else
1207 {
1208 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001209 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001210 }
1211
1212
1213 } //(WLAN_RX_BCMC_STA_ID == staId)
1214
1215 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1216 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1217 {
1218 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001219 "%s: send one packet to kernel \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001220
1221 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001222 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnsone7245742012-09-05 17:12:55 -07001223#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1224 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1225#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001226 rxstat = netif_rx_ni(skb);
1227 if (NET_RX_SUCCESS == rxstat)
1228 {
1229 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
1230 }
1231 else
1232 {
1233 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1234 }
1235 }
1236 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1237 {
1238 kfree_skb(skb);
1239 }
1240 else
1241 {
1242 //loopback traffic
1243 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1244 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1245 }
1246
1247 // now process the next packet in the chain
1248 pVosPacket = pNextVosPacket;
1249
1250 } while (pVosPacket);
1251
1252 //Return the entire VOS packet chain to the resource pool
1253 status = vos_pkt_return_packet( pVosPacketChain );
1254 if(!VOS_IS_STATUS_SUCCESS( status ))
1255 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001256 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 }
1258
1259 pAdapter->dev->last_rx = jiffies;
1260
1261 return status;
1262}
1263
1264VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1265{
1266 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1267 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1268
1269 //Clear station in TL and then update HDD data structures. This helps
1270 //to block RX frames from other station to this station.
1271 vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId );
1272 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1273 {
1274 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1275 "WLANTL_ClearSTAClient() failed to for staID %d. "
1276 "Status= %d [0x%08lX]",
1277 staId, vosStatus, vosStatus );
1278 }
1279
1280 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1281 if( VOS_STATUS_E_FAILURE == vosStatus )
1282 {
1283 VOS_TRACE ( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1284 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
1285 "Status = %d [0x%08lX]",
1286 staId, vosStatus, vosStatus );
1287 return( vosStatus );
1288 }
1289
1290 pHddCtx->sta_to_adapter[staId] = NULL;
1291
1292 return( vosStatus );
1293}
1294
1295VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1296 v_BOOL_t fAuthRequired,
1297 v_BOOL_t fPrivacyBit,
1298 v_U8_t staId,
1299 v_U8_t ucastSig,
1300 v_U8_t bcastSig,
1301 v_MACADDR_t *pPeerMacAddress,
1302 v_BOOL_t fWmmEnabled )
1303{
1304 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001305 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001306 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1307 hdd_adapter_t *pmonAdapter = NULL;
1308
1309 //eCsrEncryptionType connectedCipherAlgo;
1310 //v_BOOL_t fConnected;
1311
1312 /*
1313 * Clean up old entry if it is not cleaned up properly
1314 */
1315 if ( pAdapter->aStaInfo[staId].isUsed )
1316 {
1317 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1318 "clean up old entry for STA %d", staId);
1319 hdd_softap_DeregisterSTA( pAdapter, staId );
1320 }
1321
1322 // Get the Station ID from the one saved during the assocation.
1323
1324 staDesc.ucSTAId = staId;
1325
1326
1327 /*Save the pAdapter Pointer for this staId*/
1328 pHddCtx->sta_to_adapter[staId] = pAdapter;
1329
1330 staDesc.wSTAType = WLAN_STA_SOFTAP;
1331
1332 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1333 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1334 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1335
1336 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1337 "register station \n");
1338 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1339 "station mac %02x:%02x:%02x:%02x:%02x:%02x",
1340 staDesc.vSTAMACAddress.bytes[0],
1341 staDesc.vSTAMACAddress.bytes[1],
1342 staDesc.vSTAMACAddress.bytes[2],
1343 staDesc.vSTAMACAddress.bytes[3],
1344 staDesc.vSTAMACAddress.bytes[4],
1345 staDesc.vSTAMACAddress.bytes[5]);
1346 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1347 "BSSIDforIBSS %02x:%02x:%02x:%02x:%02x:%02x",
1348 staDesc.vBSSIDforIBSS.bytes[0],
1349 staDesc.vBSSIDforIBSS.bytes[1],
1350 staDesc.vBSSIDforIBSS.bytes[2],
1351 staDesc.vBSSIDforIBSS.bytes[3],
1352 staDesc.vBSSIDforIBSS.bytes[4],
1353 staDesc.vBSSIDforIBSS.bytes[5]);
1354 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1355 "SOFTAP SELFMAC %02x:%02x:%02x:%02x:%02x:%02x",
1356 staDesc.vSelfMACAddress.bytes[0],
1357 staDesc.vSelfMACAddress.bytes[1],
1358 staDesc.vSelfMACAddress.bytes[2],
1359 staDesc.vSelfMACAddress.bytes[3],
1360 staDesc.vSelfMACAddress.bytes[4],
1361 staDesc.vSelfMACAddress.bytes[5]);
1362
1363 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1364
1365#ifdef WLAN_SOFTAP_FEATURE
1366 staDesc.ucQosEnabled = fWmmEnabled;
1367#else
1368 // set the QoS field appropriately
1369 if (hdd_wmm_is_active(pAdapter))
1370 {
1371 staDesc.ucQosEnabled = 1;
1372 }
1373 else
1374 {
1375 staDesc.ucQosEnabled = 0;
1376 }
1377#endif
1378 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1379 "HDD SOFTAP register TL QoS_enabled=%d",
1380 staDesc.ucQosEnabled );
1381
1382 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1383
1384
1385#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1386 /* Enable UMA for TX translation only when there is no concurrent session active */
1387 if (vos_concurrent_sessions_running())
1388 {
1389 staDesc.ucSwFrameTXXlation = 1;
1390 }
1391 else
1392 {
1393 staDesc.ucSwFrameTXXlation = 0;
1394 }
1395
1396 // Enable frame translation in software for AMSDU
1397 // reception ONLY. The remaining rx is still
1398 // translated in HW.
1399 staDesc.ucSwFrameRXXlation = 1;
1400#else
1401 // For PRIMA UMA frame translation is not enable yet.
1402 staDesc.ucSwFrameTXXlation = 1;
1403 staDesc.ucSwFrameRXXlation = 1;
1404#endif
1405 staDesc.ucAddRmvLLC = 1;
1406
1407 // Initialize signatures and state
1408 staDesc.ucUcastSig = ucastSig;
1409 staDesc.ucBcastSig = bcastSig;
1410 staDesc.ucInitState = fAuthRequired ?
1411 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1412
Prathyushaf5442802012-12-12 13:58:11 -08001413 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1414
Jeff Johnson295189b2012-06-20 16:38:30 -07001415 // Register the Station with TL...
1416 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1417 hdd_softap_rx_packet_cbk,
1418 hdd_softap_tx_complete_cbk,
1419 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1420
1421 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1422 {
1423 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
1424 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08lX]",
1425 vosStatus, vosStatus );
1426 return vosStatus;
1427 }
1428
1429 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1430 // then go to 'authenticated'. For all other authentication types (those that do
1431 // not require upper layer authentication) we can put TL directly into 'authenticated'
1432 // state.
1433
1434 //VOS_ASSERT( fConnected );
1435 pAdapter->aStaInfo[staId].ucSTAId = staId;
1436 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1437
1438 if ( !fAuthRequired )
1439 {
1440 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1441 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1442
1443 // Connections that do not need Upper layer auth, transition TL directly
1444 // to 'Authenticated' state.
1445 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1446 WLANTL_STA_AUTHENTICATED );
1447
1448 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1449 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1450 }
1451 else
1452 {
1453
1454 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
1455 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1456
1457 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1458 WLANTL_STA_CONNECTED );
1459 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1460
1461 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1462
1463 }
1464 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1465 if(pmonAdapter)
1466 {
1467 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Turn on Monitor the carrier\n");
1468 netif_carrier_on(pmonAdapter->dev);
1469 //Enable Tx queue
1470 netif_tx_start_all_queues(pmonAdapter->dev);
1471 }
1472 netif_carrier_on(pAdapter->dev);
1473 //Enable Tx queue
1474 netif_tx_start_all_queues(pAdapter->dev);
1475
1476 return( vosStatus );
1477}
1478
1479VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1480{
1481 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1482 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1483 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1484
1485
1486 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1487 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1488 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1489
1490 return vosStatus;
1491}
1492
1493VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1494{
1495 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1496}
1497
1498VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1499{
1500 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1501 v_U8_t staId = 0;
1502
1503 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1504
Jeff Johnson43971f52012-07-17 12:26:56 -07001505 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001506 {
1507 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001508 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001509 }
1510
1511 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1512 {
1513 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
1514 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1515
Jeff Johnson43971f52012-07-17 12:26:56 -07001516 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001517 {
1518 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001519 "%s: Failed to deregister sta Id %d", __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001520 }
1521 }
1522
1523 return vosStatus;
1524}
1525
1526VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1527{
1528 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1529 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1530 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
1531#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1532 tHalHandle hHalHandle = (tHalHandle ) vos_get_context(VOS_MODULE_ID_HAL, pVosContext);
1533#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
1534
1535 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001536 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001537
1538#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1539 if(!hHalHandle )
1540 {
1541 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_FATAL,
1542 "%s: The hHalHandle is NULL ptr value");
1543 VOS_ASSERT( 0 );
1544 return VOS_STATUS_E_FAILURE;
1545 }
1546
1547 if (eHAL_STATUS_SUCCESS != halTable_FindStaidByAddr(hHalHandle, (tANI_U8 *)pDestMacAddress, &ucSTAId))
1548 {
1549 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001550 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 return VOS_STATUS_E_FAILURE;
1552 }
1553#else
Jeff Johnson43971f52012-07-17 12:26:56 -07001554 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001555 {
1556 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001557 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001558 return VOS_STATUS_E_FAILURE;
1559 }
1560#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
1561
1562 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1563 {
1564 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001565 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001566 return VOS_STATUS_E_FAILURE;
1567 }
1568
1569 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
1570 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001571 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001572
Jeff Johnson43971f52012-07-17 12:26:56 -07001573 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 {
1575 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1576 }
1577
1578 VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001579 "%s exit\n",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001580
1581 return vosStatus;
1582}
1583
1584
1585VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1586{
1587 v_U8_t i;
1588
1589 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1590 {
1591 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1592 pAdapter->aStaInfo[i].isUsed)
1593 {
1594 *staId = i;
1595 return VOS_STATUS_SUCCESS;
1596 }
1597 }
1598
1599 return VOS_STATUS_E_FAILURE;
1600}
1601
1602#endif //WLAN_SOFTAP_FEATURE