blob: 51f5bd1f0bc252b3670ac84175d4b58e78e353ae [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Jeff Johnson295189b2012-06-20 16:38:30 -070026 */
27
28/**===========================================================================
29
30 \file wlan_hdd_softap_tx_rx.c
31
32 \brief Linux HDD Tx/RX APIs
Kiet Lamaa8e15a2014-02-11 23:30:06 -080033 Copyright 2008 (c) Qualcomm, Incorporated.
34 All Rights Reserved.
35 Qualcomm Confidential and Proprietary.
Jeff Johnson295189b2012-06-20 16:38:30 -070036
37 ==========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070038
39/*---------------------------------------------------------------------------
40 Include files
41 -------------------------------------------------------------------------*/
42#include <linux/semaphore.h>
43#include <wlan_hdd_tx_rx.h>
44#include <wlan_hdd_softap_tx_rx.h>
45#include <wlan_hdd_dp_utils.h>
46#include <wlan_qct_tl.h>
47#include <linux/netdevice.h>
48#include <linux/skbuff.h>
49#include <linux/etherdevice.h>
50//#include <vos_list.h>
51#include <vos_types.h>
52#include <aniGlobal.h>
53#include <halTypes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070054#include <net/ieee80211_radiotap.h>
55
56
57/*---------------------------------------------------------------------------
58 Preprocessor definitions and constants
59 -------------------------------------------------------------------------*/
60
61/*---------------------------------------------------------------------------
62 Type declarations
63 -------------------------------------------------------------------------*/
64
65/*---------------------------------------------------------------------------
66 Function definitions and documenation
67 -------------------------------------------------------------------------*/
68#if 0
69static void hdd_softap_dump_sk_buff(struct sk_buff * skb)
70{
c_hpothu6d1d2a32014-03-18 20:17:03 +053071 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
72 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
73 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
74 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
75 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
76 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
77 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -070078
c_hpothu6d1d2a32014-03-18 20:17:03 +053079 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -070080 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
81 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu6d1d2a32014-03-18 20:17:03 +053082 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -070083 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
84 skb->data[13], skb->data[14], skb->data[15]);
85}
86#endif
Leo Chang64d68bc2013-06-04 15:40:52 -070087
88extern void hdd_set_wlan_suspend_mode(bool suspend);
89
90/**============================================================================
91 @brief hdd_softap_traffic_monitor_timeout_handler() -
92 SAP/P2P GO traffin monitor timeout handler function
93 If no traffic during programmed time, trigger suspand mode
94
95 @param pUsrData : [in] pointer to hdd context
96 @return : NONE
97 ===========================================================================*/
98void hdd_softap_traffic_monitor_timeout_handler( void *pUsrData )
99{
100 hdd_context_t *pHddCtx = (hdd_context_t *)pUsrData;
101 v_TIME_t currentTS;
102
103 if (NULL == pHddCtx)
104 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530105 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Leo Chang64d68bc2013-06-04 15:40:52 -0700106 "%s: Invalid user data, context", __func__);
107 return;
108 }
109
110 currentTS = vos_timer_get_system_time();
111 if (pHddCtx->cfg_ini->trafficIdleTimeout <
112 (currentTS - pHddCtx->traffic_monitor.lastFrameTs))
113 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530114 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530115 "%s: No Data Activity calling Wlan Suspend", __func__ );
Leo Chang64d68bc2013-06-04 15:40:52 -0700116 hdd_set_wlan_suspend_mode(1);
117 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0);
118 }
119 else
120 {
121 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
122 pHddCtx->cfg_ini->trafficIdleTimeout);
123 }
124
125 return;
126}
127
Kiet Lambcf38522013-10-26 18:28:27 +0530128VOS_STATUS hdd_start_trafficMonitor( hdd_adapter_t *pAdapter )
129{
130
131 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
132 VOS_STATUS status = VOS_STATUS_SUCCESS;
133
134 status = wlan_hdd_validate_context(pHddCtx);
135
136 if (0 != status)
137 {
138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
139 "%s: HDD context is not valid", __func__);
140 return status;
141 }
142
143 if ((pHddCtx->cfg_ini->enableTrafficMonitor) &&
144 (!pHddCtx->traffic_monitor.isInitialized))
145 {
146 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
147 vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer,
148 VOS_TIMER_TYPE_SW,
149 hdd_softap_traffic_monitor_timeout_handler,
150 pHddCtx);
151 vos_lock_init(&pHddCtx->traffic_monitor.trafficLock);
152 pHddCtx->traffic_monitor.isInitialized = 1;
153 pHddCtx->traffic_monitor.lastFrameTs = 0;
154 /* Start traffic monitor timer here
155 * If no AP assoc, immediatly go into suspend */
c_hpothu6d1d2a32014-03-18 20:17:03 +0530156 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530157 "%s Start Traffic Monitor Timer", __func__);
158 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
159 pHddCtx->cfg_ini->trafficIdleTimeout);
160 }
161 else
162 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530163 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530164 "%s Traffic Monitor is not Enable in ini file", __func__);
165 }
166 return status;
167}
168
169VOS_STATUS hdd_stop_trafficMonitor( hdd_adapter_t *pAdapter )
170{
171 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
172 VOS_STATUS status = VOS_STATUS_SUCCESS;
173
174 status = wlan_hdd_validate_context(pHddCtx);
175
Kiet Lamae69d7a2013-11-08 14:38:04 +0530176 if (-ENODEV == status)
Kiet Lambcf38522013-10-26 18:28:27 +0530177 {
178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
179 "%s: HDD context is not valid", __func__);
180 return status;
181 }
182
183 if (pHddCtx->traffic_monitor.isInitialized)
184 {
185 if (VOS_TIMER_STATE_STOPPED !=
186 vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer))
187 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530188 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530189 "%s Stop Traffic Monitor Timer", __func__);
190 vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer);
191 }
c_hpothu6d1d2a32014-03-18 20:17:03 +0530192 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530193 "%s Destroy Traffic Monitor Timer", __func__);
194 vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer);
195 vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock);
196 pHddCtx->traffic_monitor.isInitialized = 0;
197 }
Kiet Lamae69d7a2013-11-08 14:38:04 +0530198 return VOS_STATUS_SUCCESS;
Kiet Lambcf38522013-10-26 18:28:27 +0530199}
200
Jeff Johnson295189b2012-06-20 16:38:30 -0700201/**============================================================================
202 @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
203
204 @param pAdapter : [in] pointer to adapter context
205 @return : VOS_STATUS_E_FAILURE if any errors encountered
206 : VOS_STATUS_SUCCESS otherwise
207 ===========================================================================*/
208static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter )
209{
210 VOS_STATUS status = VOS_STATUS_SUCCESS;
211 v_SINT_t i = -1;
212 v_U8_t STAId = 0;
213 hdd_list_node_t *anchor = NULL;
214 skb_list_node_t *pktNode = NULL;
215 struct sk_buff *skb = NULL;
216
217 spin_lock_bh( &pAdapter->staInfo_lock );
218 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
219 {
220 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
221 {
222 continue;
223 }
224
225 for (i = 0; i < NUM_TX_QUEUES; i ++)
226 {
227 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
228 while (true)
229 {
230 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
231
232 if (VOS_STATUS_E_EMPTY != status)
233 {
234 //If success then we got a valid packet from some AC
235 pktNode = list_entry(anchor, skb_list_node_t, anchor);
236 skb = pktNode->skb;
237 ++pAdapter->stats.tx_dropped;
238 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
239 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
240 kfree_skb(skb);
241 continue;
242 }
243
244 //current list is empty
245 break;
246 }
247 pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE;
248 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
249 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530250 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 }
252
253 spin_unlock_bh( &pAdapter->staInfo_lock );
254
255 return status;
256}
257
258/**============================================================================
259 @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
260 transmitting packets. There are 2 versions of this function. One that uses
261 locked queue and other that uses lockless queues. Both have been retained to
262 do some performance testing
263
264 @param skb : [in] pointer to OS packet (sk_buff)
265 @param dev : [in] pointer to Libra network device
266
267 @return : NET_XMIT_DROP if packets are dropped
268 : NET_XMIT_SUCCESS if packet is enqueued succesfully
269 ===========================================================================*/
270int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
271{
272 VOS_STATUS status;
273 WLANTL_ACEnumType ac = WLANTL_AC_BE;
274 sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
275 skb_list_node_t *pktNode = NULL;
276 v_SIZE_t pktListSize = 0;
277 v_BOOL_t txSuspended = VOS_FALSE;
278 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
279 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
280 vos_list_node_t *anchor = NULL;
281 v_U8_t STAId = WLAN_MAX_STA_COUNT;
282 //Extract the destination address from ethernet frame
283 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
284 int os_status = NETDEV_TX_OK;
285
286 pDestMacAddress = (v_MACADDR_t*)skb->data;
287
288 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
289
c_hpothu6d1d2a32014-03-18 20:17:03 +0530290 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700291 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700292
293 spin_lock_bh( &pAdapter->staInfo_lock );
294 if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
295 {
296 //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
297 //ID used for BC/MC traffic. The station id is registered to TL as well.
298 STAId = pHddApCtx->uBCStaId;
299
300 /* Setting priority for broadcast packets which doesn't go to select_queue function */
301 skb->priority = SME_QOS_WMM_UP_BE;
302 skb->queue_mapping = HDD_LINUX_AC_BE;
303
c_hpothu6d1d2a32014-03-18 20:17:03 +0530304 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800305 "%s: BC/MC packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700306 }
307 else
308 {
309 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
310 if (STAId == HDD_WLAN_INVALID_STA_ID)
311 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530312 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700313 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700314 ++pAdapter->stats.tx_dropped;
315 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
316 kfree_skb(skb);
317 goto xmit_done;
318 }
319 else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
320 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530321 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
322 "%s: STA %d is unregistered", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323 ++pAdapter->stats.tx_dropped;
324 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
325 kfree_skb(skb);
326 goto xmit_done;
327 }
328
329 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
330 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
331 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530332 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700333 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700334 ++pAdapter->stats.tx_dropped;
335 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
336 kfree_skb(skb);
337 goto xmit_done;
338 }
339 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
340 {
341 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
342 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530343 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700344 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700345 ++pAdapter->stats.tx_dropped;
346 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
347 kfree_skb(skb);
348 goto xmit_done;
349 }
350 }
351 }
352
353 //Get TL AC corresponding to Qdisc queue index/AC.
354 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
355 //user priority from IP header, which is already extracted and set from
356 //select_queue call back function
357 up = skb->priority;
358 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
359
c_hpothu6d1d2a32014-03-18 20:17:03 +0530360 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700361 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700362
363 // If the memory differentiation mode is enabled, the memory limit of each queue will be
364 // checked. Over-limit packets will be dropped.
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700365 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700366 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
367 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
368 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530369 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800370 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700371 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
372 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
373 txSuspended = VOS_TRUE;
374 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530375
376 /* If 3/4th of the max queue size is used then enable the flag.
377 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
378 if (WLANTL_AC_BE == ac)
379 {
380 if (pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
381 {
382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
383 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
384 pAdapter->aStaInfo[STAId].vosLowResource = VOS_TRUE;
385 }
386 else
387 {
388 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
389 }
390 }
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700391 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700392
393 if (VOS_TRUE == txSuspended)
394 {
395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
396 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700397 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700398 os_status = NETDEV_TX_BUSY;
399 goto xmit_done;
400 }
401
402 //Use the skb->cb field to hold the list node information
403 pktNode = (skb_list_node_t *)&skb->cb;
404
405 //Stick the OS packet inside this node.
406 pktNode->skb = skb;
407
408 //Stick the User Priority inside this node
409 pktNode->userPriority = up;
410
411 INIT_LIST_HEAD(&pktNode->anchor);
412
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700413 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700414 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700415 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700416
417 if ( !VOS_IS_STATUS_SUCCESS( status ) )
418 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530419 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
420 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700421 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
422 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
423 ++pAdapter->stats.tx_dropped;
424 kfree_skb(skb);
425 goto xmit_done;
426 }
427
428 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
429 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Rashmi Ramannacbffcb12014-01-07 13:22:13 +0530430 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700431
432 if (1 == pktListSize)
433 {
434 //Let TL know we have a packet to send for this AC
435 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
436
437 if ( !VOS_IS_STATUS_SUCCESS( status ) )
438 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530439 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
440 "%s: Failed to signal TL for AC=%d STAId =%d",
441 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700442
443 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
444 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
445 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
446 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
447 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
448 ++pAdapter->stats.tx_dropped;
449 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
450 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
451 kfree_skb(skb);
452 goto xmit_done;
453 }
454 }
455 dev->trans_start = jiffies;
456
c_hpothu6d1d2a32014-03-18 20:17:03 +0530457 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
458 "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700459
460xmit_done:
461 spin_unlock_bh( &pAdapter->staInfo_lock );
462 return os_status;
463}
464
465/**============================================================================
466 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
467
468 @param skb : [in] pointer to packet (sk_buff)
469 @param dev : [in] pointer to Libra network device
470 @param STAId : [in] Station Id of Destination Station
471 @param up : [in] User Priority
472
473 @return : NET_XMIT_DROP if packets are dropped
474 : NET_XMIT_SUCCESS if packet is enqueued succesfully
475 ===========================================================================*/
476VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
477 struct net_device *dev,
478 v_U8_t STAId,
479 v_U8_t up)
480{
481 VOS_STATUS status = VOS_STATUS_SUCCESS;
482 skb_list_node_t *pktNode = NULL;
483 v_SIZE_t pktListSize = 0;
484 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
485 v_U8_t ac;
486 vos_list_node_t *anchor = NULL;
487
488 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
489
c_hpothu6d1d2a32014-03-18 20:17:03 +0530490 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700491 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700492
493 spin_lock_bh( &pAdapter->staInfo_lock );
494 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
495 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530496 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530497 "%s: STA %d is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700498 kfree_skb(skb);
499 status = VOS_STATUS_E_FAILURE;
500 goto xmit_end;
501 }
502
503 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
504 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
505 up = SME_QOS_WMM_UP_BE;
506
507 ac = hddWmmUpToAcMap[up];
508 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
c_hpothu6d1d2a32014-03-18 20:17:03 +0530509 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700510 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700511
512 skb->queue_mapping = hddLinuxUpToAcMap[up];
513
514 //Use the skb->cb field to hold the list node information
515 pktNode = (skb_list_node_t *)&skb->cb;
516
517 //Stick the OS packet inside this node.
518 pktNode->skb = skb;
519
520 //Stick the User Priority inside this node
521 pktNode->userPriority = up;
522
523 INIT_LIST_HEAD(&pktNode->anchor);
524
525 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
526 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
527 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
528 pktListSize >= pAdapter->aTxQueueLimit[ac])
529 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530530 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800531 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700532 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
533 * SUSPEND should be done based on Threshold. RESUME would be
534 * triggered in fetch cbk after recovery.
535 */
536 kfree_skb(skb);
537 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
538 status = VOS_STATUS_E_FAILURE;
539 goto xmit_end;
540 }
541 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
542 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
543
544 if ( !VOS_IS_STATUS_SUCCESS( status ) )
545 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530546 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
547 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700548 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
549 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
550 ++pAdapter->stats.tx_dropped;
551 kfree_skb(skb);
552 status = VOS_STATUS_E_FAILURE;
553 goto xmit_end;
554 }
555
556 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
557 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
558
559 if (1 == pktListSize)
560 {
561 //Let TL know we have a packet to send for this AC
c_hpothu6d1d2a32014-03-18 20:17:03 +0530562 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
563 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700564
565 if ( !VOS_IS_STATUS_SUCCESS( status ) )
566 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530567 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
568 "%s: Failed to signal TL for AC=%d STAId =%d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700569 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700570
571 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
572 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
573 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
574 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
575 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
576 ++pAdapter->stats.tx_dropped;
577 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
578 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
579 kfree_skb(skb);
580 status = VOS_STATUS_E_FAILURE;
581 goto xmit_end;
582 }
583 }
584
c_hpothu6d1d2a32014-03-18 20:17:03 +0530585 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700586
587xmit_end:
588 spin_unlock_bh( &pAdapter->staInfo_lock );
589 return status;
590}
591
592/**============================================================================
593 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
594 timeout during transmission. Since HDD simply enqueues packet
595 and returns control to OS right away, this would never be invoked
596
597 @param dev : [in] pointer to Libra network device
598 @return : None
599 ===========================================================================*/
600void hdd_softap_tx_timeout(struct net_device *dev)
601{
c_hpothu6d1d2a32014-03-18 20:17:03 +0530602 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700603 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700604 //Getting here implies we disabled the TX queues for too long. Queues are
605 //disabled either because of disassociation or low resource scenarios. In
606 //case of disassociation it is ok to ignore this. But if associated, we have
607 //do possible recovery here
608}
609
610
611/**============================================================================
612 @brief hdd_softap_stats() - Function registered with the Linux OS for
613 device TX/RX statistic
614
615 @param dev : [in] pointer to Libra network device
616
617 @return : pointer to net_device_stats structure
618 ===========================================================================*/
619struct net_device_stats* hdd_softap_stats(struct net_device *dev)
620{
621 hdd_adapter_t* priv = netdev_priv(dev);
622 return &priv->stats;
623}
624
625
626/**============================================================================
627 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
628 modules in HDD
629
630 @param pAdapter : [in] pointer to adapter context
631 @return : VOS_STATUS_E_FAILURE if any errors encountered
632 : VOS_STATUS_SUCCESS otherwise
633 ===========================================================================*/
634VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
635{
636 VOS_STATUS status = VOS_STATUS_SUCCESS;
637 v_SINT_t i = -1;
638 v_SIZE_t size = 0;
639
640 v_U8_t STAId = 0;
641
642 v_U8_t pACWeights[] = {
643 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
644 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
645 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
646 HDD_SOFTAP_VO_WEIGHT_DEFAULT
647 };
Leo Chang64d68bc2013-06-04 15:40:52 -0700648
Jeff Johnson295189b2012-06-20 16:38:30 -0700649 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530650 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700651
652 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
653
654 while (++i != NUM_TX_QUEUES)
655 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
656
657 /* Initial HDD buffer control / flow control fields*/
658 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
659
660 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
661 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
662 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
663 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
664
665 spin_lock_init( &pAdapter->staInfo_lock );
666
667 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
668 {
669 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
670 for (i = 0; i < NUM_TX_QUEUES; i ++)
671 {
672 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
673 }
674 }
675
Yue Ma3ede6052013-08-29 00:33:26 -0700676 /* Update the AC weights suitable for SoftAP mode of operation */
677 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
678
Kiet Lambcf38522013-10-26 18:28:27 +0530679 if (VOS_STATUS_SUCCESS != hdd_start_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700680 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530681 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530682 "%s: failed to start Traffic Monito timer ", __func__ );
683 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700684 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700685 return status;
686}
687
688/**============================================================================
689 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
690 modules in HDD
691
692 @param pAdapter : [in] pointer to adapter context
693 @return : VOS_STATUS_E_FAILURE if any errors encountered
694 : VOS_STATUS_SUCCESS otherwise
695 ===========================================================================*/
696VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
697{
698 VOS_STATUS status = VOS_STATUS_SUCCESS;
Leo Chang64d68bc2013-06-04 15:40:52 -0700699
Kiet Lambcf38522013-10-26 18:28:27 +0530700 if (VOS_STATUS_SUCCESS != hdd_stop_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700701 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530702 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530703 "%s: Fail to Stop Traffic Monito timer", __func__ );
704 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700705 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700706
707 status = hdd_softap_flush_tx_queues(pAdapter);
708
709 return status;
710}
711
712/**============================================================================
713 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
714
715 @param pAdapter : [in] pointer to adapter context
716 @param STAId : [in] Station ID to deinit
717 @return : VOS_STATUS_E_FAILURE if any errors encountered
718 : VOS_STATUS_SUCCESS otherwise
719 ===========================================================================*/
720static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
721{
Jeff Johnson295189b2012-06-20 16:38:30 -0700722 v_U8_t i = -1;
723
724 hdd_list_node_t *anchor = NULL;
725
726 skb_list_node_t *pktNode = NULL;
727 struct sk_buff *skb = NULL;
728
729 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
730 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530731 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700732 }
733
734 for (i = 0; i < NUM_TX_QUEUES; i ++)
735 {
736 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
737 while (true)
738 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530739 if (VOS_STATUS_E_EMPTY !=
740 hdd_list_remove_front(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
741 &anchor))
Jeff Johnson295189b2012-06-20 16:38:30 -0700742 {
743 //If success then we got a valid packet from some AC
744 pktNode = list_entry(anchor, skb_list_node_t, anchor);
745 skb = pktNode->skb;
746 ++pAdapter->stats.tx_dropped;
747 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
748 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
749 kfree_skb(skb);
750 continue;
751 }
752
753 //current list is empty
754 break;
755 }
756 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
757 }
758
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530759 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700760}
761
762/**============================================================================
763 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
764 modules in HDD
765
766 @param pAdapter : [in] pointer to adapter context
767 @param STAId : [in] Station ID to deinit
768 @param pmacAddrSTA : [in] pointer to the MAC address of the station
769 @return : VOS_STATUS_E_FAILURE if any errors encountered
770 : VOS_STATUS_SUCCESS otherwise
771 ===========================================================================*/
772VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
773{
774 v_U8_t i = 0;
775 spin_lock_bh( &pAdapter->staInfo_lock );
776 if (pAdapter->aStaInfo[STAId].isUsed)
777 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530778 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
779 "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700780 spin_unlock_bh( &pAdapter->staInfo_lock );
781 return VOS_STATUS_E_FAILURE;
782 }
783
784 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
785 for (i = 0; i < NUM_TX_QUEUES; i ++)
786 {
787 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
788 }
789
790 pAdapter->aStaInfo[STAId].isUsed = TRUE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800791 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700792 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
793
794 spin_unlock_bh( &pAdapter->staInfo_lock );
795 return VOS_STATUS_SUCCESS;
796}
797
798/**============================================================================
799 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
800 modules in HDD
801
802 @param pAdapter : [in] pointer to adapter context
803 @param STAId : [in] Station ID to deinit
804 @return : VOS_STATUS_E_FAILURE if any errors encountered
805 : VOS_STATUS_SUCCESS otherwise
806 ===========================================================================*/
807VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
808{
809 VOS_STATUS status = VOS_STATUS_SUCCESS;
810 v_U8_t ac;
811 /**Track whether OS TX queue has been disabled.*/
812 v_BOOL_t txSuspended[NUM_TX_QUEUES];
813 v_U8_t tlAC;
814 hdd_hostapd_state_t *pHostapdState;
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700815 v_U8_t i;
Jeff Johnson295189b2012-06-20 16:38:30 -0700816
817 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
818
819 spin_lock_bh( &pAdapter->staInfo_lock );
820 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
821 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530822 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700823 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700824 spin_unlock_bh( &pAdapter->staInfo_lock );
825 return VOS_STATUS_E_FAILURE;
826 }
827
828 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
829
830 pAdapter->aStaInfo[STAId].isUsed = FALSE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800831 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700832
833 /* if this STA had any of its WMM TX queues suspended, then the
834 associated queue on the network interface was disabled. check
835 to see if that is the case, in which case we need to re-enable
836 the interface queue. but we only do this if the BSS is running
837 since, if the BSS is stopped, all of the interfaces have been
838 stopped and should not be re-enabled */
839
840 if (BSS_START == pHostapdState->bssState)
841 {
842 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
843 {
844 tlAC = hdd_QdiscAcToTlAC[ac];
845 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
846 }
847 }
848 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
849
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700850 /* re-init spin lock, since netdev can still open adapter until
851 * driver gets unloaded
852 */
853 for (i = 0; i < NUM_TX_QUEUES; i ++)
854 {
855 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
856 HDD_TX_QUEUE_MAX_LEN);
857 }
858
Jeff Johnson295189b2012-06-20 16:38:30 -0700859 if (BSS_START == pHostapdState->bssState)
860 {
861 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
862 {
863 if (txSuspended[ac])
864 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530865 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700866 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700867 netif_wake_subqueue(pAdapter->dev, ac);
868 }
869 }
870 }
871
872 spin_unlock_bh( &pAdapter->staInfo_lock );
873 return status;
874}
875
876/**============================================================================
877 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
878 modules in HDD
879
880 @param pAdapter : [in] pointer to adapter context
881 @return : VOS_STATUS_E_FAILURE if any errors encountered
882 : VOS_STATUS_SUCCESS otherwise
883 ===========================================================================*/
884VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
885{
886 return hdd_softap_flush_tx_queues(pAdapter);
887}
888
889/**============================================================================
890 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
891 to indicate that a packet has been transmitted across the bus
892 succesfully. OS packet resources can be released after this cbk.
893
894 @param vosContext : [in] pointer to VOS context
895 @param pVosPacket : [in] pointer to VOS packet (containing skb)
896 @param vosStatusIn : [in] status of the transmission
897
898 @return : VOS_STATUS_E_FAILURE if any errors encountered
899 : VOS_STATUS_SUCCESS otherwise
900 ===========================================================================*/
901VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
902 vos_pkt_t *pVosPacket,
903 VOS_STATUS vosStatusIn )
904{
905 VOS_STATUS status = VOS_STATUS_SUCCESS;
906 hdd_adapter_t *pAdapter = NULL;
907 void* pOsPkt = NULL;
908
909 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
910 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530911 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
912 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700913 return VOS_STATUS_E_FAILURE;
914 }
915
916 //Return the skb to the OS
917 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Rajesh Chauhana0516c62014-01-30 16:11:18 -0800918 if ((!VOS_IS_STATUS_SUCCESS(status)) || (!pOsPkt))
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 {
920 //This is bad but still try to free the VOSS resources if we can
c_hpothu6d1d2a32014-03-18 20:17:03 +0530921 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
922 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700923 vos_pkt_return_packet( pVosPacket );
924 return VOS_STATUS_E_FAILURE;
925 }
926
927 //Get the Adapter context.
928 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
929 if(pAdapter == NULL)
930 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530931 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
932 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 }
934 else
935 {
936 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
937 }
938
939 kfree_skb((struct sk_buff *)pOsPkt);
940
941 //Return the VOS packet resources.
942 status = vos_pkt_return_packet( pVosPacket );
943 if(!VOS_IS_STATUS_SUCCESS( status ))
944 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530945 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
946 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700947 }
948
949 return status;
950}
951
952
953/**============================================================================
954 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
955 fetch a packet for transmission.
956
957 @param vosContext : [in] pointer to VOS context
958 @param staId : [in] Station for which TL is requesting a pkt
959 @param ac : [in] access category requested by TL
960 @param pVosPacket : [out] pointer to VOS packet packet pointer
961 @param pPktMetaInfo : [out] pointer to meta info for the pkt
962
963 @return : VOS_STATUS_E_EMPTY if no packets to transmit
964 : VOS_STATUS_E_FAILURE if any errors encountered
965 : VOS_STATUS_SUCCESS otherwise
966 ===========================================================================*/
967VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
968 v_U8_t *pStaId,
969 WLANTL_ACEnumType ac,
970 vos_pkt_t **ppVosPacket,
971 WLANTL_MetaInfoType *pPktMetaInfo )
972{
973 VOS_STATUS status = VOS_STATUS_E_FAILURE;
974 hdd_adapter_t *pAdapter = NULL;
975 hdd_list_node_t *anchor = NULL;
976 skb_list_node_t *pktNode = NULL;
977 struct sk_buff *skb = NULL;
978 vos_pkt_t *pVosPacket = NULL;
979 v_MACADDR_t* pDestMacAddress = NULL;
980 v_TIME_t timestamp;
981 v_SIZE_t size = 0;
982 v_U8_t STAId = WLAN_MAX_STA_COUNT;
983 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -0800984 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700985
986 //Sanity check on inputs
987 if ( ( NULL == vosContext ) ||
988 ( NULL == pStaId ) ||
989 ( NULL == ppVosPacket ) ||
990 ( NULL == pPktMetaInfo ) )
991 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530992 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
993 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700994 return VOS_STATUS_E_FAILURE;
995 }
996
997 //Get the HDD context.
998 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
999 if ( NULL == pHddCtx )
1000 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301001 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1002 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001003 return VOS_STATUS_E_FAILURE;
1004 }
1005
Jeff Johnsonb156c922013-12-05 17:19:46 -08001006 STAId = *pStaId;
1007 if (STAId >= WLAN_MAX_STA_COUNT)
1008 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301009 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001010 "%s: Invalid STAId %d passed by TL", __func__, STAId);
1011 return VOS_STATUS_E_FAILURE;
1012 }
1013
1014 pAdapter = pHddCtx->sta_to_adapter[STAId];
1015 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001016 {
1017 VOS_ASSERT(0);
1018 return VOS_STATUS_E_FAILURE;
1019 }
1020
Jeff Johnsonb156c922013-12-05 17:19:46 -08001021 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
1022 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301023 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001024 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1025 return VOS_STATUS_E_FAILURE;
1026 }
1027
Leo Chang64d68bc2013-06-04 15:40:52 -07001028 /* Monitor traffic */
1029 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1030 {
1031 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1032 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1033 {
1034 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1035 /* It was IDLE mode,
1036 * this is new state, then switch mode from suspend to resume */
1037 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1038 {
1039 hdd_set_wlan_suspend_mode(0);
1040 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1041 pHddCtx->cfg_ini->trafficIdleTimeout);
1042 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1043 }
1044 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1045 }
1046 }
1047
Jeff Johnson295189b2012-06-20 16:38:30 -07001048 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1049
Jeff Johnson295189b2012-06-20 16:38:30 -07001050 *ppVosPacket = NULL;
1051
1052 //Make sure the AC being asked for is sane
1053 if( ac > WLANTL_MAX_AC || ac < 0)
1054 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301055 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001056 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001057 return VOS_STATUS_E_FAILURE;
1058 }
1059
1060 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1061
c_hpothu6d1d2a32014-03-18 20:17:03 +05301062 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001063 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001064
1065 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1066 //This simplifies the locking and unlocking of Tx queue
1067 status = vos_pkt_wrap_data_packet( &pVosPacket,
1068 VOS_PKT_TYPE_TX_802_3_DATA,
1069 NULL, //OS Pkt is not being passed
1070 hdd_softap_tx_low_resource_cbk,
1071 pAdapter );
1072
1073 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1074 {
1075 //Remember VOS is in a low resource situation
1076 pAdapter->isVosOutOfResource = VOS_TRUE;
1077 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301078 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001079 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001080 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1081 return VOS_STATUS_E_FAILURE;
1082 }
1083
1084 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
1085 as the other branch does.
1086 */
1087 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1088 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
1089
1090 if (0 == size)
1091 {
1092 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1093 vos_pkt_return_packet(pVosPacket);
1094 return VOS_STATUS_E_EMPTY;
1095 }
1096
1097 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1098 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1099
c_hpothu6d1d2a32014-03-18 20:17:03 +05301100 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001101 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001102
1103 if(VOS_STATUS_SUCCESS == status)
1104 {
1105 //If success then we got a valid packet from some AC
1106 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1107 skb = pktNode->skb;
1108 }
1109 else
1110 {
1111 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301112 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001113 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001114 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001115 vos_pkt_return_packet(pVosPacket);
1116 return VOS_STATUS_E_FAILURE;
1117 }
1118
1119 //Attach skb to VOS packet.
1120 status = vos_pkt_set_os_packet( pVosPacket, skb );
1121 if (status != VOS_STATUS_SUCCESS)
1122 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301123 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001124 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001125 vos_pkt_return_packet(pVosPacket);
1126 ++pAdapter->stats.tx_dropped;
1127 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1128 kfree_skb(skb);
1129 return VOS_STATUS_E_FAILURE;
1130 }
1131
1132 //Just being paranoid. To be removed later
1133 if(pVosPacket == NULL)
1134 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301135 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001136 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001137 ++pAdapter->stats.tx_dropped;
1138 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1139 kfree_skb(skb);
1140 return VOS_STATUS_E_FAILURE;
1141 }
1142
1143 //Return VOS packet to TL;
1144 *ppVosPacket = pVosPacket;
1145
1146 //Fill out the meta information needed by TL
1147 //FIXME This timestamp is really the time stamp of wrap_data_packet
1148 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1149 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1150 if ( 1 < size )
1151 {
1152 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1153 }
1154 else
1155 {
1156 pPktMetaInfo->bMorePackets = 0;
1157 }
1158
1159 pPktMetaInfo->ucIsEapol = 0;
1160
1161 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
1162 {
1163 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
1164 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301165 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001166 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001167 pPktMetaInfo->ucIsEapol = 1;
1168 }
1169 }
1170
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001171 if (pHddCtx->cfg_ini->gEnableDebugLog)
1172 {
1173 proto_type = vos_pkt_get_proto_type(skb,
1174 pHddCtx->cfg_ini->gEnableDebugLog);
1175 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1176 {
1177 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1178 "SAP TX EAPOL");
1179 }
1180 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1181 {
1182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1183 "SAP TX DHCP");
1184 }
1185 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001186//xg: @@@@: temporarily disble these. will revisit later
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 {
1188 pPktMetaInfo->ucUP = pktNode->userPriority;
1189 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1190 }
1191
1192 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1193 //Extract the destination address from ethernet frame
1194 pDestMacAddress = (v_MACADDR_t*)skb->data;
1195
1196 // we need 802.3 to 802.11 frame translation
1197 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1198 pPktMetaInfo->ucDisableFrmXtl = 0;
1199 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1200 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1201
1202 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1203 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1204 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301205 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001206 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001207 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1208 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1209 }
1210
1211 // We're giving the packet to TL so consider it transmitted from
1212 // a statistics perspective. We account for it here instead of
1213 // when the packet is returned for two reasons. First, TL will
1214 // manipulate the skb to the point where the len field is not
1215 // accurate, leading to inaccurate byte counts if we account for
1216 // it later. Second, TL does not provide any feedback as to
1217 // whether or not the packet was successfully sent over the air,
1218 // so the packet counts will be the same regardless of where we
1219 // account for them
1220 pAdapter->stats.tx_bytes += skb->len;
1221 ++pAdapter->stats.tx_packets;
1222 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1223 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1224
c_hpothu6d1d2a32014-03-18 20:17:03 +05301225 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001226 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001227
1228 return status;
1229}
1230
1231
1232/**============================================================================
1233 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1234 case where VOS packets are not available at the time of the call to get
1235 packets. This callback function is invoked by VOS when packets are
1236 available.
1237
1238 @param pVosPacket : [in] pointer to VOS packet
1239 @param userData : [in] opaque user data that was passed initially
1240
1241 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1242 : VOS_STATUS_SUCCESS otherwise
1243 =============================================================================*/
1244VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1245 v_VOID_t *userData )
1246{
1247 VOS_STATUS status;
1248 v_SINT_t i = 0;
1249 v_SIZE_t size = 0;
1250 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1251 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1252
1253 if(pAdapter == NULL)
1254 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301255 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1256 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 return VOS_STATUS_E_FAILURE;
1258 }
1259
1260 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1261 //situation. Here we will only signal TL that there is a pending data for a STA.
1262 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1263 vos_pkt_return_packet( pVosPacket );
1264
1265 pAdapter->isVosOutOfResource = VOS_FALSE;
1266
1267 // Indicate to TL that there is pending data if a queue is non empty.
1268 // This Code wasnt included in earlier version which resulted in
1269 // Traffic stalling
1270 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1271 {
1272 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1273 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1274 {
1275 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1276 {
1277 size = 0;
1278 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1279 if ( size > 0 )
1280 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301281 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1282 STAId,
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 (WLANTL_ACEnumType)i );
1284 if( !VOS_IS_STATUS_SUCCESS( status ) )
1285 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301286 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1287 "%s: Failure in indicating pkt to TL for ac=%d", __func__,i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001288 }
1289 }
1290 }
1291 }
1292 }
1293 return VOS_STATUS_SUCCESS;
1294}
1295
1296
1297/**============================================================================
1298 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1299 TL will call this to notify the HDD when one or more packets were
1300 received for a registered STA.
1301
1302 @param vosContext : [in] pointer to VOS context
1303 @param pVosPacketChain : [in] pointer to VOS packet chain
1304 @param staId : [in] Station Id (Adress 1 Index)
1305 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1306
1307 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1308 : VOS_STATUS_SUCCESS otherwise
1309 ===========================================================================*/
1310VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1311 vos_pkt_t *pVosPacketChain,
1312 v_U8_t staId,
1313 WLANTL_RxMetaInfoType* pRxMetaInfo )
1314{
1315 hdd_adapter_t *pAdapter = NULL;
1316 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1317 int rxstat;
1318 struct sk_buff *skb = NULL;
1319 vos_pkt_t* pVosPacket;
1320 vos_pkt_t* pNextVosPacket;
1321 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001322 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001323
1324 //Sanity check on inputs
1325 if ( ( NULL == vosContext ) ||
1326 ( NULL == pVosPacketChain ) ||
1327 ( NULL == pRxMetaInfo ) )
1328 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301329 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1330 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001331 return VOS_STATUS_E_FAILURE;
1332 }
1333
1334 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1335 if ( NULL == pHddCtx )
1336 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301337 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1338 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001339 return VOS_STATUS_E_FAILURE;
1340 }
1341
1342 pAdapter = pHddCtx->sta_to_adapter[staId];
1343 if( NULL == pAdapter )
1344 {
1345 VOS_ASSERT(0);
1346 return VOS_STATUS_E_FAILURE;
1347 }
Leo Chang64d68bc2013-06-04 15:40:52 -07001348
1349 /* Monitor traffic */
1350 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1351 {
1352 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1353 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1354 {
1355 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1356 /* It was IDLE mode,
1357 * this is new state, then switch mode from suspend to resume */
1358 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1359 {
1360 hdd_set_wlan_suspend_mode(0);
1361 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1362 pHddCtx->cfg_ini->trafficIdleTimeout);
1363 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1364 }
1365 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1366 }
1367 }
1368
Jeff Johnson295189b2012-06-20 16:38:30 -07001369 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1370
1371 // walk the chain until all are processed
1372 pVosPacket = pVosPacketChain;
1373 do
1374 {
1375 // get the pointer to the next packet in the chain
1376 // (but don't unlink the packet since we free the entire chain later)
1377 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1378
1379 // both "success" and "empty" are acceptable results
1380 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1381 {
1382 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301383 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1384 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001385 return VOS_STATUS_E_FAILURE;
1386 }
1387
1388 // Extract the OS packet (skb).
1389 // Tell VOS to detach the OS packet from the VOS packet
1390 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1391 if(!VOS_IS_STATUS_SUCCESS( status ))
1392 {
1393 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301394 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1395 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001396 return VOS_STATUS_E_FAILURE;
1397 }
1398
1399 //hdd_softap_dump_sk_buff(skb);
1400
1401 skb->dev = pAdapter->dev;
1402
1403 if(skb->dev == NULL) {
1404
c_hpothu6d1d2a32014-03-18 20:17:03 +05301405 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_FATAL,
1406 "ERROR!!Invalid netdevice");
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 return VOS_STATUS_E_FAILURE;
1408 }
1409 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1410 ++pAdapter->stats.rx_packets;
1411 pAdapter->stats.rx_bytes += skb->len;
1412
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001413 if (pHddCtx->cfg_ini->gEnableDebugLog)
1414 {
1415 proto_type = vos_pkt_get_proto_type(skb,
1416 pHddCtx->cfg_ini->gEnableDebugLog);
1417 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1418 {
1419 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1420 "SAP RX EAPOL");
1421 }
1422 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1423 {
1424 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1425 "SAP RX DHCP");
1426 }
1427 }
1428
Jeff Johnson295189b2012-06-20 16:38:30 -07001429 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1430 {
1431 //MC/BC packets. Duplicate a copy of packet
1432 struct sk_buff *pSkbCopy;
1433 hdd_ap_ctx_t *pHddApCtx;
1434
1435 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1436 if (!(pHddApCtx->apDisableIntraBssFwd))
1437 {
1438 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1439 if (pSkbCopy)
1440 {
1441 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1442 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1443 }
1444 }
1445 else
1446 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301447 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001448 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 }
1450
1451
1452 } //(WLAN_RX_BCMC_STA_ID == staId)
1453
1454 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1455 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1456 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301457 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001458 "%s: send one packet to kernel", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001459
1460 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001461 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001462#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001463#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001464 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001465#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001466#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001467 rxstat = netif_rx_ni(skb);
1468 if (NET_RX_SUCCESS == rxstat)
1469 {
1470 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001471 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 }
1473 else
1474 {
1475 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1476 }
1477 }
1478 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1479 {
1480 kfree_skb(skb);
1481 }
1482 else
1483 {
1484 //loopback traffic
1485 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1486 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1487 }
1488
1489 // now process the next packet in the chain
1490 pVosPacket = pNextVosPacket;
1491
1492 } while (pVosPacket);
1493
1494 //Return the entire VOS packet chain to the resource pool
1495 status = vos_pkt_return_packet( pVosPacketChain );
1496 if(!VOS_IS_STATUS_SUCCESS( status ))
1497 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301498 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1499 "%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001500 }
1501
1502 pAdapter->dev->last_rx = jiffies;
1503
1504 return status;
1505}
1506
1507VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1508{
1509 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301510 hdd_context_t *pHddCtx;
1511 if (NULL == pAdapter)
1512 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301513 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301514 "%s: pAdapter is NULL", __func__);
1515 return VOS_STATUS_E_INVAL;
1516 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001517
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301518 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1519 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301520 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301521 "%s: Invalid pAdapter magic", __func__);
1522 return VOS_STATUS_E_INVAL;
1523 }
1524
1525 pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
c_hpothu6d1d2a32014-03-18 20:17:03 +05301526 //Clear station in TL and then update HDD data structures. This helps
Jeff Johnson295189b2012-06-20 16:38:30 -07001527 //to block RX frames from other station to this station.
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301528 vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001529 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1530 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301531 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001532 "WLANTL_ClearSTAClient() failed to for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001533 "Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001534 staId, vosStatus, vosStatus );
1535 }
1536
1537 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1538 if( VOS_STATUS_E_FAILURE == vosStatus )
1539 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301540 VOS_TRACE ( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001541 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001542 "Status = %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001543 staId, vosStatus, vosStatus );
1544 return( vosStatus );
1545 }
1546
1547 pHddCtx->sta_to_adapter[staId] = NULL;
1548
1549 return( vosStatus );
1550}
1551
1552VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1553 v_BOOL_t fAuthRequired,
1554 v_BOOL_t fPrivacyBit,
1555 v_U8_t staId,
1556 v_U8_t ucastSig,
1557 v_U8_t bcastSig,
1558 v_MACADDR_t *pPeerMacAddress,
1559 v_BOOL_t fWmmEnabled )
1560{
1561 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001562 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1564 hdd_adapter_t *pmonAdapter = NULL;
1565
1566 //eCsrEncryptionType connectedCipherAlgo;
1567 //v_BOOL_t fConnected;
1568
1569 /*
1570 * Clean up old entry if it is not cleaned up properly
1571 */
1572 if ( pAdapter->aStaInfo[staId].isUsed )
1573 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301574 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001575 "clean up old entry for STA %d", staId);
1576 hdd_softap_DeregisterSTA( pAdapter, staId );
1577 }
1578
1579 // Get the Station ID from the one saved during the assocation.
1580
1581 staDesc.ucSTAId = staId;
1582
1583
1584 /*Save the pAdapter Pointer for this staId*/
1585 pHddCtx->sta_to_adapter[staId] = pAdapter;
1586
1587 staDesc.wSTAType = WLAN_STA_SOFTAP;
1588
1589 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1590 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1591 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1592
c_hpothu6d1d2a32014-03-18 20:17:03 +05301593 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001594 "register station");
c_hpothu6d1d2a32014-03-18 20:17:03 +05301595 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001596 "station mac " MAC_ADDRESS_STR,
1597 MAC_ADDR_ARRAY(staDesc.vSTAMACAddress.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301598 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001599 "BSSIDforIBSS " MAC_ADDRESS_STR,
1600 MAC_ADDR_ARRAY(staDesc.vBSSIDforIBSS.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301601 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001602 "SOFTAP SELFMAC " MAC_ADDRESS_STR,
1603 MAC_ADDR_ARRAY(staDesc.vSelfMACAddress.bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07001604
1605 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1606
Jeff Johnson295189b2012-06-20 16:38:30 -07001607 staDesc.ucQosEnabled = fWmmEnabled;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301608 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001609 "HDD SOFTAP register TL QoS_enabled=%d",
1610 staDesc.ucQosEnabled );
1611
1612 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1613
1614
Jeff Johnson295189b2012-06-20 16:38:30 -07001615 // For PRIMA UMA frame translation is not enable yet.
1616 staDesc.ucSwFrameTXXlation = 1;
1617 staDesc.ucSwFrameRXXlation = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 staDesc.ucAddRmvLLC = 1;
1619
1620 // Initialize signatures and state
1621 staDesc.ucUcastSig = ucastSig;
1622 staDesc.ucBcastSig = bcastSig;
1623 staDesc.ucInitState = fAuthRequired ?
1624 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1625
Prathyushaf5442802012-12-12 13:58:11 -08001626 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1627
Jeff Johnson295189b2012-06-20 16:38:30 -07001628 // Register the Station with TL...
c_hpothu6d1d2a32014-03-18 20:17:03 +05301629 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1630 hdd_softap_rx_packet_cbk,
1631 hdd_softap_tx_complete_cbk,
Jeff Johnson295189b2012-06-20 16:38:30 -07001632 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1633
1634 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1635 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301636 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001637 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001638 vosStatus, vosStatus );
1639 return vosStatus;
1640 }
1641
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001642 //Timer value should be in milliseconds
1643 if ( pHddCtx->cfg_ini->dynSplitscan &&
1644 ( VOS_TIMER_STATE_RUNNING !=
1645 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
1646 {
1647 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1648 pHddCtx->cfg_ini->trafficMntrTmrForSplitScan);
1649 }
1650
Jeff Johnson295189b2012-06-20 16:38:30 -07001651 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1652 // then go to 'authenticated'. For all other authentication types (those that do
1653 // not require upper layer authentication) we can put TL directly into 'authenticated'
1654 // state.
1655
1656 //VOS_ASSERT( fConnected );
1657 pAdapter->aStaInfo[staId].ucSTAId = staId;
1658 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1659
1660 if ( !fAuthRequired )
1661 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301662 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
1663 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
1664 pAdapter->aStaInfo[staId].ucSTAId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001665
1666 // Connections that do not need Upper layer auth, transition TL directly
1667 // to 'Authenticated' state.
1668 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1669 WLANTL_STA_AUTHENTICATED );
1670
1671 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1672 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1673 }
1674 else
1675 {
1676
c_hpothu6d1d2a32014-03-18 20:17:03 +05301677 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001678 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1679
1680 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1681 WLANTL_STA_CONNECTED );
1682 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1683
1684 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1685
1686 }
1687 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1688 if(pmonAdapter)
1689 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301690 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
1691 "Turn on Monitor the carrier");
Jeff Johnson295189b2012-06-20 16:38:30 -07001692 netif_carrier_on(pmonAdapter->dev);
1693 //Enable Tx queue
1694 netif_tx_start_all_queues(pmonAdapter->dev);
1695 }
1696 netif_carrier_on(pAdapter->dev);
1697 //Enable Tx queue
1698 netif_tx_start_all_queues(pAdapter->dev);
1699
1700 return( vosStatus );
1701}
1702
1703VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1704{
1705 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1706 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1707 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1708
1709
1710 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1711 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1712 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1713
1714 return vosStatus;
1715}
1716
1717VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1718{
1719 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1720}
1721
1722VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1723{
Wilson Yangf80a0542013-10-07 13:02:37 -07001724 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001725 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1726 v_U8_t staId = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07001727 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1728
1729 /*bss deregister is not allowed during wlan driver loading or unloading*/
1730 if (pHddCtx->isLoadUnloadInProgress)
1731 {
1732 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1733 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
1734 return VOS_STATUS_E_PERM;
1735 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001736
1737 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1738
Jeff Johnson43971f52012-07-17 12:26:56 -07001739 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001740 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301741 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001742 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001743 }
1744
1745 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1746 {
1747 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
Jeff Johnson295189b2012-06-20 16:38:30 -07001748 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301749 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1750 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1751 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301752 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001753 "%s: Failed to deregister sta Id %d", __func__, staId);
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301754 }
1755 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001756 }
1757
1758 return vosStatus;
1759}
1760
1761VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1762{
1763 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1764 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1765 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001766
c_hpothu6d1d2a32014-03-18 20:17:03 +05301767 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001768 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001769
Jeff Johnson43971f52012-07-17 12:26:56 -07001770 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001771 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301772 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001773 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001774 return VOS_STATUS_E_FAILURE;
1775 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001776
1777 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1778 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301779 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001780 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001781 return VOS_STATUS_E_FAILURE;
1782 }
1783
1784 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
c_hpothu6d1d2a32014-03-18 20:17:03 +05301785 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001786 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001787
Jeff Johnson43971f52012-07-17 12:26:56 -07001788 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001789 {
1790 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1791 }
1792
c_hpothu6d1d2a32014-03-18 20:17:03 +05301793 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001794 "%s exit",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001795
1796 return vosStatus;
1797}
1798
1799
1800VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1801{
1802 v_U8_t i;
1803
1804 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1805 {
1806 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1807 pAdapter->aStaInfo[i].isUsed)
1808 {
1809 *staId = i;
1810 return VOS_STATUS_SUCCESS;
1811 }
1812 }
1813
1814 return VOS_STATUS_E_FAILURE;
1815}
1816
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301817VOS_STATUS hdd_softap_GetConnectedStaId(hdd_adapter_t *pAdapter, v_U8_t *staId)
1818{
1819 v_U8_t i;
1820
1821 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1822 {
Kiet Lam61589852013-09-19 17:10:58 +05301823 if (pAdapter->aStaInfo[i].isUsed &&
1824 (!vos_is_macaddr_broadcast(&pAdapter->aStaInfo[i].macAddrSTA)))
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301825 {
1826 *staId = i;
1827 return VOS_STATUS_SUCCESS;
1828 }
1829 }
1830
1831 return VOS_STATUS_E_FAILURE;
1832}