blob: ec68f9838e15e7bd6195c18845dfc4a7cc1944be [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Jeff Johnson295189b2012-06-20 16:38:30 -070026 */
27
28/**===========================================================================
29
30 \file wlan_hdd_softap_tx_rx.c
31
32 \brief Linux HDD Tx/RX APIs
Kiet Lamaa8e15a2014-02-11 23:30:06 -080033 Copyright 2008 (c) Qualcomm, Incorporated.
34 All Rights Reserved.
35 Qualcomm Confidential and Proprietary.
Jeff Johnson295189b2012-06-20 16:38:30 -070036
37 ==========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070038
39/*---------------------------------------------------------------------------
40 Include files
41 -------------------------------------------------------------------------*/
42#include <linux/semaphore.h>
43#include <wlan_hdd_tx_rx.h>
44#include <wlan_hdd_softap_tx_rx.h>
45#include <wlan_hdd_dp_utils.h>
46#include <wlan_qct_tl.h>
47#include <linux/netdevice.h>
48#include <linux/skbuff.h>
49#include <linux/etherdevice.h>
50//#include <vos_list.h>
51#include <vos_types.h>
52#include <aniGlobal.h>
53#include <halTypes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070054#include <net/ieee80211_radiotap.h>
Mihir Shetef3473692014-06-27 15:13:20 +053055#include <linux/ratelimit.h>
56#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
57#include <soc/qcom/subsystem_restart.h>
58#else
59#include <mach/subsystem_restart.h>
60#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070061
62
63/*---------------------------------------------------------------------------
64 Preprocessor definitions and constants
65 -------------------------------------------------------------------------*/
66
67/*---------------------------------------------------------------------------
68 Type declarations
69 -------------------------------------------------------------------------*/
70
71/*---------------------------------------------------------------------------
72 Function definitions and documenation
73 -------------------------------------------------------------------------*/
74#if 0
75static void hdd_softap_dump_sk_buff(struct sk_buff * skb)
76{
c_hpothu6d1d2a32014-03-18 20:17:03 +053077 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
78 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
79 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
80 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
81 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
82 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
83 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -070084
c_hpothu6d1d2a32014-03-18 20:17:03 +053085 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -070086 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
87 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu6d1d2a32014-03-18 20:17:03 +053088 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -070089 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
90 skb->data[13], skb->data[14], skb->data[15]);
91}
92#endif
Leo Chang64d68bc2013-06-04 15:40:52 -070093
94extern void hdd_set_wlan_suspend_mode(bool suspend);
95
Mihir Shetef3473692014-06-27 15:13:20 +053096#define HDD_SAP_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
97#define HDD_SAP_TX_TIMEOUT_RATELIMIT_BURST 1
98#define HDD_SAP_TX_STALL_SSR_THRESHOLD 5
99
100static DEFINE_RATELIMIT_STATE(hdd_softap_tx_timeout_rs, \
101 HDD_SAP_TX_TIMEOUT_RATELIMIT_INTERVAL, \
102 HDD_SAP_TX_TIMEOUT_RATELIMIT_BURST);
103
Leo Chang64d68bc2013-06-04 15:40:52 -0700104/**============================================================================
105 @brief hdd_softap_traffic_monitor_timeout_handler() -
106 SAP/P2P GO traffin monitor timeout handler function
107 If no traffic during programmed time, trigger suspand mode
108
109 @param pUsrData : [in] pointer to hdd context
110 @return : NONE
111 ===========================================================================*/
112void hdd_softap_traffic_monitor_timeout_handler( void *pUsrData )
113{
114 hdd_context_t *pHddCtx = (hdd_context_t *)pUsrData;
115 v_TIME_t currentTS;
116
117 if (NULL == pHddCtx)
118 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530119 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Leo Chang64d68bc2013-06-04 15:40:52 -0700120 "%s: Invalid user data, context", __func__);
121 return;
122 }
123
124 currentTS = vos_timer_get_system_time();
125 if (pHddCtx->cfg_ini->trafficIdleTimeout <
126 (currentTS - pHddCtx->traffic_monitor.lastFrameTs))
127 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530128 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530129 "%s: No Data Activity calling Wlan Suspend", __func__ );
Leo Chang64d68bc2013-06-04 15:40:52 -0700130 hdd_set_wlan_suspend_mode(1);
131 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0);
132 }
133 else
134 {
135 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
136 pHddCtx->cfg_ini->trafficIdleTimeout);
137 }
138
139 return;
140}
141
Kiet Lambcf38522013-10-26 18:28:27 +0530142VOS_STATUS hdd_start_trafficMonitor( hdd_adapter_t *pAdapter )
143{
144
145 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
146 VOS_STATUS status = VOS_STATUS_SUCCESS;
147
148 status = wlan_hdd_validate_context(pHddCtx);
149
150 if (0 != status)
151 {
152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
153 "%s: HDD context is not valid", __func__);
154 return status;
155 }
156
157 if ((pHddCtx->cfg_ini->enableTrafficMonitor) &&
158 (!pHddCtx->traffic_monitor.isInitialized))
159 {
160 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
161 vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer,
162 VOS_TIMER_TYPE_SW,
163 hdd_softap_traffic_monitor_timeout_handler,
164 pHddCtx);
165 vos_lock_init(&pHddCtx->traffic_monitor.trafficLock);
166 pHddCtx->traffic_monitor.isInitialized = 1;
167 pHddCtx->traffic_monitor.lastFrameTs = 0;
168 /* Start traffic monitor timer here
169 * If no AP assoc, immediatly go into suspend */
c_hpothu6d1d2a32014-03-18 20:17:03 +0530170 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530171 "%s Start Traffic Monitor Timer", __func__);
172 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
173 pHddCtx->cfg_ini->trafficIdleTimeout);
174 }
175 else
176 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530177 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530178 "%s Traffic Monitor is not Enable in ini file", __func__);
179 }
180 return status;
181}
182
183VOS_STATUS hdd_stop_trafficMonitor( hdd_adapter_t *pAdapter )
184{
185 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
186 VOS_STATUS status = VOS_STATUS_SUCCESS;
187
188 status = wlan_hdd_validate_context(pHddCtx);
189
Kiet Lamae69d7a2013-11-08 14:38:04 +0530190 if (-ENODEV == status)
Kiet Lambcf38522013-10-26 18:28:27 +0530191 {
192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
193 "%s: HDD context is not valid", __func__);
194 return status;
195 }
196
197 if (pHddCtx->traffic_monitor.isInitialized)
198 {
199 if (VOS_TIMER_STATE_STOPPED !=
200 vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer))
201 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530202 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530203 "%s Stop Traffic Monitor Timer", __func__);
204 vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer);
205 }
c_hpothu6d1d2a32014-03-18 20:17:03 +0530206 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530207 "%s Destroy Traffic Monitor Timer", __func__);
208 vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer);
209 vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock);
210 pHddCtx->traffic_monitor.isInitialized = 0;
211 }
Kiet Lamae69d7a2013-11-08 14:38:04 +0530212 return VOS_STATUS_SUCCESS;
Kiet Lambcf38522013-10-26 18:28:27 +0530213}
214
Jeff Johnson295189b2012-06-20 16:38:30 -0700215/**============================================================================
216 @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
217
218 @param pAdapter : [in] pointer to adapter context
219 @return : VOS_STATUS_E_FAILURE if any errors encountered
220 : VOS_STATUS_SUCCESS otherwise
221 ===========================================================================*/
222static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter )
223{
224 VOS_STATUS status = VOS_STATUS_SUCCESS;
225 v_SINT_t i = -1;
226 v_U8_t STAId = 0;
227 hdd_list_node_t *anchor = NULL;
228 skb_list_node_t *pktNode = NULL;
229 struct sk_buff *skb = NULL;
230
231 spin_lock_bh( &pAdapter->staInfo_lock );
232 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
233 {
234 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
235 {
236 continue;
237 }
238
239 for (i = 0; i < NUM_TX_QUEUES; i ++)
240 {
241 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
242 while (true)
243 {
244 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
245
246 if (VOS_STATUS_E_EMPTY != status)
247 {
248 //If success then we got a valid packet from some AC
249 pktNode = list_entry(anchor, skb_list_node_t, anchor);
250 skb = pktNode->skb;
251 ++pAdapter->stats.tx_dropped;
252 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
253 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
254 kfree_skb(skb);
255 continue;
256 }
257
258 //current list is empty
259 break;
260 }
261 pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE;
262 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
263 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530264 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700265 }
266
267 spin_unlock_bh( &pAdapter->staInfo_lock );
268
269 return status;
270}
271
272/**============================================================================
273 @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
274 transmitting packets. There are 2 versions of this function. One that uses
275 locked queue and other that uses lockless queues. Both have been retained to
276 do some performance testing
277
278 @param skb : [in] pointer to OS packet (sk_buff)
279 @param dev : [in] pointer to Libra network device
280
281 @return : NET_XMIT_DROP if packets are dropped
282 : NET_XMIT_SUCCESS if packet is enqueued succesfully
283 ===========================================================================*/
284int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
285{
286 VOS_STATUS status;
287 WLANTL_ACEnumType ac = WLANTL_AC_BE;
288 sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
289 skb_list_node_t *pktNode = NULL;
290 v_SIZE_t pktListSize = 0;
291 v_BOOL_t txSuspended = VOS_FALSE;
292 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
293 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
294 vos_list_node_t *anchor = NULL;
295 v_U8_t STAId = WLAN_MAX_STA_COUNT;
296 //Extract the destination address from ethernet frame
297 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
298 int os_status = NETDEV_TX_OK;
299
300 pDestMacAddress = (v_MACADDR_t*)skb->data;
301
302 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
303
c_hpothu6d1d2a32014-03-18 20:17:03 +0530304 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700305 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700306
307 spin_lock_bh( &pAdapter->staInfo_lock );
308 if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
309 {
310 //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
311 //ID used for BC/MC traffic. The station id is registered to TL as well.
312 STAId = pHddApCtx->uBCStaId;
313
314 /* Setting priority for broadcast packets which doesn't go to select_queue function */
315 skb->priority = SME_QOS_WMM_UP_BE;
316 skb->queue_mapping = HDD_LINUX_AC_BE;
317
c_hpothu6d1d2a32014-03-18 20:17:03 +0530318 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800319 "%s: BC/MC packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320 }
321 else
322 {
323 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
324 if (STAId == HDD_WLAN_INVALID_STA_ID)
325 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530326 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700327 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700328 ++pAdapter->stats.tx_dropped;
329 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
330 kfree_skb(skb);
331 goto xmit_done;
332 }
333 else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
334 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530335 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
336 "%s: STA %d is unregistered", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700337 ++pAdapter->stats.tx_dropped;
338 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
339 kfree_skb(skb);
340 goto xmit_done;
341 }
342
343 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
344 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
345 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530346 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700347 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700348 ++pAdapter->stats.tx_dropped;
349 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
350 kfree_skb(skb);
351 goto xmit_done;
352 }
353 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
354 {
355 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
356 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530357 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700358 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700359 ++pAdapter->stats.tx_dropped;
360 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
361 kfree_skb(skb);
362 goto xmit_done;
363 }
364 }
365 }
366
367 //Get TL AC corresponding to Qdisc queue index/AC.
368 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
369 //user priority from IP header, which is already extracted and set from
370 //select_queue call back function
371 up = skb->priority;
372 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
373
c_hpothu6d1d2a32014-03-18 20:17:03 +0530374 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700375 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700376
377 // If the memory differentiation mode is enabled, the memory limit of each queue will be
378 // checked. Over-limit packets will be dropped.
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700379 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700380 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
381 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
382 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530383 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800384 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
386 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
387 txSuspended = VOS_TRUE;
388 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530389
390 /* If 3/4th of the max queue size is used then enable the flag.
391 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
392 if (WLANTL_AC_BE == ac)
393 {
394 if (pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
395 {
396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
397 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
398 pAdapter->aStaInfo[STAId].vosLowResource = VOS_TRUE;
399 }
400 else
401 {
402 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
403 }
404 }
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700405 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700406
407 if (VOS_TRUE == txSuspended)
408 {
409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
410 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700411 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700412 os_status = NETDEV_TX_BUSY;
413 goto xmit_done;
414 }
415
416 //Use the skb->cb field to hold the list node information
417 pktNode = (skb_list_node_t *)&skb->cb;
418
419 //Stick the OS packet inside this node.
420 pktNode->skb = skb;
421
422 //Stick the User Priority inside this node
423 pktNode->userPriority = up;
424
425 INIT_LIST_HEAD(&pktNode->anchor);
426
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700427 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700428 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700429 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700430
431 if ( !VOS_IS_STATUS_SUCCESS( status ) )
432 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530433 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
434 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700435 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
436 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
437 ++pAdapter->stats.tx_dropped;
438 kfree_skb(skb);
439 goto xmit_done;
440 }
441
442 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
443 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Rashmi Ramannacbffcb12014-01-07 13:22:13 +0530444 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700445
446 if (1 == pktListSize)
447 {
448 //Let TL know we have a packet to send for this AC
449 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
450
451 if ( !VOS_IS_STATUS_SUCCESS( status ) )
452 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530453 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
454 "%s: Failed to signal TL for AC=%d STAId =%d",
455 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700456
457 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
458 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
459 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
460 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
461 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
462 ++pAdapter->stats.tx_dropped;
463 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
464 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
465 kfree_skb(skb);
466 goto xmit_done;
467 }
468 }
469 dev->trans_start = jiffies;
470
c_hpothu6d1d2a32014-03-18 20:17:03 +0530471 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
472 "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700473
474xmit_done:
475 spin_unlock_bh( &pAdapter->staInfo_lock );
476 return os_status;
477}
478
479/**============================================================================
480 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
481
482 @param skb : [in] pointer to packet (sk_buff)
483 @param dev : [in] pointer to Libra network device
484 @param STAId : [in] Station Id of Destination Station
485 @param up : [in] User Priority
486
487 @return : NET_XMIT_DROP if packets are dropped
488 : NET_XMIT_SUCCESS if packet is enqueued succesfully
489 ===========================================================================*/
490VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
491 struct net_device *dev,
492 v_U8_t STAId,
493 v_U8_t up)
494{
495 VOS_STATUS status = VOS_STATUS_SUCCESS;
496 skb_list_node_t *pktNode = NULL;
497 v_SIZE_t pktListSize = 0;
498 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
499 v_U8_t ac;
500 vos_list_node_t *anchor = NULL;
501
502 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
503
c_hpothu6d1d2a32014-03-18 20:17:03 +0530504 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700505 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700506
507 spin_lock_bh( &pAdapter->staInfo_lock );
508 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
509 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530510 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530511 "%s: STA %d is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700512 kfree_skb(skb);
513 status = VOS_STATUS_E_FAILURE;
514 goto xmit_end;
515 }
516
517 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
518 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
519 up = SME_QOS_WMM_UP_BE;
520
521 ac = hddWmmUpToAcMap[up];
522 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
c_hpothu6d1d2a32014-03-18 20:17:03 +0530523 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700524 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700525
526 skb->queue_mapping = hddLinuxUpToAcMap[up];
527
528 //Use the skb->cb field to hold the list node information
529 pktNode = (skb_list_node_t *)&skb->cb;
530
531 //Stick the OS packet inside this node.
532 pktNode->skb = skb;
533
534 //Stick the User Priority inside this node
535 pktNode->userPriority = up;
536
537 INIT_LIST_HEAD(&pktNode->anchor);
538
539 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
540 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
541 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
542 pktListSize >= pAdapter->aTxQueueLimit[ac])
543 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530544 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800545 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
547 * SUSPEND should be done based on Threshold. RESUME would be
548 * triggered in fetch cbk after recovery.
549 */
550 kfree_skb(skb);
551 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
552 status = VOS_STATUS_E_FAILURE;
553 goto xmit_end;
554 }
555 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
556 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
557
558 if ( !VOS_IS_STATUS_SUCCESS( status ) )
559 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530560 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
561 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700562 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
563 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
564 ++pAdapter->stats.tx_dropped;
565 kfree_skb(skb);
566 status = VOS_STATUS_E_FAILURE;
567 goto xmit_end;
568 }
569
570 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
571 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
572
573 if (1 == pktListSize)
574 {
575 //Let TL know we have a packet to send for this AC
c_hpothu6d1d2a32014-03-18 20:17:03 +0530576 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
577 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700578
579 if ( !VOS_IS_STATUS_SUCCESS( status ) )
580 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530581 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
582 "%s: Failed to signal TL for AC=%d STAId =%d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700583 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700584
585 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
586 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
587 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
588 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
589 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
590 ++pAdapter->stats.tx_dropped;
591 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
592 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
593 kfree_skb(skb);
594 status = VOS_STATUS_E_FAILURE;
595 goto xmit_end;
596 }
597 }
598
c_hpothu6d1d2a32014-03-18 20:17:03 +0530599 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700600
601xmit_end:
602 spin_unlock_bh( &pAdapter->staInfo_lock );
603 return status;
604}
605
606/**============================================================================
607 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
608 timeout during transmission. Since HDD simply enqueues packet
609 and returns control to OS right away, this would never be invoked
610
611 @param dev : [in] pointer to Libra network device
612 @return : None
613 ===========================================================================*/
614void hdd_softap_tx_timeout(struct net_device *dev)
615{
Mihir Shetef3473692014-06-27 15:13:20 +0530616 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
617 struct netdev_queue *txq;
618 int i = 0;
619
c_hpothu6d1d2a32014-03-18 20:17:03 +0530620 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700621 "%s: Transmission timeout occurred", __func__);
Mihir Shetef3473692014-06-27 15:13:20 +0530622
623 if ( NULL == pAdapter )
624 {
625 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
626 FL("pAdapter is NULL"));
627 VOS_ASSERT(0);
628 return;
629 }
630
631 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
632
633 for (i = 0; i < 8; i++)
634 {
635 txq = netdev_get_tx_queue(dev, i);
636 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
637 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
638 }
639
640 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
641 "carrier state: %d", netif_carrier_ok(dev));
642
643 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
644
645 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
646 HDD_SAP_TX_STALL_SSR_THRESHOLD)
647 {
648 // Driver could not recover, issue SSR
649 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
650 "%s: Cannot recover from Data stall Issue SSR",
651 __func__);
652 subsystem_restart("wcnss");
653 return;
654 }
655
656 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
657 * every 5sec. The TL debug spits out a lot of information on the
658 * serial console, if it is called every time *hdd_tx_timeout* is
659 * called then we may get a watchdog bite on the Application
660 * processor, so ratelimit the TL debug logs.
661 */
662 if (__ratelimit(&hdd_softap_tx_timeout_rs))
663 {
664 hdd_wmm_tx_snapshot(pAdapter);
665 WLANTL_TLDebugMessage(VOS_TRUE);
666 }
667
Jeff Johnson295189b2012-06-20 16:38:30 -0700668}
669
670
671/**============================================================================
672 @brief hdd_softap_stats() - Function registered with the Linux OS for
673 device TX/RX statistic
674
675 @param dev : [in] pointer to Libra network device
676
677 @return : pointer to net_device_stats structure
678 ===========================================================================*/
679struct net_device_stats* hdd_softap_stats(struct net_device *dev)
680{
681 hdd_adapter_t* priv = netdev_priv(dev);
682 return &priv->stats;
683}
684
685
686/**============================================================================
687 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
688 modules in HDD
689
690 @param pAdapter : [in] pointer to adapter context
691 @return : VOS_STATUS_E_FAILURE if any errors encountered
692 : VOS_STATUS_SUCCESS otherwise
693 ===========================================================================*/
694VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
695{
696 VOS_STATUS status = VOS_STATUS_SUCCESS;
697 v_SINT_t i = -1;
698 v_SIZE_t size = 0;
699
700 v_U8_t STAId = 0;
701
702 v_U8_t pACWeights[] = {
703 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
704 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
705 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
706 HDD_SOFTAP_VO_WEIGHT_DEFAULT
707 };
Leo Chang64d68bc2013-06-04 15:40:52 -0700708
Jeff Johnson295189b2012-06-20 16:38:30 -0700709 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530710 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700711
712 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
713
714 while (++i != NUM_TX_QUEUES)
715 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
716
717 /* Initial HDD buffer control / flow control fields*/
718 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
719
720 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
721 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
722 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
723 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
724
725 spin_lock_init( &pAdapter->staInfo_lock );
726
727 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
728 {
729 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
730 for (i = 0; i < NUM_TX_QUEUES; i ++)
731 {
732 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
733 }
734 }
735
Yue Ma3ede6052013-08-29 00:33:26 -0700736 /* Update the AC weights suitable for SoftAP mode of operation */
737 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
738
Kiet Lambcf38522013-10-26 18:28:27 +0530739 if (VOS_STATUS_SUCCESS != hdd_start_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700740 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530741 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530742 "%s: failed to start Traffic Monito timer ", __func__ );
743 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700744 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700745 return status;
746}
747
748/**============================================================================
749 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
750 modules in HDD
751
752 @param pAdapter : [in] pointer to adapter context
753 @return : VOS_STATUS_E_FAILURE if any errors encountered
754 : VOS_STATUS_SUCCESS otherwise
755 ===========================================================================*/
756VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
757{
758 VOS_STATUS status = VOS_STATUS_SUCCESS;
Leo Chang64d68bc2013-06-04 15:40:52 -0700759
Kiet Lambcf38522013-10-26 18:28:27 +0530760 if (VOS_STATUS_SUCCESS != hdd_stop_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700761 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530762 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530763 "%s: Fail to Stop Traffic Monito timer", __func__ );
764 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700765 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700766
767 status = hdd_softap_flush_tx_queues(pAdapter);
768
769 return status;
770}
771
772/**============================================================================
773 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
774
775 @param pAdapter : [in] pointer to adapter context
776 @param STAId : [in] Station ID to deinit
777 @return : VOS_STATUS_E_FAILURE if any errors encountered
778 : VOS_STATUS_SUCCESS otherwise
779 ===========================================================================*/
780static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
781{
Jeff Johnson295189b2012-06-20 16:38:30 -0700782 v_U8_t i = -1;
783
784 hdd_list_node_t *anchor = NULL;
785
786 skb_list_node_t *pktNode = NULL;
787 struct sk_buff *skb = NULL;
788
789 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
790 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530791 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700792 }
793
794 for (i = 0; i < NUM_TX_QUEUES; i ++)
795 {
796 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
797 while (true)
798 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530799 if (VOS_STATUS_E_EMPTY !=
800 hdd_list_remove_front(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
801 &anchor))
Jeff Johnson295189b2012-06-20 16:38:30 -0700802 {
803 //If success then we got a valid packet from some AC
804 pktNode = list_entry(anchor, skb_list_node_t, anchor);
805 skb = pktNode->skb;
806 ++pAdapter->stats.tx_dropped;
807 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
808 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
809 kfree_skb(skb);
810 continue;
811 }
812
813 //current list is empty
814 break;
815 }
816 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
817 }
818
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530819 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700820}
821
822/**============================================================================
823 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
824 modules in HDD
825
826 @param pAdapter : [in] pointer to adapter context
827 @param STAId : [in] Station ID to deinit
828 @param pmacAddrSTA : [in] pointer to the MAC address of the station
829 @return : VOS_STATUS_E_FAILURE if any errors encountered
830 : VOS_STATUS_SUCCESS otherwise
831 ===========================================================================*/
832VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
833{
834 v_U8_t i = 0;
835 spin_lock_bh( &pAdapter->staInfo_lock );
836 if (pAdapter->aStaInfo[STAId].isUsed)
837 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530838 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
839 "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 spin_unlock_bh( &pAdapter->staInfo_lock );
841 return VOS_STATUS_E_FAILURE;
842 }
843
844 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
845 for (i = 0; i < NUM_TX_QUEUES; i ++)
846 {
847 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
848 }
849
850 pAdapter->aStaInfo[STAId].isUsed = TRUE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800851 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700852 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
853
854 spin_unlock_bh( &pAdapter->staInfo_lock );
855 return VOS_STATUS_SUCCESS;
856}
857
858/**============================================================================
859 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
860 modules in HDD
861
862 @param pAdapter : [in] pointer to adapter context
863 @param STAId : [in] Station ID to deinit
864 @return : VOS_STATUS_E_FAILURE if any errors encountered
865 : VOS_STATUS_SUCCESS otherwise
866 ===========================================================================*/
867VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
868{
869 VOS_STATUS status = VOS_STATUS_SUCCESS;
870 v_U8_t ac;
871 /**Track whether OS TX queue has been disabled.*/
872 v_BOOL_t txSuspended[NUM_TX_QUEUES];
873 v_U8_t tlAC;
874 hdd_hostapd_state_t *pHostapdState;
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700875 v_U8_t i;
Jeff Johnson295189b2012-06-20 16:38:30 -0700876
877 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
878
879 spin_lock_bh( &pAdapter->staInfo_lock );
880 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
881 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530882 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700883 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700884 spin_unlock_bh( &pAdapter->staInfo_lock );
885 return VOS_STATUS_E_FAILURE;
886 }
887
888 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
889
890 pAdapter->aStaInfo[STAId].isUsed = FALSE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800891 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700892
893 /* if this STA had any of its WMM TX queues suspended, then the
894 associated queue on the network interface was disabled. check
895 to see if that is the case, in which case we need to re-enable
896 the interface queue. but we only do this if the BSS is running
897 since, if the BSS is stopped, all of the interfaces have been
898 stopped and should not be re-enabled */
899
900 if (BSS_START == pHostapdState->bssState)
901 {
902 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
903 {
904 tlAC = hdd_QdiscAcToTlAC[ac];
905 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
906 }
907 }
908 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
909
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700910 /* re-init spin lock, since netdev can still open adapter until
911 * driver gets unloaded
912 */
913 for (i = 0; i < NUM_TX_QUEUES; i ++)
914 {
915 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
916 HDD_TX_QUEUE_MAX_LEN);
917 }
918
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 if (BSS_START == pHostapdState->bssState)
920 {
921 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
922 {
923 if (txSuspended[ac])
924 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530925 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700926 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 netif_wake_subqueue(pAdapter->dev, ac);
928 }
929 }
930 }
931
932 spin_unlock_bh( &pAdapter->staInfo_lock );
933 return status;
934}
935
936/**============================================================================
937 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
938 modules in HDD
939
940 @param pAdapter : [in] pointer to adapter context
941 @return : VOS_STATUS_E_FAILURE if any errors encountered
942 : VOS_STATUS_SUCCESS otherwise
943 ===========================================================================*/
944VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
945{
946 return hdd_softap_flush_tx_queues(pAdapter);
947}
948
949/**============================================================================
950 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
951 to indicate that a packet has been transmitted across the bus
952 succesfully. OS packet resources can be released after this cbk.
953
954 @param vosContext : [in] pointer to VOS context
955 @param pVosPacket : [in] pointer to VOS packet (containing skb)
956 @param vosStatusIn : [in] status of the transmission
957
958 @return : VOS_STATUS_E_FAILURE if any errors encountered
959 : VOS_STATUS_SUCCESS otherwise
960 ===========================================================================*/
961VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
962 vos_pkt_t *pVosPacket,
963 VOS_STATUS vosStatusIn )
964{
965 VOS_STATUS status = VOS_STATUS_SUCCESS;
966 hdd_adapter_t *pAdapter = NULL;
967 void* pOsPkt = NULL;
968
969 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
970 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530971 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
972 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 return VOS_STATUS_E_FAILURE;
974 }
975
976 //Return the skb to the OS
977 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Rajesh Chauhana0516c62014-01-30 16:11:18 -0800978 if ((!VOS_IS_STATUS_SUCCESS(status)) || (!pOsPkt))
Jeff Johnson295189b2012-06-20 16:38:30 -0700979 {
980 //This is bad but still try to free the VOSS resources if we can
c_hpothu6d1d2a32014-03-18 20:17:03 +0530981 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
982 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700983 vos_pkt_return_packet( pVosPacket );
984 return VOS_STATUS_E_FAILURE;
985 }
986
987 //Get the Adapter context.
988 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
989 if(pAdapter == NULL)
990 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530991 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
992 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 }
994 else
995 {
996 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
997 }
998
999 kfree_skb((struct sk_buff *)pOsPkt);
1000
1001 //Return the VOS packet resources.
1002 status = vos_pkt_return_packet( pVosPacket );
1003 if(!VOS_IS_STATUS_SUCCESS( status ))
1004 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301005 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1006 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001007 }
1008
1009 return status;
1010}
1011
1012
1013/**============================================================================
1014 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
1015 fetch a packet for transmission.
1016
1017 @param vosContext : [in] pointer to VOS context
1018 @param staId : [in] Station for which TL is requesting a pkt
1019 @param ac : [in] access category requested by TL
1020 @param pVosPacket : [out] pointer to VOS packet packet pointer
1021 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1022
1023 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1024 : VOS_STATUS_E_FAILURE if any errors encountered
1025 : VOS_STATUS_SUCCESS otherwise
1026 ===========================================================================*/
1027VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1028 v_U8_t *pStaId,
1029 WLANTL_ACEnumType ac,
1030 vos_pkt_t **ppVosPacket,
1031 WLANTL_MetaInfoType *pPktMetaInfo )
1032{
1033 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1034 hdd_adapter_t *pAdapter = NULL;
1035 hdd_list_node_t *anchor = NULL;
1036 skb_list_node_t *pktNode = NULL;
1037 struct sk_buff *skb = NULL;
1038 vos_pkt_t *pVosPacket = NULL;
1039 v_MACADDR_t* pDestMacAddress = NULL;
1040 v_TIME_t timestamp;
1041 v_SIZE_t size = 0;
1042 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1043 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001044 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001045
1046 //Sanity check on inputs
1047 if ( ( NULL == vosContext ) ||
1048 ( NULL == pStaId ) ||
1049 ( NULL == ppVosPacket ) ||
1050 ( NULL == pPktMetaInfo ) )
1051 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301052 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1053 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001054 return VOS_STATUS_E_FAILURE;
1055 }
1056
1057 //Get the HDD context.
1058 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1059 if ( NULL == pHddCtx )
1060 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301061 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1062 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001063 return VOS_STATUS_E_FAILURE;
1064 }
1065
Jeff Johnsonb156c922013-12-05 17:19:46 -08001066 STAId = *pStaId;
1067 if (STAId >= WLAN_MAX_STA_COUNT)
1068 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301069 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001070 "%s: Invalid STAId %d passed by TL", __func__, STAId);
1071 return VOS_STATUS_E_FAILURE;
1072 }
1073
1074 pAdapter = pHddCtx->sta_to_adapter[STAId];
1075 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001076 {
1077 VOS_ASSERT(0);
1078 return VOS_STATUS_E_FAILURE;
1079 }
1080
Jeff Johnsonb156c922013-12-05 17:19:46 -08001081 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
1082 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301083 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001084 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1085 return VOS_STATUS_E_FAILURE;
1086 }
1087
Leo Chang64d68bc2013-06-04 15:40:52 -07001088 /* Monitor traffic */
1089 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1090 {
1091 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1092 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1093 {
1094 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1095 /* It was IDLE mode,
1096 * this is new state, then switch mode from suspend to resume */
1097 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1098 {
1099 hdd_set_wlan_suspend_mode(0);
1100 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1101 pHddCtx->cfg_ini->trafficIdleTimeout);
1102 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1103 }
1104 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1105 }
1106 }
1107
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1109
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 *ppVosPacket = NULL;
1111
1112 //Make sure the AC being asked for is sane
1113 if( ac > WLANTL_MAX_AC || ac < 0)
1114 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301115 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001116 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001117 return VOS_STATUS_E_FAILURE;
1118 }
1119
1120 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1121
c_hpothu6d1d2a32014-03-18 20:17:03 +05301122 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001123 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001124
1125 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1126 //This simplifies the locking and unlocking of Tx queue
1127 status = vos_pkt_wrap_data_packet( &pVosPacket,
1128 VOS_PKT_TYPE_TX_802_3_DATA,
1129 NULL, //OS Pkt is not being passed
1130 hdd_softap_tx_low_resource_cbk,
1131 pAdapter );
1132
1133 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1134 {
1135 //Remember VOS is in a low resource situation
1136 pAdapter->isVosOutOfResource = VOS_TRUE;
1137 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301138 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001139 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001140 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1141 return VOS_STATUS_E_FAILURE;
1142 }
1143
1144 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
1145 as the other branch does.
1146 */
1147 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1148 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
1149
1150 if (0 == size)
1151 {
1152 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1153 vos_pkt_return_packet(pVosPacket);
1154 return VOS_STATUS_E_EMPTY;
1155 }
1156
1157 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1158 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1159
c_hpothu6d1d2a32014-03-18 20:17:03 +05301160 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001161 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001162
1163 if(VOS_STATUS_SUCCESS == status)
1164 {
1165 //If success then we got a valid packet from some AC
1166 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1167 skb = pktNode->skb;
1168 }
1169 else
1170 {
1171 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301172 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001173 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001174 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001175 vos_pkt_return_packet(pVosPacket);
1176 return VOS_STATUS_E_FAILURE;
1177 }
1178
1179 //Attach skb to VOS packet.
1180 status = vos_pkt_set_os_packet( pVosPacket, skb );
1181 if (status != VOS_STATUS_SUCCESS)
1182 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301183 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001184 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001185 vos_pkt_return_packet(pVosPacket);
1186 ++pAdapter->stats.tx_dropped;
1187 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1188 kfree_skb(skb);
1189 return VOS_STATUS_E_FAILURE;
1190 }
1191
1192 //Just being paranoid. To be removed later
1193 if(pVosPacket == NULL)
1194 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301195 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001196 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001197 ++pAdapter->stats.tx_dropped;
1198 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1199 kfree_skb(skb);
1200 return VOS_STATUS_E_FAILURE;
1201 }
1202
1203 //Return VOS packet to TL;
1204 *ppVosPacket = pVosPacket;
1205
1206 //Fill out the meta information needed by TL
1207 //FIXME This timestamp is really the time stamp of wrap_data_packet
1208 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1209 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1210 if ( 1 < size )
1211 {
1212 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1213 }
1214 else
1215 {
1216 pPktMetaInfo->bMorePackets = 0;
1217 }
1218
1219 pPktMetaInfo->ucIsEapol = 0;
1220
1221 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
1222 {
1223 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
1224 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301225 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001226 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001227 pPktMetaInfo->ucIsEapol = 1;
1228 }
1229 }
1230
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001231 if (pHddCtx->cfg_ini->gEnableDebugLog)
1232 {
1233 proto_type = vos_pkt_get_proto_type(skb,
1234 pHddCtx->cfg_ini->gEnableDebugLog);
1235 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1236 {
1237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1238 "SAP TX EAPOL");
1239 }
1240 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1241 {
1242 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1243 "SAP TX DHCP");
1244 }
1245 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001246//xg: @@@@: temporarily disble these. will revisit later
Jeff Johnson295189b2012-06-20 16:38:30 -07001247 {
1248 pPktMetaInfo->ucUP = pktNode->userPriority;
1249 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1250 }
1251
1252 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1253 //Extract the destination address from ethernet frame
1254 pDestMacAddress = (v_MACADDR_t*)skb->data;
1255
1256 // we need 802.3 to 802.11 frame translation
1257 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1258 pPktMetaInfo->ucDisableFrmXtl = 0;
1259 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1260 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1261
1262 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1263 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1264 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301265 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001266 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001267 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1268 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1269 }
1270
1271 // We're giving the packet to TL so consider it transmitted from
1272 // a statistics perspective. We account for it here instead of
1273 // when the packet is returned for two reasons. First, TL will
1274 // manipulate the skb to the point where the len field is not
1275 // accurate, leading to inaccurate byte counts if we account for
1276 // it later. Second, TL does not provide any feedback as to
1277 // whether or not the packet was successfully sent over the air,
1278 // so the packet counts will be the same regardless of where we
1279 // account for them
1280 pAdapter->stats.tx_bytes += skb->len;
1281 ++pAdapter->stats.tx_packets;
1282 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1283 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301284 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001285
c_hpothu6d1d2a32014-03-18 20:17:03 +05301286 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001287 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001288
1289 return status;
1290}
1291
1292
1293/**============================================================================
1294 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1295 case where VOS packets are not available at the time of the call to get
1296 packets. This callback function is invoked by VOS when packets are
1297 available.
1298
1299 @param pVosPacket : [in] pointer to VOS packet
1300 @param userData : [in] opaque user data that was passed initially
1301
1302 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1303 : VOS_STATUS_SUCCESS otherwise
1304 =============================================================================*/
1305VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1306 v_VOID_t *userData )
1307{
1308 VOS_STATUS status;
1309 v_SINT_t i = 0;
1310 v_SIZE_t size = 0;
1311 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1312 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1313
1314 if(pAdapter == NULL)
1315 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301316 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1317 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 return VOS_STATUS_E_FAILURE;
1319 }
1320
1321 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1322 //situation. Here we will only signal TL that there is a pending data for a STA.
1323 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1324 vos_pkt_return_packet( pVosPacket );
1325
1326 pAdapter->isVosOutOfResource = VOS_FALSE;
1327
1328 // Indicate to TL that there is pending data if a queue is non empty.
1329 // This Code wasnt included in earlier version which resulted in
1330 // Traffic stalling
1331 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1332 {
1333 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1334 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1335 {
1336 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1337 {
1338 size = 0;
1339 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1340 if ( size > 0 )
1341 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301342 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1343 STAId,
Jeff Johnson295189b2012-06-20 16:38:30 -07001344 (WLANTL_ACEnumType)i );
1345 if( !VOS_IS_STATUS_SUCCESS( status ) )
1346 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301347 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1348 "%s: Failure in indicating pkt to TL for ac=%d", __func__,i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001349 }
1350 }
1351 }
1352 }
1353 }
1354 return VOS_STATUS_SUCCESS;
1355}
1356
1357
1358/**============================================================================
1359 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1360 TL will call this to notify the HDD when one or more packets were
1361 received for a registered STA.
1362
1363 @param vosContext : [in] pointer to VOS context
1364 @param pVosPacketChain : [in] pointer to VOS packet chain
1365 @param staId : [in] Station Id (Adress 1 Index)
1366 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1367
1368 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1369 : VOS_STATUS_SUCCESS otherwise
1370 ===========================================================================*/
1371VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1372 vos_pkt_t *pVosPacketChain,
1373 v_U8_t staId,
1374 WLANTL_RxMetaInfoType* pRxMetaInfo )
1375{
1376 hdd_adapter_t *pAdapter = NULL;
1377 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1378 int rxstat;
1379 struct sk_buff *skb = NULL;
1380 vos_pkt_t* pVosPacket;
1381 vos_pkt_t* pNextVosPacket;
1382 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001383 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001384
1385 //Sanity check on inputs
1386 if ( ( NULL == vosContext ) ||
1387 ( NULL == pVosPacketChain ) ||
1388 ( NULL == pRxMetaInfo ) )
1389 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301390 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1391 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001392 return VOS_STATUS_E_FAILURE;
1393 }
1394
1395 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1396 if ( NULL == pHddCtx )
1397 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301398 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1399 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001400 return VOS_STATUS_E_FAILURE;
1401 }
1402
1403 pAdapter = pHddCtx->sta_to_adapter[staId];
1404 if( NULL == pAdapter )
1405 {
1406 VOS_ASSERT(0);
1407 return VOS_STATUS_E_FAILURE;
1408 }
Leo Chang64d68bc2013-06-04 15:40:52 -07001409
1410 /* Monitor traffic */
1411 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1412 {
1413 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1414 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1415 {
1416 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1417 /* It was IDLE mode,
1418 * this is new state, then switch mode from suspend to resume */
1419 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1420 {
1421 hdd_set_wlan_suspend_mode(0);
1422 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1423 pHddCtx->cfg_ini->trafficIdleTimeout);
1424 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1425 }
1426 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1427 }
1428 }
1429
Jeff Johnson295189b2012-06-20 16:38:30 -07001430 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1431
1432 // walk the chain until all are processed
1433 pVosPacket = pVosPacketChain;
1434 do
1435 {
1436 // get the pointer to the next packet in the chain
1437 // (but don't unlink the packet since we free the entire chain later)
1438 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1439
1440 // both "success" and "empty" are acceptable results
1441 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1442 {
1443 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301444 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1445 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 return VOS_STATUS_E_FAILURE;
1447 }
1448
1449 // Extract the OS packet (skb).
1450 // Tell VOS to detach the OS packet from the VOS packet
1451 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1452 if(!VOS_IS_STATUS_SUCCESS( status ))
1453 {
1454 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301455 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1456 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001457 return VOS_STATUS_E_FAILURE;
1458 }
1459
1460 //hdd_softap_dump_sk_buff(skb);
1461
1462 skb->dev = pAdapter->dev;
1463
1464 if(skb->dev == NULL) {
1465
c_hpothu6d1d2a32014-03-18 20:17:03 +05301466 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_FATAL,
1467 "ERROR!!Invalid netdevice");
Jeff Johnson295189b2012-06-20 16:38:30 -07001468 return VOS_STATUS_E_FAILURE;
1469 }
1470 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1471 ++pAdapter->stats.rx_packets;
1472 pAdapter->stats.rx_bytes += skb->len;
1473
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001474 if (pHddCtx->cfg_ini->gEnableDebugLog)
1475 {
1476 proto_type = vos_pkt_get_proto_type(skb,
1477 pHddCtx->cfg_ini->gEnableDebugLog);
1478 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1479 {
1480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1481 "SAP RX EAPOL");
1482 }
1483 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1484 {
1485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1486 "SAP RX DHCP");
1487 }
1488 }
1489
Jeff Johnson295189b2012-06-20 16:38:30 -07001490 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1491 {
1492 //MC/BC packets. Duplicate a copy of packet
1493 struct sk_buff *pSkbCopy;
1494 hdd_ap_ctx_t *pHddApCtx;
1495
1496 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1497 if (!(pHddApCtx->apDisableIntraBssFwd))
1498 {
1499 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1500 if (pSkbCopy)
1501 {
1502 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1503 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1504 }
1505 }
1506 else
1507 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301508 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001509 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001510 }
1511
1512
1513 } //(WLAN_RX_BCMC_STA_ID == staId)
1514
1515 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1516 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1517 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301518 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001519 "%s: send one packet to kernel", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001520
1521 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001522 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001523#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001524#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001525 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001526#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001527#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001528 rxstat = netif_rx_ni(skb);
1529 if (NET_RX_SUCCESS == rxstat)
1530 {
1531 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001532 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001533 }
1534 else
1535 {
1536 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1537 }
1538 }
1539 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1540 {
1541 kfree_skb(skb);
1542 }
1543 else
1544 {
1545 //loopback traffic
1546 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1547 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1548 }
1549
1550 // now process the next packet in the chain
1551 pVosPacket = pNextVosPacket;
1552
1553 } while (pVosPacket);
1554
1555 //Return the entire VOS packet chain to the resource pool
1556 status = vos_pkt_return_packet( pVosPacketChain );
1557 if(!VOS_IS_STATUS_SUCCESS( status ))
1558 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301559 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1560 "%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001561 }
1562
1563 pAdapter->dev->last_rx = jiffies;
1564
1565 return status;
1566}
1567
1568VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1569{
1570 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301571 hdd_context_t *pHddCtx;
1572 if (NULL == pAdapter)
1573 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301574 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301575 "%s: pAdapter is NULL", __func__);
1576 return VOS_STATUS_E_INVAL;
1577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001578
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301579 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1580 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301581 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301582 "%s: Invalid pAdapter magic", __func__);
1583 return VOS_STATUS_E_INVAL;
1584 }
1585
1586 pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
c_hpothu6d1d2a32014-03-18 20:17:03 +05301587 //Clear station in TL and then update HDD data structures. This helps
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 //to block RX frames from other station to this station.
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301589 vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001590 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1591 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301592 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001593 "WLANTL_ClearSTAClient() failed to for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001594 "Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001595 staId, vosStatus, vosStatus );
1596 }
1597
1598 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1599 if( VOS_STATUS_E_FAILURE == vosStatus )
1600 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301601 VOS_TRACE ( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001602 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001603 "Status = %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001604 staId, vosStatus, vosStatus );
1605 return( vosStatus );
1606 }
1607
1608 pHddCtx->sta_to_adapter[staId] = NULL;
1609
1610 return( vosStatus );
1611}
1612
1613VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1614 v_BOOL_t fAuthRequired,
1615 v_BOOL_t fPrivacyBit,
1616 v_U8_t staId,
1617 v_U8_t ucastSig,
1618 v_U8_t bcastSig,
1619 v_MACADDR_t *pPeerMacAddress,
1620 v_BOOL_t fWmmEnabled )
1621{
1622 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001623 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1625 hdd_adapter_t *pmonAdapter = NULL;
1626
1627 //eCsrEncryptionType connectedCipherAlgo;
1628 //v_BOOL_t fConnected;
1629
1630 /*
1631 * Clean up old entry if it is not cleaned up properly
1632 */
1633 if ( pAdapter->aStaInfo[staId].isUsed )
1634 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301635 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 "clean up old entry for STA %d", staId);
1637 hdd_softap_DeregisterSTA( pAdapter, staId );
1638 }
1639
1640 // Get the Station ID from the one saved during the assocation.
1641
1642 staDesc.ucSTAId = staId;
1643
1644
1645 /*Save the pAdapter Pointer for this staId*/
1646 pHddCtx->sta_to_adapter[staId] = pAdapter;
1647
1648 staDesc.wSTAType = WLAN_STA_SOFTAP;
1649
1650 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1651 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1652 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1653
c_hpothu6d1d2a32014-03-18 20:17:03 +05301654 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001655 "register station");
c_hpothu6d1d2a32014-03-18 20:17:03 +05301656 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001657 "station mac " MAC_ADDRESS_STR,
1658 MAC_ADDR_ARRAY(staDesc.vSTAMACAddress.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301659 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001660 "BSSIDforIBSS " MAC_ADDRESS_STR,
1661 MAC_ADDR_ARRAY(staDesc.vBSSIDforIBSS.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301662 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001663 "SOFTAP SELFMAC " MAC_ADDRESS_STR,
1664 MAC_ADDR_ARRAY(staDesc.vSelfMACAddress.bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07001665
1666 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1667
Jeff Johnson295189b2012-06-20 16:38:30 -07001668 staDesc.ucQosEnabled = fWmmEnabled;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301669 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 "HDD SOFTAP register TL QoS_enabled=%d",
1671 staDesc.ucQosEnabled );
1672
1673 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1674
1675
Jeff Johnson295189b2012-06-20 16:38:30 -07001676 // For PRIMA UMA frame translation is not enable yet.
1677 staDesc.ucSwFrameTXXlation = 1;
1678 staDesc.ucSwFrameRXXlation = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 staDesc.ucAddRmvLLC = 1;
1680
1681 // Initialize signatures and state
1682 staDesc.ucUcastSig = ucastSig;
1683 staDesc.ucBcastSig = bcastSig;
1684 staDesc.ucInitState = fAuthRequired ?
1685 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1686
Prathyushaf5442802012-12-12 13:58:11 -08001687 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1688
Jeff Johnson295189b2012-06-20 16:38:30 -07001689 // Register the Station with TL...
c_hpothu6d1d2a32014-03-18 20:17:03 +05301690 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1691 hdd_softap_rx_packet_cbk,
1692 hdd_softap_tx_complete_cbk,
Jeff Johnson295189b2012-06-20 16:38:30 -07001693 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1694
1695 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1696 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301697 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001698 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001699 vosStatus, vosStatus );
1700 return vosStatus;
1701 }
1702
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001703 //Timer value should be in milliseconds
1704 if ( pHddCtx->cfg_ini->dynSplitscan &&
1705 ( VOS_TIMER_STATE_RUNNING !=
1706 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
1707 {
1708 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1709 pHddCtx->cfg_ini->trafficMntrTmrForSplitScan);
1710 }
1711
Jeff Johnson295189b2012-06-20 16:38:30 -07001712 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1713 // then go to 'authenticated'. For all other authentication types (those that do
1714 // not require upper layer authentication) we can put TL directly into 'authenticated'
1715 // state.
1716
1717 //VOS_ASSERT( fConnected );
1718 pAdapter->aStaInfo[staId].ucSTAId = staId;
1719 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1720
1721 if ( !fAuthRequired )
1722 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301723 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
1724 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
1725 pAdapter->aStaInfo[staId].ucSTAId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001726
1727 // Connections that do not need Upper layer auth, transition TL directly
1728 // to 'Authenticated' state.
1729 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1730 WLANTL_STA_AUTHENTICATED );
1731
1732 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1733 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1734 }
1735 else
1736 {
1737
c_hpothu6d1d2a32014-03-18 20:17:03 +05301738 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001739 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1740
1741 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1742 WLANTL_STA_CONNECTED );
1743 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1744
1745 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1746
1747 }
1748 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1749 if(pmonAdapter)
1750 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301751 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
1752 "Turn on Monitor the carrier");
Jeff Johnson295189b2012-06-20 16:38:30 -07001753 netif_carrier_on(pmonAdapter->dev);
1754 //Enable Tx queue
1755 netif_tx_start_all_queues(pmonAdapter->dev);
1756 }
1757 netif_carrier_on(pAdapter->dev);
1758 //Enable Tx queue
1759 netif_tx_start_all_queues(pAdapter->dev);
1760
1761 return( vosStatus );
1762}
1763
1764VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1765{
1766 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1767 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1768 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1769
1770
1771 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1772 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1773 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1774
1775 return vosStatus;
1776}
1777
1778VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1779{
1780 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1781}
1782
1783VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1784{
Wilson Yangf80a0542013-10-07 13:02:37 -07001785 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001786 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1787 v_U8_t staId = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07001788 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1789
1790 /*bss deregister is not allowed during wlan driver loading or unloading*/
Mihir Shete18156292014-03-11 15:38:30 +05301791 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Wilson Yangf80a0542013-10-07 13:02:37 -07001792 {
1793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1794 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
1795 return VOS_STATUS_E_PERM;
1796 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001797
1798 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1799
Jeff Johnson43971f52012-07-17 12:26:56 -07001800 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001801 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301802 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001803 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001804 }
1805
1806 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1807 {
1808 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
Jeff Johnson295189b2012-06-20 16:38:30 -07001809 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301810 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1811 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1812 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301813 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001814 "%s: Failed to deregister sta Id %d", __func__, staId);
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301815 }
1816 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001817 }
1818
1819 return vosStatus;
1820}
1821
1822VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1823{
1824 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1825 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1826 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001827
c_hpothu6d1d2a32014-03-18 20:17:03 +05301828 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001829 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001830
Jeff Johnson43971f52012-07-17 12:26:56 -07001831 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001832 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301833 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001834 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001835 return VOS_STATUS_E_FAILURE;
1836 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001837
1838 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1839 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301840 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001841 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001842 return VOS_STATUS_E_FAILURE;
1843 }
1844
1845 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
c_hpothu6d1d2a32014-03-18 20:17:03 +05301846 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001847 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001848
Jeff Johnson43971f52012-07-17 12:26:56 -07001849 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001850 {
1851 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1852 }
1853
c_hpothu6d1d2a32014-03-18 20:17:03 +05301854 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001855 "%s exit",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001856
1857 return vosStatus;
1858}
1859
1860
1861VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1862{
1863 v_U8_t i;
1864
1865 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1866 {
1867 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1868 pAdapter->aStaInfo[i].isUsed)
1869 {
1870 *staId = i;
1871 return VOS_STATUS_SUCCESS;
1872 }
1873 }
1874
1875 return VOS_STATUS_E_FAILURE;
1876}
1877
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301878VOS_STATUS hdd_softap_GetConnectedStaId(hdd_adapter_t *pAdapter, v_U8_t *staId)
1879{
1880 v_U8_t i;
1881
1882 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1883 {
Kiet Lam61589852013-09-19 17:10:58 +05301884 if (pAdapter->aStaInfo[i].isUsed &&
1885 (!vos_is_macaddr_broadcast(&pAdapter->aStaInfo[i].macAddrSTA)))
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301886 {
1887 *staId = i;
1888 return VOS_STATUS_SUCCESS;
1889 }
1890 }
1891
1892 return VOS_STATUS_E_FAILURE;
1893}