blob: dca6c524db385e5a67e9c3077a07e383369a2606 [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
Mihir Shete327c2ab2014-11-13 15:17:02 +053099#define HDD_SAP_TX_STALL_RECOVERY_THRESHOLD HDD_SAP_TX_STALL_SSR_THRESHOLD - 2
Mihir Shetef3473692014-06-27 15:13:20 +0530100
101static DEFINE_RATELIMIT_STATE(hdd_softap_tx_timeout_rs, \
102 HDD_SAP_TX_TIMEOUT_RATELIMIT_INTERVAL, \
103 HDD_SAP_TX_TIMEOUT_RATELIMIT_BURST);
104
Leo Chang64d68bc2013-06-04 15:40:52 -0700105/**============================================================================
106 @brief hdd_softap_traffic_monitor_timeout_handler() -
107 SAP/P2P GO traffin monitor timeout handler function
108 If no traffic during programmed time, trigger suspand mode
109
110 @param pUsrData : [in] pointer to hdd context
111 @return : NONE
112 ===========================================================================*/
113void hdd_softap_traffic_monitor_timeout_handler( void *pUsrData )
114{
115 hdd_context_t *pHddCtx = (hdd_context_t *)pUsrData;
116 v_TIME_t currentTS;
117
118 if (NULL == pHddCtx)
119 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530120 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Leo Chang64d68bc2013-06-04 15:40:52 -0700121 "%s: Invalid user data, context", __func__);
122 return;
123 }
124
125 currentTS = vos_timer_get_system_time();
126 if (pHddCtx->cfg_ini->trafficIdleTimeout <
127 (currentTS - pHddCtx->traffic_monitor.lastFrameTs))
128 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530129 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530130 "%s: No Data Activity calling Wlan Suspend", __func__ );
Leo Chang64d68bc2013-06-04 15:40:52 -0700131 hdd_set_wlan_suspend_mode(1);
132 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0);
133 }
134 else
135 {
136 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
137 pHddCtx->cfg_ini->trafficIdleTimeout);
138 }
139
140 return;
141}
142
Kiet Lambcf38522013-10-26 18:28:27 +0530143VOS_STATUS hdd_start_trafficMonitor( hdd_adapter_t *pAdapter )
144{
145
146 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
147 VOS_STATUS status = VOS_STATUS_SUCCESS;
148
149 status = wlan_hdd_validate_context(pHddCtx);
150
151 if (0 != status)
152 {
153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
154 "%s: HDD context is not valid", __func__);
155 return status;
156 }
157
158 if ((pHddCtx->cfg_ini->enableTrafficMonitor) &&
159 (!pHddCtx->traffic_monitor.isInitialized))
160 {
161 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
162 vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer,
163 VOS_TIMER_TYPE_SW,
164 hdd_softap_traffic_monitor_timeout_handler,
165 pHddCtx);
166 vos_lock_init(&pHddCtx->traffic_monitor.trafficLock);
167 pHddCtx->traffic_monitor.isInitialized = 1;
168 pHddCtx->traffic_monitor.lastFrameTs = 0;
169 /* Start traffic monitor timer here
170 * If no AP assoc, immediatly go into suspend */
c_hpothu6d1d2a32014-03-18 20:17:03 +0530171 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530172 "%s Start Traffic Monitor Timer", __func__);
173 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
174 pHddCtx->cfg_ini->trafficIdleTimeout);
175 }
176 else
177 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530178 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530179 "%s Traffic Monitor is not Enable in ini file", __func__);
180 }
181 return status;
182}
183
184VOS_STATUS hdd_stop_trafficMonitor( hdd_adapter_t *pAdapter )
185{
186 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
187 VOS_STATUS status = VOS_STATUS_SUCCESS;
188
189 status = wlan_hdd_validate_context(pHddCtx);
190
Kiet Lamae69d7a2013-11-08 14:38:04 +0530191 if (-ENODEV == status)
Kiet Lambcf38522013-10-26 18:28:27 +0530192 {
193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
194 "%s: HDD context is not valid", __func__);
195 return status;
196 }
197
198 if (pHddCtx->traffic_monitor.isInitialized)
199 {
200 if (VOS_TIMER_STATE_STOPPED !=
201 vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer))
202 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530203 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530204 "%s Stop Traffic Monitor Timer", __func__);
205 vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer);
206 }
c_hpothu6d1d2a32014-03-18 20:17:03 +0530207 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Kiet Lambcf38522013-10-26 18:28:27 +0530208 "%s Destroy Traffic Monitor Timer", __func__);
209 vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer);
210 vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock);
211 pHddCtx->traffic_monitor.isInitialized = 0;
212 }
Kiet Lamae69d7a2013-11-08 14:38:04 +0530213 return VOS_STATUS_SUCCESS;
Kiet Lambcf38522013-10-26 18:28:27 +0530214}
215
Jeff Johnson295189b2012-06-20 16:38:30 -0700216/**============================================================================
217 @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues
218
219 @param pAdapter : [in] pointer to adapter context
220 @return : VOS_STATUS_E_FAILURE if any errors encountered
221 : VOS_STATUS_SUCCESS otherwise
222 ===========================================================================*/
223static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter )
224{
225 VOS_STATUS status = VOS_STATUS_SUCCESS;
226 v_SINT_t i = -1;
227 v_U8_t STAId = 0;
228 hdd_list_node_t *anchor = NULL;
229 skb_list_node_t *pktNode = NULL;
230 struct sk_buff *skb = NULL;
231
232 spin_lock_bh( &pAdapter->staInfo_lock );
233 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
234 {
235 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
236 {
237 continue;
238 }
239
240 for (i = 0; i < NUM_TX_QUEUES; i ++)
241 {
242 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
243 while (true)
244 {
245 status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor);
246
247 if (VOS_STATUS_E_EMPTY != status)
248 {
249 //If success then we got a valid packet from some AC
250 pktNode = list_entry(anchor, skb_list_node_t, anchor);
251 skb = pktNode->skb;
252 ++pAdapter->stats.tx_dropped;
253 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
254 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
255 kfree_skb(skb);
256 continue;
257 }
258
259 //current list is empty
260 break;
261 }
262 pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE;
263 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
264 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530265 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 }
267
268 spin_unlock_bh( &pAdapter->staInfo_lock );
269
270 return status;
271}
272
273/**============================================================================
274 @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for
275 transmitting packets. There are 2 versions of this function. One that uses
276 locked queue and other that uses lockless queues. Both have been retained to
277 do some performance testing
278
279 @param skb : [in] pointer to OS packet (sk_buff)
280 @param dev : [in] pointer to Libra network device
281
282 @return : NET_XMIT_DROP if packets are dropped
283 : NET_XMIT_SUCCESS if packet is enqueued succesfully
284 ===========================================================================*/
285int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
286{
287 VOS_STATUS status;
288 WLANTL_ACEnumType ac = WLANTL_AC_BE;
289 sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
290 skb_list_node_t *pktNode = NULL;
291 v_SIZE_t pktListSize = 0;
292 v_BOOL_t txSuspended = VOS_FALSE;
293 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
294 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530295 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700296 vos_list_node_t *anchor = NULL;
297 v_U8_t STAId = WLAN_MAX_STA_COUNT;
298 //Extract the destination address from ethernet frame
299 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
300 int os_status = NETDEV_TX_OK;
301
302 pDestMacAddress = (v_MACADDR_t*)skb->data;
303
304 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
305
c_hpothu6d1d2a32014-03-18 20:17:03 +0530306 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700307 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700308
309 spin_lock_bh( &pAdapter->staInfo_lock );
310 if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
311 {
312 //The BC/MC station ID is assigned during BSS starting phase. SAP will return the station
313 //ID used for BC/MC traffic. The station id is registered to TL as well.
314 STAId = pHddApCtx->uBCStaId;
315
316 /* Setting priority for broadcast packets which doesn't go to select_queue function */
317 skb->priority = SME_QOS_WMM_UP_BE;
318 skb->queue_mapping = HDD_LINUX_AC_BE;
319
c_hpothu6d1d2a32014-03-18 20:17:03 +0530320 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800321 "%s: BC/MC packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 }
323 else
324 {
325 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
326 if (STAId == HDD_WLAN_INVALID_STA_ID)
327 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530328 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700329 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700330 ++pAdapter->stats.tx_dropped;
331 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
332 kfree_skb(skb);
333 goto xmit_done;
334 }
335 else if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
336 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530337 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
338 "%s: STA %d is unregistered", __func__, STAId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700339 ++pAdapter->stats.tx_dropped;
340 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
341 kfree_skb(skb);
342 goto xmit_done;
343 }
344
345 if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) &&
346 (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) )
347 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530348 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700349 "%s: Station not connected yet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700350 ++pAdapter->stats.tx_dropped;
351 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
352 kfree_skb(skb);
353 goto xmit_done;
354 }
355 else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState)
356 {
357 if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X)
358 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530359 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700360 "%s: NON-EAPOL packet in non-Authenticated state", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700361 ++pAdapter->stats.tx_dropped;
362 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
363 kfree_skb(skb);
364 goto xmit_done;
365 }
366 }
367 }
368
369 //Get TL AC corresponding to Qdisc queue index/AC.
370 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
371 //user priority from IP header, which is already extracted and set from
372 //select_queue call back function
373 up = skb->priority;
374 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
375
c_hpothu6d1d2a32014-03-18 20:17:03 +0530376 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700377 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700378
Dino Mycled9b7cc12014-09-04 18:43:07 +0530379 if ( ( NULL != pHddCtx ) && pHddCtx->cfg_ini->enableDhcpDebug )
380 {
381 hdd_dump_dhcp_pkt(skb, TX_PATH);
382 }
383
Jeff Johnson295189b2012-06-20 16:38:30 -0700384 // If the memory differentiation mode is enabled, the memory limit of each queue will be
385 // checked. Over-limit packets will be dropped.
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700386 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700387 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
388 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
389 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530390 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800391 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700392 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
393 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
394 txSuspended = VOS_TRUE;
395 }
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530396
397 /* If 3/4th of the max queue size is used then enable the flag.
398 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
399 if (WLANTL_AC_BE == ac)
400 {
401 if (pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
402 {
403 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
404 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
405 pAdapter->aStaInfo[STAId].vosLowResource = VOS_TRUE;
406 }
407 else
408 {
409 pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE;
410 }
411 }
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700412 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700413
414 if (VOS_TRUE == txSuspended)
415 {
416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
417 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700418 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700419 os_status = NETDEV_TX_BUSY;
420 goto xmit_done;
421 }
422
423 //Use the skb->cb field to hold the list node information
424 pktNode = (skb_list_node_t *)&skb->cb;
425
426 //Stick the OS packet inside this node.
427 pktNode->skb = skb;
428
429 //Stick the User Priority inside this node
430 pktNode->userPriority = up;
431
432 INIT_LIST_HEAD(&pktNode->anchor);
433
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700434 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700435 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700436 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700437
438 if ( !VOS_IS_STATUS_SUCCESS( status ) )
439 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530440 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
441 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700442 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
443 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
444 ++pAdapter->stats.tx_dropped;
445 kfree_skb(skb);
446 goto xmit_done;
447 }
448
449 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
450 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Rashmi Ramannacbffcb12014-01-07 13:22:13 +0530451 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700452
453 if (1 == pktListSize)
454 {
455 //Let TL know we have a packet to send for this AC
456 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
457
458 if ( !VOS_IS_STATUS_SUCCESS( status ) )
459 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530460 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
461 "%s: Failed to signal TL for AC=%d STAId =%d",
462 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700463
464 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
465 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
466 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
467 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
468 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
469 ++pAdapter->stats.tx_dropped;
470 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
471 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
472 kfree_skb(skb);
473 goto xmit_done;
474 }
475 }
476 dev->trans_start = jiffies;
477
c_hpothu6d1d2a32014-03-18 20:17:03 +0530478 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
479 "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700480
481xmit_done:
482 spin_unlock_bh( &pAdapter->staInfo_lock );
483 return os_status;
484}
485
486/**============================================================================
487 @brief hdd_softap_sta_2_sta_xmit This function for Transmitting the frames when the traffic is between two stations.
488
489 @param skb : [in] pointer to packet (sk_buff)
490 @param dev : [in] pointer to Libra network device
491 @param STAId : [in] Station Id of Destination Station
492 @param up : [in] User Priority
493
494 @return : NET_XMIT_DROP if packets are dropped
495 : NET_XMIT_SUCCESS if packet is enqueued succesfully
496 ===========================================================================*/
497VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb,
498 struct net_device *dev,
499 v_U8_t STAId,
500 v_U8_t up)
501{
502 VOS_STATUS status = VOS_STATUS_SUCCESS;
503 skb_list_node_t *pktNode = NULL;
504 v_SIZE_t pktListSize = 0;
505 hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
506 v_U8_t ac;
507 vos_list_node_t *anchor = NULL;
508
509 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
510
c_hpothu6d1d2a32014-03-18 20:17:03 +0530511 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700512 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700513
514 spin_lock_bh( &pAdapter->staInfo_lock );
515 if ( FALSE == pAdapter->aStaInfo[STAId].isUsed )
516 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530517 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530518 "%s: STA %d is unregistered", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700519 kfree_skb(skb);
520 status = VOS_STATUS_E_FAILURE;
521 goto xmit_end;
522 }
523
524 /* If the QoS is not enabled on the receiving station, then send it with BE priority */
525 if ( !pAdapter->aStaInfo[STAId].isQosEnabled )
526 up = SME_QOS_WMM_UP_BE;
527
528 ac = hddWmmUpToAcMap[up];
529 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
c_hpothu6d1d2a32014-03-18 20:17:03 +0530530 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700531 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700532
533 skb->queue_mapping = hddLinuxUpToAcMap[up];
534
535 //Use the skb->cb field to hold the list node information
536 pktNode = (skb_list_node_t *)&skb->cb;
537
538 //Stick the OS packet inside this node.
539 pktNode->skb = skb;
540
541 //Stick the User Priority inside this node
542 pktNode->userPriority = up;
543
544 INIT_LIST_HEAD(&pktNode->anchor);
545
546 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
547 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
548 if(pAdapter->aStaInfo[STAId].txSuspended[ac] ||
549 pktListSize >= pAdapter->aTxQueueLimit[ac])
550 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530551 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800552 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700553 /* TODO:Rx Flowchart should be trigerred here to SUPEND SSC on RX side.
554 * SUSPEND should be done based on Threshold. RESUME would be
555 * triggered in fetch cbk after recovery.
556 */
557 kfree_skb(skb);
558 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
559 status = VOS_STATUS_E_FAILURE;
560 goto xmit_end;
561 }
562 status = hdd_list_insert_back_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
563 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
564
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:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700569 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
570 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
571 ++pAdapter->stats.tx_dropped;
572 kfree_skb(skb);
573 status = VOS_STATUS_E_FAILURE;
574 goto xmit_end;
575 }
576
577 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
578 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
579
580 if (1 == pktListSize)
581 {
582 //Let TL know we have a packet to send for this AC
c_hpothu6d1d2a32014-03-18 20:17:03 +0530583 //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
584 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700585
586 if ( !VOS_IS_STATUS_SUCCESS( status ) )
587 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530588 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
589 "%s: Failed to signal TL for AC=%d STAId =%d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700590 __func__, ac, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700591
592 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
593 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
594 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
595 status = hdd_list_remove_back( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor);
596 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
597 ++pAdapter->stats.tx_dropped;
598 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
599 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
600 kfree_skb(skb);
601 status = VOS_STATUS_E_FAILURE;
602 goto xmit_end;
603 }
604 }
605
c_hpothu6d1d2a32014-03-18 20:17:03 +0530606 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700607
608xmit_end:
609 spin_unlock_bh( &pAdapter->staInfo_lock );
610 return status;
611}
612
613/**============================================================================
614 @brief hdd_softap_tx_timeout() - Function called by OS if there is any
615 timeout during transmission. Since HDD simply enqueues packet
616 and returns control to OS right away, this would never be invoked
617
618 @param dev : [in] pointer to Libra network device
619 @return : None
620 ===========================================================================*/
621void hdd_softap_tx_timeout(struct net_device *dev)
622{
Mihir Shetef3473692014-06-27 15:13:20 +0530623 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
624 struct netdev_queue *txq;
625 int i = 0;
626
c_hpothu6d1d2a32014-03-18 20:17:03 +0530627 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700628 "%s: Transmission timeout occurred", __func__);
Mihir Shetef3473692014-06-27 15:13:20 +0530629
630 if ( NULL == pAdapter )
631 {
632 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
633 FL("pAdapter is NULL"));
634 VOS_ASSERT(0);
635 return;
636 }
637
638 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
639
640 for (i = 0; i < 8; i++)
641 {
642 txq = netdev_get_tx_queue(dev, i);
643 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
644 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
645 }
646
647 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
648 "carrier state: %d", netif_carrier_ok(dev));
649
650 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
651
Mihir Shete327c2ab2014-11-13 15:17:02 +0530652 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
653 HDD_SAP_TX_STALL_RECOVERY_THRESHOLD)
654 {
655 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
656 "%s: Request firmware for recovery",__func__);
657 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
658 }
Mihir Shetef3473692014-06-27 15:13:20 +0530659 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
660 HDD_SAP_TX_STALL_SSR_THRESHOLD)
661 {
662 // Driver could not recover, issue SSR
663 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
664 "%s: Cannot recover from Data stall Issue SSR",
665 __func__);
Mihir Shetefd62d9d2014-08-06 15:08:21 +0530666 WLANTL_FatalError();
Mihir Shetef3473692014-06-27 15:13:20 +0530667 return;
668 }
669
670 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
671 * every 5sec. The TL debug spits out a lot of information on the
672 * serial console, if it is called every time *hdd_tx_timeout* is
673 * called then we may get a watchdog bite on the Application
674 * processor, so ratelimit the TL debug logs.
675 */
676 if (__ratelimit(&hdd_softap_tx_timeout_rs))
677 {
678 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +0530679 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetef3473692014-06-27 15:13:20 +0530680 }
681
Jeff Johnson295189b2012-06-20 16:38:30 -0700682}
683
684
685/**============================================================================
686 @brief hdd_softap_stats() - Function registered with the Linux OS for
687 device TX/RX statistic
688
689 @param dev : [in] pointer to Libra network device
690
691 @return : pointer to net_device_stats structure
692 ===========================================================================*/
693struct net_device_stats* hdd_softap_stats(struct net_device *dev)
694{
695 hdd_adapter_t* priv = netdev_priv(dev);
696 return &priv->stats;
697}
698
699
700/**============================================================================
701 @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX
702 modules in HDD
703
704 @param pAdapter : [in] pointer to adapter context
705 @return : VOS_STATUS_E_FAILURE if any errors encountered
706 : VOS_STATUS_SUCCESS otherwise
707 ===========================================================================*/
708VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter )
709{
710 VOS_STATUS status = VOS_STATUS_SUCCESS;
711 v_SINT_t i = -1;
712 v_SIZE_t size = 0;
713
714 v_U8_t STAId = 0;
715
716 v_U8_t pACWeights[] = {
717 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
718 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
719 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
720 HDD_SOFTAP_VO_WEIGHT_DEFAULT
721 };
Leo Chang64d68bc2013-06-04 15:40:52 -0700722
Jeff Johnson295189b2012-06-20 16:38:30 -0700723 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530724 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700725
726 vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
727
728 while (++i != NUM_TX_QUEUES)
729 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
730
731 /* Initial HDD buffer control / flow control fields*/
732 vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size);
733
734 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
735 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
736 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
737 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
738
739 spin_lock_init( &pAdapter->staInfo_lock );
740
741 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
742 {
743 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
744 for (i = 0; i < NUM_TX_QUEUES; i ++)
745 {
746 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
747 }
748 }
749
Yue Ma3ede6052013-08-29 00:33:26 -0700750 /* Update the AC weights suitable for SoftAP mode of operation */
751 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
752
Kiet Lambcf38522013-10-26 18:28:27 +0530753 if (VOS_STATUS_SUCCESS != hdd_start_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700754 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530755 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530756 "%s: failed to start Traffic Monito timer ", __func__ );
757 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700758 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700759 return status;
760}
761
762/**============================================================================
763 @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX
764 modules in HDD
765
766 @param pAdapter : [in] pointer to adapter context
767 @return : VOS_STATUS_E_FAILURE if any errors encountered
768 : VOS_STATUS_SUCCESS otherwise
769 ===========================================================================*/
770VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter )
771{
772 VOS_STATUS status = VOS_STATUS_SUCCESS;
Leo Chang64d68bc2013-06-04 15:40:52 -0700773
Kiet Lambcf38522013-10-26 18:28:27 +0530774 if (VOS_STATUS_SUCCESS != hdd_stop_trafficMonitor(pAdapter))
Leo Chang64d68bc2013-06-04 15:40:52 -0700775 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530776 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Kiet Lambcf38522013-10-26 18:28:27 +0530777 "%s: Fail to Stop Traffic Monito timer", __func__ );
778 return VOS_STATUS_E_INVAL;
Leo Chang64d68bc2013-06-04 15:40:52 -0700779 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700780
781 status = hdd_softap_flush_tx_queues(pAdapter);
782
783 return status;
784}
785
786/**============================================================================
787 @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station
788
789 @param pAdapter : [in] pointer to adapter context
790 @param STAId : [in] Station ID to deinit
791 @return : VOS_STATUS_E_FAILURE if any errors encountered
792 : VOS_STATUS_SUCCESS otherwise
793 ===========================================================================*/
794static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId )
795{
Jeff Johnson295189b2012-06-20 16:38:30 -0700796 v_U8_t i = -1;
797
798 hdd_list_node_t *anchor = NULL;
799
800 skb_list_node_t *pktNode = NULL;
801 struct sk_buff *skb = NULL;
802
803 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
804 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530805 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700806 }
807
808 for (i = 0; i < NUM_TX_QUEUES; i ++)
809 {
810 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
811 while (true)
812 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530813 if (VOS_STATUS_E_EMPTY !=
814 hdd_list_remove_front(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
815 &anchor))
Jeff Johnson295189b2012-06-20 16:38:30 -0700816 {
817 //If success then we got a valid packet from some AC
818 pktNode = list_entry(anchor, skb_list_node_t, anchor);
819 skb = pktNode->skb;
820 ++pAdapter->stats.tx_dropped;
821 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
822 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
823 kfree_skb(skb);
824 continue;
825 }
826
827 //current list is empty
828 break;
829 }
830 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock);
831 }
832
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +0530833 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700834}
835
836/**============================================================================
837 @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX
838 modules in HDD
839
840 @param pAdapter : [in] pointer to adapter context
841 @param STAId : [in] Station ID to deinit
842 @param pmacAddrSTA : [in] pointer to the MAC address of the station
843 @return : VOS_STATUS_E_FAILURE if any errors encountered
844 : VOS_STATUS_SUCCESS otherwise
845 ===========================================================================*/
846VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
847{
848 v_U8_t i = 0;
849 spin_lock_bh( &pAdapter->staInfo_lock );
850 if (pAdapter->aStaInfo[STAId].isUsed)
851 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530852 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
853 "%s: Reinit station %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700854 spin_unlock_bh( &pAdapter->staInfo_lock );
855 return VOS_STATUS_E_FAILURE;
856 }
857
858 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
859 for (i = 0; i < NUM_TX_QUEUES; i ++)
860 {
861 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
862 }
863
864 pAdapter->aStaInfo[STAId].isUsed = TRUE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800865 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700866 vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
867
868 spin_unlock_bh( &pAdapter->staInfo_lock );
869 return VOS_STATUS_SUCCESS;
870}
871
872/**============================================================================
873 @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a statioin in Tx/RX
874 modules in HDD
875
876 @param pAdapter : [in] pointer to adapter context
877 @param STAId : [in] Station ID to deinit
878 @return : VOS_STATUS_E_FAILURE if any errors encountered
879 : VOS_STATUS_SUCCESS otherwise
880 ===========================================================================*/
881VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId )
882{
883 VOS_STATUS status = VOS_STATUS_SUCCESS;
884 v_U8_t ac;
885 /**Track whether OS TX queue has been disabled.*/
886 v_BOOL_t txSuspended[NUM_TX_QUEUES];
887 v_U8_t tlAC;
888 hdd_hostapd_state_t *pHostapdState;
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700889 v_U8_t i;
Jeff Johnson295189b2012-06-20 16:38:30 -0700890
891 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
892
893 spin_lock_bh( &pAdapter->staInfo_lock );
894 if (FALSE == pAdapter->aStaInfo[STAId].isUsed)
895 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530896 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700897 "%s: Deinit station not inited %d", __func__, STAId );
Jeff Johnson295189b2012-06-20 16:38:30 -0700898 spin_unlock_bh( &pAdapter->staInfo_lock );
899 return VOS_STATUS_E_FAILURE;
900 }
901
902 status = hdd_softap_flush_tx_queues_sta(pAdapter, STAId);
903
904 pAdapter->aStaInfo[STAId].isUsed = FALSE;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -0800905 pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700906
907 /* if this STA had any of its WMM TX queues suspended, then the
908 associated queue on the network interface was disabled. check
909 to see if that is the case, in which case we need to re-enable
910 the interface queue. but we only do this if the BSS is running
911 since, if the BSS is stopped, all of the interfaces have been
912 stopped and should not be re-enabled */
913
914 if (BSS_START == pHostapdState->bssState)
915 {
916 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
917 {
918 tlAC = hdd_QdiscAcToTlAC[ac];
919 txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC];
920 }
921 }
922 vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
923
Rajesh Chauhan52d885b2013-11-01 10:54:25 -0700924 /* re-init spin lock, since netdev can still open adapter until
925 * driver gets unloaded
926 */
927 for (i = 0; i < NUM_TX_QUEUES; i ++)
928 {
929 hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i],
930 HDD_TX_QUEUE_MAX_LEN);
931 }
932
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 if (BSS_START == pHostapdState->bssState)
934 {
935 for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++)
936 {
937 if (txSuspended[ac])
938 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530939 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700940 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700941 netif_wake_subqueue(pAdapter->dev, ac);
942 }
943 }
944 }
945
946 spin_unlock_bh( &pAdapter->staInfo_lock );
947 return status;
948}
949
950/**============================================================================
951 @brief hdd_softap_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
952 modules in HDD
953
954 @param pAdapter : [in] pointer to adapter context
955 @return : VOS_STATUS_E_FAILURE if any errors encountered
956 : VOS_STATUS_SUCCESS otherwise
957 ===========================================================================*/
958VOS_STATUS hdd_softap_disconnect_tx_rx( hdd_adapter_t *pAdapter )
959{
960 return hdd_softap_flush_tx_queues(pAdapter);
961}
962
963/**============================================================================
964 @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL
965 to indicate that a packet has been transmitted across the bus
966 succesfully. OS packet resources can be released after this cbk.
967
968 @param vosContext : [in] pointer to VOS context
969 @param pVosPacket : [in] pointer to VOS packet (containing skb)
970 @param vosStatusIn : [in] status of the transmission
971
972 @return : VOS_STATUS_E_FAILURE if any errors encountered
973 : VOS_STATUS_SUCCESS otherwise
974 ===========================================================================*/
975VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext,
976 vos_pkt_t *pVosPacket,
977 VOS_STATUS vosStatusIn )
978{
979 VOS_STATUS status = VOS_STATUS_SUCCESS;
980 hdd_adapter_t *pAdapter = NULL;
981 void* pOsPkt = NULL;
982
983 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
984 {
c_hpothu6d1d2a32014-03-18 20:17:03 +0530985 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
986 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700987 return VOS_STATUS_E_FAILURE;
988 }
989
990 //Return the skb to the OS
991 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Rajesh Chauhana0516c62014-01-30 16:11:18 -0800992 if ((!VOS_IS_STATUS_SUCCESS(status)) || (!pOsPkt))
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 {
994 //This is bad but still try to free the VOSS resources if we can
c_hpothu6d1d2a32014-03-18 20:17:03 +0530995 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
996 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700997 vos_pkt_return_packet( pVosPacket );
998 return VOS_STATUS_E_FAILURE;
999 }
1000
1001 //Get the Adapter context.
1002 pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev);
1003 if(pAdapter == NULL)
1004 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301005 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1006 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001007 }
1008 else
1009 {
1010 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1011 }
1012
1013 kfree_skb((struct sk_buff *)pOsPkt);
1014
1015 //Return the VOS packet resources.
1016 status = vos_pkt_return_packet( pVosPacket );
1017 if(!VOS_IS_STATUS_SUCCESS( status ))
1018 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301019 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1020 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001021 }
1022
1023 return status;
1024}
1025
1026
1027/**============================================================================
1028 @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to
1029 fetch a packet for transmission.
1030
1031 @param vosContext : [in] pointer to VOS context
1032 @param staId : [in] Station for which TL is requesting a pkt
1033 @param ac : [in] access category requested by TL
1034 @param pVosPacket : [out] pointer to VOS packet packet pointer
1035 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1036
1037 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1038 : VOS_STATUS_E_FAILURE if any errors encountered
1039 : VOS_STATUS_SUCCESS otherwise
1040 ===========================================================================*/
1041VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1042 v_U8_t *pStaId,
1043 WLANTL_ACEnumType ac,
1044 vos_pkt_t **ppVosPacket,
1045 WLANTL_MetaInfoType *pPktMetaInfo )
1046{
1047 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1048 hdd_adapter_t *pAdapter = NULL;
1049 hdd_list_node_t *anchor = NULL;
1050 skb_list_node_t *pktNode = NULL;
1051 struct sk_buff *skb = NULL;
1052 vos_pkt_t *pVosPacket = NULL;
1053 v_MACADDR_t* pDestMacAddress = NULL;
1054 v_TIME_t timestamp;
1055 v_SIZE_t size = 0;
1056 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1057 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001058 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001059
1060 //Sanity check on inputs
1061 if ( ( NULL == vosContext ) ||
1062 ( NULL == pStaId ) ||
1063 ( NULL == ppVosPacket ) ||
1064 ( NULL == pPktMetaInfo ) )
1065 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301066 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1067 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001068 return VOS_STATUS_E_FAILURE;
1069 }
1070
1071 //Get the HDD context.
1072 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1073 if ( NULL == pHddCtx )
1074 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301075 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1076 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001077 return VOS_STATUS_E_FAILURE;
1078 }
1079
Jeff Johnsonb156c922013-12-05 17:19:46 -08001080 STAId = *pStaId;
1081 if (STAId >= WLAN_MAX_STA_COUNT)
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: Invalid STAId %d passed by TL", __func__, STAId);
1085 return VOS_STATUS_E_FAILURE;
1086 }
1087
1088 pAdapter = pHddCtx->sta_to_adapter[STAId];
1089 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 {
1091 VOS_ASSERT(0);
1092 return VOS_STATUS_E_FAILURE;
1093 }
1094
Jeff Johnsonb156c922013-12-05 17:19:46 -08001095 if (FALSE == pAdapter->aStaInfo[STAId].isUsed )
1096 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301097 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb156c922013-12-05 17:19:46 -08001098 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1099 return VOS_STATUS_E_FAILURE;
1100 }
1101
Leo Chang64d68bc2013-06-04 15:40:52 -07001102 /* Monitor traffic */
1103 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1104 {
1105 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1106 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1107 {
1108 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1109 /* It was IDLE mode,
1110 * this is new state, then switch mode from suspend to resume */
1111 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1112 {
1113 hdd_set_wlan_suspend_mode(0);
1114 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1115 pHddCtx->cfg_ini->trafficIdleTimeout);
1116 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1117 }
1118 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1119 }
1120 }
1121
Jeff Johnson295189b2012-06-20 16:38:30 -07001122 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1123
Jeff Johnson295189b2012-06-20 16:38:30 -07001124 *ppVosPacket = NULL;
1125
1126 //Make sure the AC being asked for is sane
1127 if( ac > WLANTL_MAX_AC || ac < 0)
1128 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301129 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001130 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001131 return VOS_STATUS_E_FAILURE;
1132 }
1133
1134 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1135
c_hpothu6d1d2a32014-03-18 20:17:03 +05301136 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001137 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001138
1139 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1140 //This simplifies the locking and unlocking of Tx queue
1141 status = vos_pkt_wrap_data_packet( &pVosPacket,
1142 VOS_PKT_TYPE_TX_802_3_DATA,
1143 NULL, //OS Pkt is not being passed
1144 hdd_softap_tx_low_resource_cbk,
1145 pAdapter );
1146
1147 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1148 {
1149 //Remember VOS is in a low resource situation
1150 pAdapter->isVosOutOfResource = VOS_TRUE;
1151 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301152 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001153 "%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1155 return VOS_STATUS_E_FAILURE;
1156 }
1157
1158 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC
1159 as the other branch does.
1160 */
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301161 spin_lock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001162 spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
1163 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size);
1164
1165 if (0 == size)
1166 {
1167 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301168 spin_unlock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001169 vos_pkt_return_packet(pVosPacket);
1170 return VOS_STATUS_E_EMPTY;
1171 }
1172
1173 status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1174 spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock);
Katya Nigam69ddd0b2014-07-21 13:29:28 +05301175 spin_unlock_bh( &pAdapter->staInfo_lock );
Jeff Johnson295189b2012-06-20 16:38:30 -07001176
c_hpothu6d1d2a32014-03-18 20:17:03 +05301177 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001178 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001179
1180 if(VOS_STATUS_SUCCESS == status)
1181 {
1182 //If success then we got a valid packet from some AC
1183 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1184 skb = pktNode->skb;
1185 }
1186 else
1187 {
1188 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301189 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 "%s: Error in de-queuing skb from Tx queue status = %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001191 __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001192 vos_pkt_return_packet(pVosPacket);
1193 return VOS_STATUS_E_FAILURE;
1194 }
1195
1196 //Attach skb to VOS packet.
1197 status = vos_pkt_set_os_packet( pVosPacket, skb );
1198 if (status != VOS_STATUS_SUCCESS)
1199 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301200 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001201 "%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001202 vos_pkt_return_packet(pVosPacket);
1203 ++pAdapter->stats.tx_dropped;
1204 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1205 kfree_skb(skb);
1206 return VOS_STATUS_E_FAILURE;
1207 }
1208
1209 //Just being paranoid. To be removed later
1210 if(pVosPacket == NULL)
1211 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301212 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001213 "%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001214 ++pAdapter->stats.tx_dropped;
1215 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1216 kfree_skb(skb);
1217 return VOS_STATUS_E_FAILURE;
1218 }
1219
1220 //Return VOS packet to TL;
1221 *ppVosPacket = pVosPacket;
1222
1223 //Fill out the meta information needed by TL
1224 //FIXME This timestamp is really the time stamp of wrap_data_packet
1225 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1226 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1227 if ( 1 < size )
1228 {
1229 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1230 }
1231 else
1232 {
1233 pPktMetaInfo->bMorePackets = 0;
1234 }
1235
1236 pPktMetaInfo->ucIsEapol = 0;
1237
1238 if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED)
1239 {
1240 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
1241 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301242 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001243 "%s: VOS packet is EAPOL packet", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001244 pPktMetaInfo->ucIsEapol = 1;
1245 }
1246 }
1247
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001248 if (pHddCtx->cfg_ini->gEnableDebugLog)
1249 {
1250 proto_type = vos_pkt_get_proto_type(skb,
1251 pHddCtx->cfg_ini->gEnableDebugLog);
1252 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1253 {
1254 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1255 "SAP TX EAPOL");
1256 }
1257 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1258 {
1259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1260 "SAP TX DHCP");
1261 }
1262 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001263//xg: @@@@: temporarily disble these. will revisit later
Jeff Johnson295189b2012-06-20 16:38:30 -07001264 {
1265 pPktMetaInfo->ucUP = pktNode->userPriority;
1266 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1267 }
1268
1269 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1270 //Extract the destination address from ethernet frame
1271 pDestMacAddress = (v_MACADDR_t*)skb->data;
1272
1273 // we need 802.3 to 802.11 frame translation
1274 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1275 pPktMetaInfo->ucDisableFrmXtl = 0;
1276 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1277 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1278
1279 if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) &&
1280 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1281 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301282 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001283 "%s: TX queue re-enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001284 pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1285 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1286 }
1287
1288 // We're giving the packet to TL so consider it transmitted from
1289 // a statistics perspective. We account for it here instead of
1290 // when the packet is returned for two reasons. First, TL will
1291 // manipulate the skb to the point where the len field is not
1292 // accurate, leading to inaccurate byte counts if we account for
1293 // it later. Second, TL does not provide any feedback as to
1294 // whether or not the packet was successfully sent over the air,
1295 // so the packet counts will be the same regardless of where we
1296 // account for them
1297 pAdapter->stats.tx_bytes += skb->len;
1298 ++pAdapter->stats.tx_packets;
1299 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1300 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301301 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001302
c_hpothu6d1d2a32014-03-18 20:17:03 +05301303 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001304 "%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001305
1306 return status;
1307}
1308
1309
1310/**============================================================================
1311 @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the
1312 case where VOS packets are not available at the time of the call to get
1313 packets. This callback function is invoked by VOS when packets are
1314 available.
1315
1316 @param pVosPacket : [in] pointer to VOS packet
1317 @param userData : [in] opaque user data that was passed initially
1318
1319 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1320 : VOS_STATUS_SUCCESS otherwise
1321 =============================================================================*/
1322VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1323 v_VOID_t *userData )
1324{
1325 VOS_STATUS status;
1326 v_SINT_t i = 0;
1327 v_SIZE_t size = 0;
1328 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1329 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1330
1331 if(pAdapter == NULL)
1332 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301333 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1334 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001335 return VOS_STATUS_E_FAILURE;
1336 }
1337
1338 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1339 //situation. Here we will only signal TL that there is a pending data for a STA.
1340 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1341 vos_pkt_return_packet( pVosPacket );
1342
1343 pAdapter->isVosOutOfResource = VOS_FALSE;
1344
1345 // Indicate to TL that there is pending data if a queue is non empty.
1346 // This Code wasnt included in earlier version which resulted in
1347 // Traffic stalling
1348 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++)
1349 {
1350 if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) ||
1351 (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED))
1352 {
1353 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1354 {
1355 size = 0;
1356 hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size);
1357 if ( size > 0 )
1358 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301359 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1360 STAId,
Jeff Johnson295189b2012-06-20 16:38:30 -07001361 (WLANTL_ACEnumType)i );
1362 if( !VOS_IS_STATUS_SUCCESS( status ) )
1363 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301364 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1365 "%s: Failure in indicating pkt to TL for ac=%d", __func__,i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001366 }
1367 }
1368 }
1369 }
1370 }
1371 return VOS_STATUS_SUCCESS;
1372}
1373
1374
1375/**============================================================================
1376 @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL.
1377 TL will call this to notify the HDD when one or more packets were
1378 received for a registered STA.
1379
1380 @param vosContext : [in] pointer to VOS context
1381 @param pVosPacketChain : [in] pointer to VOS packet chain
1382 @param staId : [in] Station Id (Adress 1 Index)
1383 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s).
1384
1385 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1386 : VOS_STATUS_SUCCESS otherwise
1387 ===========================================================================*/
1388VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext,
1389 vos_pkt_t *pVosPacketChain,
1390 v_U8_t staId,
1391 WLANTL_RxMetaInfoType* pRxMetaInfo )
1392{
1393 hdd_adapter_t *pAdapter = NULL;
1394 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1395 int rxstat;
1396 struct sk_buff *skb = NULL;
1397 vos_pkt_t* pVosPacket;
1398 vos_pkt_t* pNextVosPacket;
1399 hdd_context_t *pHddCtx = NULL;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001400 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001401
1402 //Sanity check on inputs
1403 if ( ( NULL == vosContext ) ||
1404 ( NULL == pVosPacketChain ) ||
1405 ( NULL == pRxMetaInfo ) )
1406 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301407 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1408 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001409 return VOS_STATUS_E_FAILURE;
1410 }
1411
1412 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1413 if ( NULL == pHddCtx )
1414 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301415 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1416 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001417 return VOS_STATUS_E_FAILURE;
1418 }
1419
1420 pAdapter = pHddCtx->sta_to_adapter[staId];
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301421 if( (NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001422 {
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301423 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1424 "%s: invalid adapter or adapter has invalid magic",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001425 VOS_ASSERT(0);
1426 return VOS_STATUS_E_FAILURE;
1427 }
Leo Chang64d68bc2013-06-04 15:40:52 -07001428
1429 /* Monitor traffic */
1430 if ( pHddCtx->cfg_ini->enableTrafficMonitor )
1431 {
1432 pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time();
1433 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1434 {
1435 vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock);
1436 /* It was IDLE mode,
1437 * this is new state, then switch mode from suspend to resume */
1438 if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) )
1439 {
1440 hdd_set_wlan_suspend_mode(0);
1441 vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer,
1442 pHddCtx->cfg_ini->trafficIdleTimeout);
1443 atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1);
1444 }
1445 vos_lock_release(&pHddCtx->traffic_monitor.trafficLock);
1446 }
1447 }
1448
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1450
1451 // walk the chain until all are processed
1452 pVosPacket = pVosPacketChain;
1453 do
1454 {
1455 // get the pointer to the next packet in the chain
1456 // (but don't unlink the packet since we free the entire chain later)
1457 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1458
1459 // both "success" and "empty" are acceptable results
1460 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1461 {
1462 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301463 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1464 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001465 return VOS_STATUS_E_FAILURE;
1466 }
1467
1468 // Extract the OS packet (skb).
1469 // Tell VOS to detach the OS packet from the VOS packet
1470 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1471 if(!VOS_IS_STATUS_SUCCESS( status ))
1472 {
1473 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301474 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1475 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001476 return VOS_STATUS_E_FAILURE;
1477 }
1478
1479 //hdd_softap_dump_sk_buff(skb);
1480
1481 skb->dev = pAdapter->dev;
1482
1483 if(skb->dev == NULL) {
1484
c_hpothu6d1d2a32014-03-18 20:17:03 +05301485 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_FATAL,
1486 "ERROR!!Invalid netdevice");
Jeff Johnson295189b2012-06-20 16:38:30 -07001487 return VOS_STATUS_E_FAILURE;
1488 }
1489 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1490 ++pAdapter->stats.rx_packets;
1491 pAdapter->stats.rx_bytes += skb->len;
1492
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001493 if (pHddCtx->cfg_ini->gEnableDebugLog)
1494 {
1495 proto_type = vos_pkt_get_proto_type(skb,
1496 pHddCtx->cfg_ini->gEnableDebugLog);
1497 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1498 {
1499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1500 "SAP RX EAPOL");
1501 }
1502 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1503 {
1504 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1505 "SAP RX DHCP");
1506 }
1507 }
1508
Jeff Johnson295189b2012-06-20 16:38:30 -07001509 if (WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId)
1510 {
1511 //MC/BC packets. Duplicate a copy of packet
1512 struct sk_buff *pSkbCopy;
1513 hdd_ap_ctx_t *pHddApCtx;
1514
1515 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
1516 if (!(pHddApCtx->apDisableIntraBssFwd))
1517 {
1518 pSkbCopy = skb_copy(skb, GFP_ATOMIC);
1519 if (pSkbCopy)
1520 {
1521 hdd_softap_sta_2_sta_xmit(pSkbCopy, pSkbCopy->dev,
1522 pHddApCtx->uBCStaId, (pRxMetaInfo->ucUP));
1523 }
1524 }
1525 else
1526 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301527 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001528 "%s: skb allocation fails", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001529 }
1530
1531
1532 } //(WLAN_RX_BCMC_STA_ID == staId)
1533
1534 if ((WLAN_RX_BCMC_STA_ID == pRxMetaInfo->ucDesSTAId) ||
1535 (WLAN_RX_SAP_SELF_STA_ID == pRxMetaInfo->ucDesSTAId))
1536 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301537 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001538 "%s: send one packet to kernel", __func__);
Dino Mycled9b7cc12014-09-04 18:43:07 +05301539 if ( pHddCtx->cfg_ini->enableDhcpDebug )
1540 {
1541 hdd_dump_dhcp_pkt(skb, RX_PATH);
1542 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001543
1544 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001545 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001546#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001547#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001548 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001549#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001550#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 rxstat = netif_rx_ni(skb);
1552 if (NET_RX_SUCCESS == rxstat)
1553 {
1554 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001555 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001556 }
1557 else
1558 {
1559 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1560 }
1561 }
1562 else if ((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->apDisableIntraBssFwd)
1563 {
1564 kfree_skb(skb);
1565 }
1566 else
1567 {
1568 //loopback traffic
1569 status = hdd_softap_sta_2_sta_xmit(skb, skb->dev,
1570 pRxMetaInfo->ucDesSTAId, (pRxMetaInfo->ucUP));
1571 }
1572
1573 // now process the next packet in the chain
1574 pVosPacket = pNextVosPacket;
1575
1576 } while (pVosPacket);
1577
1578 //Return the entire VOS packet chain to the resource pool
1579 status = vos_pkt_return_packet( pVosPacketChain );
1580 if(!VOS_IS_STATUS_SUCCESS( status ))
1581 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301582 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1583 "%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001584 }
1585
1586 pAdapter->dev->last_rx = jiffies;
1587
1588 return status;
1589}
1590
1591VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId )
1592{
1593 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301594 hdd_context_t *pHddCtx;
1595 if (NULL == pAdapter)
1596 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301597 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301598 "%s: pAdapter is NULL", __func__);
1599 return VOS_STATUS_E_INVAL;
1600 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001601
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301602 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1603 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301604 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301605 "%s: Invalid pAdapter magic", __func__);
1606 return VOS_STATUS_E_INVAL;
1607 }
1608
1609 pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
c_hpothu6d1d2a32014-03-18 20:17:03 +05301610 //Clear station in TL and then update HDD data structures. This helps
Jeff Johnson295189b2012-06-20 16:38:30 -07001611 //to block RX frames from other station to this station.
Gopichand Nakkala3bd53fa2013-05-22 20:04:18 +05301612 vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001613 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1614 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301615 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001616 "WLANTL_ClearSTAClient() failed to for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001617 "Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 staId, vosStatus, vosStatus );
1619 }
1620
1621 vosStatus = hdd_softap_deinit_tx_rx_sta ( pAdapter, staId );
1622 if( VOS_STATUS_E_FAILURE == vosStatus )
1623 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301624 VOS_TRACE ( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001625 "hdd_softap_deinit_tx_rx_sta() failed for staID %d. "
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001626 "Status = %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 staId, vosStatus, vosStatus );
1628 return( vosStatus );
1629 }
1630
1631 pHddCtx->sta_to_adapter[staId] = NULL;
1632
1633 return( vosStatus );
1634}
1635
1636VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter,
1637 v_BOOL_t fAuthRequired,
1638 v_BOOL_t fPrivacyBit,
1639 v_U8_t staId,
1640 v_U8_t ucastSig,
1641 v_U8_t bcastSig,
1642 v_MACADDR_t *pPeerMacAddress,
1643 v_BOOL_t fWmmEnabled )
1644{
1645 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
Prathyushaf5442802012-12-12 13:58:11 -08001646 WLAN_STADescType staDesc = {0};
Jeff Johnson295189b2012-06-20 16:38:30 -07001647 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
1648 hdd_adapter_t *pmonAdapter = NULL;
1649
1650 //eCsrEncryptionType connectedCipherAlgo;
1651 //v_BOOL_t fConnected;
1652
1653 /*
1654 * Clean up old entry if it is not cleaned up properly
1655 */
1656 if ( pAdapter->aStaInfo[staId].isUsed )
1657 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301658 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 "clean up old entry for STA %d", staId);
1660 hdd_softap_DeregisterSTA( pAdapter, staId );
1661 }
1662
1663 // Get the Station ID from the one saved during the assocation.
1664
1665 staDesc.ucSTAId = staId;
1666
1667
1668 /*Save the pAdapter Pointer for this staId*/
1669 pHddCtx->sta_to_adapter[staId] = pAdapter;
1670
1671 staDesc.wSTAType = WLAN_STA_SOFTAP;
1672
1673 vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) );
1674 vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 );
1675 vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
1676
c_hpothu6d1d2a32014-03-18 20:17:03 +05301677 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001678 "register station");
c_hpothu6d1d2a32014-03-18 20:17:03 +05301679 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001680 "station mac " MAC_ADDRESS_STR,
1681 MAC_ADDR_ARRAY(staDesc.vSTAMACAddress.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301682 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001683 "BSSIDforIBSS " MAC_ADDRESS_STR,
1684 MAC_ADDR_ARRAY(staDesc.vBSSIDforIBSS.bytes));
c_hpothu6d1d2a32014-03-18 20:17:03 +05301685 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08001686 "SOFTAP SELFMAC " MAC_ADDRESS_STR,
1687 MAC_ADDR_ARRAY(staDesc.vSelfMACAddress.bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07001688
1689 vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress);
1690
Jeff Johnson295189b2012-06-20 16:38:30 -07001691 staDesc.ucQosEnabled = fWmmEnabled;
c_hpothu6d1d2a32014-03-18 20:17:03 +05301692 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001693 "HDD SOFTAP register TL QoS_enabled=%d",
1694 staDesc.ucQosEnabled );
1695
1696 staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ;
1697
1698
Jeff Johnson295189b2012-06-20 16:38:30 -07001699 // For PRIMA UMA frame translation is not enable yet.
1700 staDesc.ucSwFrameTXXlation = 1;
1701 staDesc.ucSwFrameRXXlation = 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07001702 staDesc.ucAddRmvLLC = 1;
1703
1704 // Initialize signatures and state
1705 staDesc.ucUcastSig = ucastSig;
1706 staDesc.ucBcastSig = bcastSig;
1707 staDesc.ucInitState = fAuthRequired ?
1708 WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED;
1709
Prathyushaf5442802012-12-12 13:58:11 -08001710 staDesc.ucIsReplayCheckValid = VOS_FALSE;
1711
Jeff Johnson295189b2012-06-20 16:38:30 -07001712 // Register the Station with TL...
c_hpothu6d1d2a32014-03-18 20:17:03 +05301713 vosStatus = WLANTL_RegisterSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1714 hdd_softap_rx_packet_cbk,
1715 hdd_softap_tx_complete_cbk,
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 );
1717
1718 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1719 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301720 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07001721 "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 vosStatus, vosStatus );
1723 return vosStatus;
1724 }
1725
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001726 //Timer value should be in milliseconds
1727 if ( pHddCtx->cfg_ini->dynSplitscan &&
1728 ( VOS_TIMER_STATE_RUNNING !=
1729 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
1730 {
1731 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1732 pHddCtx->cfg_ini->trafficMntrTmrForSplitScan);
1733 }
1734
Jeff Johnson295189b2012-06-20 16:38:30 -07001735 // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver,
1736 // then go to 'authenticated'. For all other authentication types (those that do
1737 // not require upper layer authentication) we can put TL directly into 'authenticated'
1738 // state.
1739
1740 //VOS_ASSERT( fConnected );
1741 pAdapter->aStaInfo[staId].ucSTAId = staId;
1742 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
1743
1744 if ( !fAuthRequired )
1745 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301746 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
1747 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
1748 pAdapter->aStaInfo[staId].ucSTAId );
Jeff Johnson295189b2012-06-20 16:38:30 -07001749
1750 // Connections that do not need Upper layer auth, transition TL directly
1751 // to 'Authenticated' state.
1752 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1753 WLANTL_STA_AUTHENTICATED );
1754
1755 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1756 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE;
1757 }
1758 else
1759 {
1760
c_hpothu6d1d2a32014-03-18 20:17:03 +05301761 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001762 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId );
1763
1764 vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId,
1765 WLANTL_STA_CONNECTED );
1766 pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED;
1767
1768 pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE;
1769
1770 }
1771 pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx);
1772 if(pmonAdapter)
1773 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301774 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH,
1775 "Turn on Monitor the carrier");
Jeff Johnson295189b2012-06-20 16:38:30 -07001776 netif_carrier_on(pmonAdapter->dev);
1777 //Enable Tx queue
1778 netif_tx_start_all_queues(pmonAdapter->dev);
1779 }
1780 netif_carrier_on(pAdapter->dev);
1781 //Enable Tx queue
1782 netif_tx_start_all_queues(pAdapter->dev);
1783
1784 return( vosStatus );
1785}
1786
1787VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit)
1788{
1789 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1790 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1791 v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
1792
1793
1794 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
1795 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
1796 vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0);
1797
1798 return vosStatus;
1799}
1800
1801VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter)
1802{
1803 return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
1804}
1805
1806VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter)
1807{
Wilson Yangf80a0542013-10-07 13:02:37 -07001808 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001809 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
1810 v_U8_t staId = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07001811 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1812
1813 /*bss deregister is not allowed during wlan driver loading or unloading*/
Mihir Shete18156292014-03-11 15:38:30 +05301814 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Wilson Yangf80a0542013-10-07 13:02:37 -07001815 {
1816 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1817 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
1818 return VOS_STATUS_E_PERM;
1819 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001820
1821 vosStatus = hdd_softap_Deregister_BC_STA( pAdapter);
1822
Jeff Johnson43971f52012-07-17 12:26:56 -07001823 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07001824 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301825 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001826 "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001827 }
1828
1829 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1830 {
1831 if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered
Jeff Johnson295189b2012-06-20 16:38:30 -07001832 {
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301833 vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId);
1834 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1835 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301836 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001837 "%s: Failed to deregister sta Id %d", __func__, staId);
Hanumantha Reddy Pothulac7100902013-12-28 18:17:36 +05301838 }
1839 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001840 }
1841
1842 return vosStatus;
1843}
1844
1845VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state)
1846{
1847 v_U8_t ucSTAId = WLAN_MAX_STA_COUNT;
1848 VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS;
1849 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001850
c_hpothu6d1d2a32014-03-18 20:17:03 +05301851 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001852 "%s: enter", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001853
Jeff Johnson43971f52012-07-17 12:26:56 -07001854 if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId))
Jeff Johnson295189b2012-06-20 16:38:30 -07001855 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301856 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001857 "%s: Failed to find right station", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001858 return VOS_STATUS_E_FAILURE;
1859 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001860
1861 if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress))
1862 {
c_hpothu6d1d2a32014-03-18 20:17:03 +05301863 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001864 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001865 return VOS_STATUS_E_FAILURE;
1866 }
1867
1868 vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state );
c_hpothu6d1d2a32014-03-18 20:17:03 +05301869 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001870 "%s: change station to state %d succeed", __func__, state);
Jeff Johnson295189b2012-06-20 16:38:30 -07001871
Jeff Johnson43971f52012-07-17 12:26:56 -07001872 if (VOS_STATUS_SUCCESS == vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07001873 {
1874 pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED;
1875 }
1876
c_hpothu6d1d2a32014-03-18 20:17:03 +05301877 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001878 "%s exit",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001879
1880 return vosStatus;
1881}
1882
1883
1884VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1885{
1886 v_U8_t i;
1887
1888 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1889 {
1890 if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) &&
1891 pAdapter->aStaInfo[i].isUsed)
1892 {
1893 *staId = i;
1894 return VOS_STATUS_SUCCESS;
1895 }
1896 }
1897
1898 return VOS_STATUS_E_FAILURE;
1899}
1900
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301901VOS_STATUS hdd_softap_GetConnectedStaId(hdd_adapter_t *pAdapter, v_U8_t *staId)
1902{
1903 v_U8_t i;
1904
1905 for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
1906 {
Kiet Lam61589852013-09-19 17:10:58 +05301907 if (pAdapter->aStaInfo[i].isUsed &&
1908 (!vos_is_macaddr_broadcast(&pAdapter->aStaInfo[i].macAddrSTA)))
Madan Mohan Koyyalamudie68989b2013-09-10 01:15:19 +05301909 {
1910 *staId = i;
1911 return VOS_STATUS_SUCCESS;
1912 }
1913 }
1914
1915 return VOS_STATUS_E_FAILURE;
1916}