blob: 7f851de67f816a3b883f78f6e5a4da53ee42c3f6 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
c_hpothu32490782014-03-14 19:14:34 +05302 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
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.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
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.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**===========================================================================
29
30 \file wlan_hdd_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 ==========================================================================*/
38
39/*---------------------------------------------------------------------------
40 Include files
41 -------------------------------------------------------------------------*/
42#include <wlan_hdd_tx_rx.h>
43#include <wlan_hdd_softap_tx_rx.h>
44#include <wlan_hdd_dp_utils.h>
45#include <wlan_qct_tl.h>
46#include <linux/netdevice.h>
47#include <linux/skbuff.h>
48#include <linux/etherdevice.h>
Mihir Shetec8fe71b2014-06-16 15:32:59 +053049#include <linux/ratelimit.h>
Mihir Shetef3473692014-06-27 15:13:20 +053050#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
51#include <soc/qcom/subsystem_restart.h>
52#else
53#include <mach/subsystem_restart.h>
54#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070055
Jeff Johnson295189b2012-06-20 16:38:30 -070056#include <wlan_hdd_p2p.h>
57#include <linux/wireless.h>
58#include <net/cfg80211.h>
59#include <net/ieee80211_radiotap.h>
60#include "sapApi.h"
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053061#include <vos_sched.h>
Chilam NG571c65a2013-01-19 12:27:36 +053062#ifdef FEATURE_WLAN_TDLS
63#include "wlan_hdd_tdls.h"
64#endif
65
Mukul Sharma84f27252014-07-14 18:11:42 +053066#ifdef DEBUG_ROAM_DELAY
67#include "vos_utils.h"
68#endif
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053069#include "sapInternal.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070070/*---------------------------------------------------------------------------
71 Preprocessor definitions and constants
72 -------------------------------------------------------------------------*/
73
74const v_U8_t hddWmmAcToHighestUp[] = {
75 SME_QOS_WMM_UP_RESV,
76 SME_QOS_WMM_UP_EE,
77 SME_QOS_WMM_UP_VI,
78 SME_QOS_WMM_UP_NC
79};
80
81//Mapping Linux AC interpretation to TL AC.
82const v_U8_t hdd_QdiscAcToTlAC[] = {
83 WLANTL_AC_VO,
84 WLANTL_AC_VI,
85 WLANTL_AC_BE,
86 WLANTL_AC_BK,
87};
88
Mihir Shetec8fe71b2014-06-16 15:32:59 +053089#define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
90#define HDD_TX_TIMEOUT_RATELIMIT_BURST 1
Mihir Shetef3473692014-06-27 15:13:20 +053091#define HDD_TX_STALL_SSR_THRESHOLD 5
Mihir Shete327c2ab2014-11-13 15:17:02 +053092#define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
Mihir Shetec8fe71b2014-06-16 15:32:59 +053093
94static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs, \
95 HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
96 HDD_TX_TIMEOUT_RATELIMIT_BURST);
97
Jeff Johnson295189b2012-06-20 16:38:30 -070098static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070099
100/*---------------------------------------------------------------------------
101 Type declarations
102 -------------------------------------------------------------------------*/
103
104/*---------------------------------------------------------------------------
105 Function definitions and documenation
106 -------------------------------------------------------------------------*/
107
108#ifdef DATA_PATH_UNIT_TEST
109//Utility function to dump an sk_buff
110static void dump_sk_buff(struct sk_buff * skb)
111{
c_hpothu32490782014-03-14 19:14:34 +0530112 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
113 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
114 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
115 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
116 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
117 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
118 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700119
c_hpothu32490782014-03-14 19:14:34 +0530120 VOS_TRACE( VOS_MODULE_ID_HDD_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 -0700121 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
122 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu32490782014-03-14 19:14:34 +0530123 VOS_TRACE( VOS_MODULE_ID_HDD_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 -0700124 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
125 skb->data[13], skb->data[14], skb->data[15]);
126}
127
128//Function for Unit Test only
129static void transport_thread(hdd_adapter_t *pAdapter)
130{
131 v_U8_t staId;
132 WLANTL_ACEnumType ac = WLANTL_AC_BE;
133 vos_pkt_t *pVosPacket = NULL ;
134 vos_pkt_t dummyPacket;
135 WLANTL_MetaInfoType pktMetaInfo;
136 WLANTL_RxMetaInfoType pktRxMetaInfo;
137 VOS_STATUS status = VOS_STATUS_E_FAILURE;
138
c_hpothub8245442013-11-20 23:41:09 +0530139 if (NULL == pAdapter)
140 {
c_hpothu32490782014-03-14 19:14:34 +0530141 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530142 FL("pAdapter is NULL"));
143 VOS_ASSERT(0);
144 return;
145 }
146
Jeff Johnson295189b2012-06-20 16:38:30 -0700147 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
148 &staId,
149 &ac,
150 &pVosPacket,
151 &pktMetaInfo );
152 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530153 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
154 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700155 else
c_hpothu32490782014-03-14 19:14:34 +0530156 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
157 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700158
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700159 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700160 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530161 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
162 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700163 else
c_hpothu32490782014-03-14 19:14:34 +0530164 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
165 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700166
167 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
168 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530169 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
170 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700171 else
c_hpothu32490782014-03-14 19:14:34 +0530172 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
173 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700174
175 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
176 &dummyPacket,
177 staId,
178 &pktRxMetaInfo);
179 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530180 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
181 "%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700182 else
c_hpothu32490782014-03-14 19:14:34 +0530183 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
184 "%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700185
186}
187#endif
188
189
190/**============================================================================
191 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
192
193 @param pAdapter : [in] pointer to adapter context
194 @return : VOS_STATUS_E_FAILURE if any errors encountered
195 : VOS_STATUS_SUCCESS otherwise
196 ===========================================================================*/
197static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
198{
199 VOS_STATUS status = VOS_STATUS_SUCCESS;
200 v_SINT_t i = -1;
201 hdd_list_node_t *anchor = NULL;
202 skb_list_node_t *pktNode = NULL;
203 struct sk_buff *skb = NULL;
204
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530205 pAdapter->isVosLowResource = VOS_FALSE;
206
Jeff Johnson295189b2012-06-20 16:38:30 -0700207 while (++i != NUM_TX_QUEUES)
208 {
209 //Free up any packets in the Tx queue
210 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
211 while (true)
212 {
213 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
214 if(VOS_STATUS_E_EMPTY != status)
215 {
216 pktNode = list_entry(anchor, skb_list_node_t, anchor);
217 skb = pktNode->skb;
218 //TODO
219 //++pAdapter->stats.tx_dropped;
220 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
221 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
222 kfree_skb(skb);
223 continue;
224 }
225 break;
226 }
227 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
228 // backpressure is no longer in effect
229 pAdapter->isTxSuspended[i] = VOS_FALSE;
230 }
231
232 return status;
233}
234
Ravi Joshif9520d62013-10-18 04:11:46 -0700235/**============================================================================
236 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
237 in IBSS mode
238
239 @param pAdapter : [in] pointer to adapter context
240 : [in] Staion Id
241 @return : VOS_STATUS_E_FAILURE if any errors encountered
242 : VOS_STATUS_SUCCESS otherwise
243 ===========================================================================*/
244void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
245{
246 v_U8_t i;
Ravi Joshi41914632013-10-21 23:02:21 -0700247 v_SIZE_t size = 0;
Ravi Joshif9520d62013-10-18 04:11:46 -0700248 v_U8_t skbStaIdx;
Ravi Joshi41914632013-10-21 23:02:21 -0700249 skb_list_node_t *pktNode = NULL;
250 hdd_list_node_t *tmp = NULL, *next = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700251 struct netdev_queue *txq;
Ravi Joshi41914632013-10-21 23:02:21 -0700252 struct sk_buff *skb = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700253
c_hpothub8245442013-11-20 23:41:09 +0530254 if (NULL == pAdapter)
255 {
c_hpothu32490782014-03-14 19:14:34 +0530256 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530257 FL("pAdapter is NULL %u"), STAId);
258 VOS_ASSERT(0);
259 return;
260 }
261
Ravi Joshif9520d62013-10-18 04:11:46 -0700262 for (i = 0; i < NUM_TX_QUEUES; i++)
263 {
264 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
265
266 if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) )
267 {
268 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
269 continue;
270 }
271
272 /* Iterate through the queue and identify the data for STAId */
Ravi Joshi41914632013-10-21 23:02:21 -0700273 list_for_each_safe(tmp, next, &pAdapter->wmm_tx_queue[i].anchor)
Ravi Joshif9520d62013-10-18 04:11:46 -0700274 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700275 pktNode = list_entry(tmp, skb_list_node_t, anchor);
276 if (pktNode != NULL)
277 {
278 skb = pktNode->skb;
279
280 /* Get the STAId from data */
281 skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
282 if (skbStaIdx == STAId)
283 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700284 /* Data for STAId is freed along with the queue node */
Ravi Joshif9520d62013-10-18 04:11:46 -0700285 list_del(tmp);
Mihir Shete31e1e392014-03-24 17:09:09 +0530286 kfree_skb(skb);
Ravi Joshif9520d62013-10-18 04:11:46 -0700287
288 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
289 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
290 pAdapter->wmm_tx_queue[i].count--;
291 }
292 }
293 }
294
295 /* Restart the queue only-if suspend and the queue was flushed */
Ravi Joshi41914632013-10-21 23:02:21 -0700296 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
Ravi Joshif9520d62013-10-18 04:11:46 -0700297 txq = netdev_get_tx_queue(pAdapter->dev, i);
Ravi Joshi41914632013-10-21 23:02:21 -0700298
299 if (VOS_TRUE == pAdapter->isTxSuspended[i] &&
300 size <= HDD_TX_QUEUE_LOW_WATER_MARK &&
301 netif_tx_queue_stopped(txq) )
Ravi Joshif9520d62013-10-18 04:11:46 -0700302 {
303 netif_tx_start_queue(txq);
Ravi Joshi41914632013-10-21 23:02:21 -0700304 pAdapter->isTxSuspended[i] = VOS_FALSE;
305 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressured;
306 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressuredAC[i];
Ravi Joshif9520d62013-10-18 04:11:46 -0700307 }
308
309 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
310 }
311}
312
Jeff Johnson295189b2012-06-20 16:38:30 -0700313static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
314{
315 skb_list_node_t *pktNode = NULL;
316 struct sk_buff *skb = NULL;
317 v_SIZE_t size = 0;
318 WLANTL_ACEnumType ac = 0;
319 VOS_STATUS status = VOS_STATUS_E_FAILURE;
320 hdd_list_node_t *anchor = NULL;
321
c_hpothu77731d42014-01-23 13:59:03 +0530322 if (NULL == pAdapter)
323 {
324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
325 FL("pAdapter is NULL"));
326 VOS_ASSERT(0);
327 return NULL;
328 }
329
Jeff Johnson295189b2012-06-20 16:38:30 -0700330 // do we have any packets pending in this AC?
331 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
332 if( size == 0 )
333 {
c_hpothu32490782014-03-14 19:14:34 +0530334 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700335 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700336 return NULL;
337 }
338
339 //Remove the packet from the queue
340 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
341 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
342 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
343
344 if(VOS_STATUS_SUCCESS == status)
345 {
346 //If success then we got a valid packet from some AC
347 pktNode = list_entry(anchor, skb_list_node_t, anchor);
348 skb = pktNode->skb;
349 }
350 else
351 {
c_hpothu32490782014-03-14 19:14:34 +0530352 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700353 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700354 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700355
356 return NULL;
357 }
358
359 // if we are in a backpressure situation see if we can turn the hose back on
360 if ( (pAdapter->isTxSuspended[ac]) &&
361 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
362 {
c_hpothu32490782014-03-14 19:14:34 +0530363 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700364 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700365 pAdapter->isTxSuspended[ac] = VOS_FALSE;
366 /* Enable Queues which we have disabled earlier */
367 netif_tx_start_all_queues( pAdapter->dev );
368 }
369
370 return skb;
371}
372
373void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
374{
375 hdd_cfg80211_state_t *cfgState;
376 struct sk_buff* skb;
377 hdd_adapter_t* pMonAdapter = NULL;
378 struct ieee80211_hdr *hdr;
379
Mukul Sharma23a92232014-04-07 18:04:00 +0530380 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700381 {
c_hpothu32490782014-03-14 19:14:34 +0530382 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530383 FL("pAdapter is NULL"));
384 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 return;
386 }
387
388 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530389 if (pMonAdapter == NULL)
390 {
391 hddLog(VOS_TRACE_LEVEL_ERROR,
392 "%s: pMonAdapter is NULL", __func__);
393 return;
394 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700395 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
396
397 if( NULL != cfgState->buf )
398 {
c_hpothu32490782014-03-14 19:14:34 +0530399 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700400 "%s: Already one MGMT packet Tx going on", __func__);
401 return;
402 }
403
404 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
405
406 if (NULL == skb)
407 {
c_hpothu32490782014-03-14 19:14:34 +0530408 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700409 "%s: No Packet Pending", __func__);
410 return;
411 }
412
413 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
414 if( cfgState->buf == NULL )
415 {
c_hpothu32490782014-03-14 19:14:34 +0530416 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700417 "%s: Failed to Allocate memory", __func__);
418 goto fail;
419 }
420
421 cfgState->len = skb->len;
422
423 vos_mem_copy( cfgState->buf, skb->data, skb->len);
424
425 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800426 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700427
428 hdr = (struct ieee80211_hdr *)skb->data;
429 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
430 == HDD_FRAME_TYPE_MGMT )
431 {
432 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
433 == HDD_FRAME_SUBTYPE_DEAUTH )
434 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530435 struct tagCsrDelStaParams delStaParams;
436
437 WLANSAP_PopulateDelStaParams(hdr->addr1, eCsrForcedDeauthSta,
438 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
439
440 hdd_softap_sta_deauth(pAdapter, &delStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -0700441 goto mgmt_handled;
442 }
443 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
444 == HDD_FRAME_SUBTYPE_DISASSOC )
445 {
446 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
447 goto mgmt_handled;
448 }
449 }
c_hpothu32490782014-03-14 19:14:34 +0530450 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700451 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
452
Jeff Johnson43971f52012-07-17 12:26:56 -0700453 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700455 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 {
c_hpothu32490782014-03-14 19:14:34 +0530457 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700458 "%s: WLANSAP_SendAction returned fail", __func__);
459 hdd_sendActionCnf( pAdapter, FALSE );
460 }
461 return;
462
463mgmt_handled:
464 hdd_sendActionCnf( pAdapter, TRUE );
465 return;
466fail:
467 kfree_skb(pAdapter->skb_to_tx);
468 pAdapter->skb_to_tx = NULL;
469 return;
470}
471
472void hdd_mon_tx_work_queue(struct work_struct *work)
473{
474 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
475 hdd_mon_tx_mgmt_pkt(pAdapter);
476}
477
478int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
479{
480 v_U16_t rt_hdr_len;
481 struct ieee80211_hdr *hdr;
482 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
483 struct ieee80211_radiotap_header *rtap_hdr =
484 (struct ieee80211_radiotap_header *)skb->data;
485
486 /*Supplicant sends the EAPOL packet on monitor interface*/
487 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
488 if(pPgBkAdapter == NULL)
489 {
c_hpothu32490782014-03-14 19:14:34 +0530490 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700491 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
492 __func__);
493 goto fail; /* too short to be possibly valid */
494 }
495
496 /* check if toal skb length is greater then radio tab header length of not */
497 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
498 goto fail; /* too short to be possibly valid */
499
500 /* check if radio tap header version is correct or not */
501 if (unlikely(rtap_hdr->it_version))
502 goto fail; /* only version 0 is supported */
503
504 /*Strip off the radio tap header*/
505 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
506
507 /* check if skb length if greator then total radio tap header length ot not*/
508 if (unlikely(skb->len < rt_hdr_len))
509 goto fail;
510
511 /* Update the trans_start for this netdev */
512 dev->trans_start = jiffies;
513 /*
514 * fix up the pointers accounting for the radiotap
515 * header still being in there.
516 */
517 skb_set_mac_header(skb, rt_hdr_len);
518 skb_set_network_header(skb, rt_hdr_len);
519 skb_set_transport_header(skb, rt_hdr_len);
520
521 /* Pull rtap header out of the skb */
522 skb_pull(skb, rt_hdr_len);
523
524 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
525 * radio tap header and 802.11 header starts
526 */
527 hdr = (struct ieee80211_hdr *)skb->data;
528
529 /* Send data frames through the normal Data path. In this path we will
530 * conver rcvd 802.11 packet to 802.3 packet */
531 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
532 {
533 v_U8_t da[6];
534 v_U8_t sa[6];
535
536 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
537 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
538
539 /* Pull 802.11 MAC header */
540 skb_pull(skb, HDD_80211_HEADER_LEN);
541
542 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
543 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
544 {
545 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
546 }
547
548 /* Pull LLC header */
549 skb_pull(skb, HDD_LLC_HDR_LEN);
550
551 /* Create space for Ethernet header */
552 skb_push(skb, HDD_MAC_HDR_SIZE*2);
553 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
554 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
555
556 /* Only EAPOL Data packets are allowed through monitor interface */
557 if (vos_be16_to_cpu(
558 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
559 != HDD_ETHERTYPE_802_1_X)
560 {
c_hpothu32490782014-03-14 19:14:34 +0530561 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700562 "%s: Not a Eapol packet. Drop this frame", __func__);
563 //If not EAPOL frames, drop them.
564 kfree_skb(skb);
565 return NETDEV_TX_OK;
566 }
567
568 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
569
570 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
571 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
572 }
573 else
574 {
575 VOS_STATUS status;
576 WLANTL_ACEnumType ac = 0;
577 skb_list_node_t *pktNode = NULL;
578 v_SIZE_t pktListSize = 0;
579
580 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
581 //If we have already reached the max queue size, disable the TX queue
582 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
583 {
584 /* We want to process one packet at a time, so lets disable all TX queues
585 * and re-enable the queues once we get TX feedback for this packet */
586 netif_tx_stop_all_queues(pAdapter->dev);
587 pAdapter->isTxSuspended[ac] = VOS_TRUE;
588 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
589 return NETDEV_TX_BUSY;
590 }
591 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
592
593 //Use the skb->cb field to hold the list node information
594 pktNode = (skb_list_node_t *)&skb->cb;
595
596 //Stick the OS packet inside this node.
597 pktNode->skb = skb;
598
599 INIT_LIST_HEAD(&pktNode->anchor);
600
601 //Insert the OS packet into the appropriate AC queue
602 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
603 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
604 &pktNode->anchor, &pktListSize );
605 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
606
607 if ( !VOS_IS_STATUS_SUCCESS( status ) )
608 {
c_hpothu32490782014-03-14 19:14:34 +0530609 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700610 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 kfree_skb(skb);
612 return NETDEV_TX_OK;
613 }
614
615 if ( pktListSize == 1 )
616 {
617 /* In this context we cannot acquire any mutex etc. And to transmit
618 * this packet we need to call SME API. So to take care of this we will
619 * schedule a workqueue
620 */
621 schedule_work(&pPgBkAdapter->monTxWorkQueue);
622 }
623 return NETDEV_TX_OK;
624 }
625
626fail:
c_hpothu32490782014-03-14 19:14:34 +0530627 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700628 "%s: Packet Rcvd at Monitor interface is not proper,"
629 " Dropping the packet",
630 __func__);
631 kfree_skb(skb);
632 return NETDEV_TX_OK;
633}
Dino Mycled9b7cc12014-09-04 18:43:07 +0530634
635/**============================================================================
636 @brief hdd_dhcp_pkt_info() -
637 Function to log DHCP pkt info
638
639 @param skb : [in] pointer to OS packet (sk_buff)
640 @return : None
641 ===========================================================================*/
642
643void hdd_dhcp_pkt_info(struct sk_buff *skb)
644{
645 /* port no 67 (0x43) or 68 (0x44) */
646
647 if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_REQUEST_MSG)
648 hddLog(VOS_TRACE_LEVEL_INFO, FL("Request"));
649 else if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_RESPONSE_MSG)
650 hddLog(VOS_TRACE_LEVEL_INFO, FL("Response"));
651 else
652 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP invalid"));
653
654 hddLog(VOS_TRACE_LEVEL_INFO,
655 FL("DHCP Dest Addr: %pM Src Addr %pM "
656 " source port : %d, dest port : %d"),
657 skb->data, (skb->data + 6),
658 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))),
659 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))));
660
661 if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
662 (skb->data[DHCP_OPTION53_LENGTH_OFFSET] == DHCP_OPTION53_LENGTH)) {
663
664 switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
665 case DHCPDISCOVER:
666 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP DISCOVER"));
667 break;
668 case DHCPREQUEST:
669 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP REQUEST"));
670 break;
671 case DHCPOFFER:
672 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP OFFER"));
673 break;
674 case DHCPACK:
675 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP ACK"));
676 break;
677 case DHCPNAK:
678 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP NACK"));
679 break;
680 case DHCPRELEASE:
681 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP RELEASE"));
682 break;
683 case DHCPINFORM:
684 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP INFORM"));
685 break;
686
687 default:
688 hddLog(VOS_TRACE_LEVEL_INFO,
689 "%s: DHCP Not Defined OPTION53 : %d", __func__,
690 skb->data[DHCP_OPTION53_STATUS_OFFSET]);
691 }
692 }
693}
694
695/**============================================================================
696 @brief hdd_dump_dhcp_pkt() -
697 Function to dump DHCP packets in TX and RX path.
698
699 @param skb : [in] pointer to OS packet (sk_buff)
700 @param path : [in] bool indicating TX/RX path
701 @return : None
702 ===========================================================================*/
703void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path)
704{
705
706 if ((ntohs(*((u16*)((u8*)skb->data + ETH_TYPE_OFFSET)))
707 == ETH_TYPE_IP_PKT) ||
708 (ntohs(*((u8*)skb->data + PROTOCOL_OFFSET)) == UDP_PROTOCOL)) {
709
710 /* IP protocol 12 bytes of mac addresses in 802.3 header */
711 if ( ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
712 BOOTP_SERVER_PORT ||
713 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
714 BOOTP_CLIENT_PORT ||
715 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
716 BOOTP_SERVER_PORT ||
717 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
718 BOOTP_CLIENT_PORT ) {
719
720 if (path == TX_PATH) {
721 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP TX PATH"));
722 } else {
723 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP RX PATH"));
724 }
725
726 hdd_dhcp_pkt_info(skb);
727 }
728 }
729}
730
Jeff Johnson295189b2012-06-20 16:38:30 -0700731/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530732 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 transmitting packets. There are 2 versions of this function. One that uses
734 locked queue and other that uses lockless queues. Both have been retained to
735 do some performance testing
736
737 @param skb : [in] pointer to OS packet (sk_buff)
738 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530739
Jeff Johnson295189b2012-06-20 16:38:30 -0700740 @return : NET_XMIT_DROP if packets are dropped
741 : NET_XMIT_SUCCESS if packet is enqueued succesfully
742 ===========================================================================*/
743int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
744{
745 VOS_STATUS status;
746 WLANTL_ACEnumType ac;
747 sme_QosWmmUpType up;
748 skb_list_node_t *pktNode = NULL;
749 hdd_list_node_t *anchor = NULL;
750 v_SIZE_t pktListSize = 0;
751 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
752 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700753 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Dino Mycled9b7cc12014-09-04 18:43:07 +0530755 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700756 v_BOOL_t txSuspended = VOS_FALSE;
Mihir Shetef8f74532014-12-04 11:53:34 +0530757 struct sk_buff *skb1;
Jeff Johnson295189b2012-06-20 16:38:30 -0700758
759 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
760
Ravi Joshif9520d62013-10-18 04:11:46 -0700761 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530762 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700763 "%s is called when netif TX %d is disabled",
764 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530765 return NETDEV_TX_BUSY;
766 }
767
Ravi Joshicc57ed42013-10-12 16:31:25 -0700768 //Get TL AC corresponding to Qdisc queue index/AC.
769 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
770
771 if (WLAN_HDD_IBSS == pAdapter->device_mode)
Shailender Karmuchia734f332013-04-19 14:02:48 -0700772 {
773 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
774
Ravi Joshif9520d62013-10-18 04:11:46 -0700775 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
Ravi Joshicc57ed42013-10-12 16:31:25 -0700776 {
c_hpothu32490782014-03-14 19:14:34 +0530777 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700778 "%s: Tx frame in disconnected state in IBSS mode", __func__);
779 ++pAdapter->stats.tx_dropped;
780 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
781 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
782 kfree_skb(skb);
783 return NETDEV_TX_OK;
784 }
785
Shailender Karmuchia734f332013-04-19 14:02:48 -0700786 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
787
788 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
789 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
790 vos_is_macaddr_group(pDestMacAddress)))
791 {
792 STAId = IBSS_BROADCAST_STAID;
c_hpothu32490782014-03-14 19:14:34 +0530793 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Ravi Joshif9520d62013-10-18 04:11:46 -0700794 "%s: BC/MC packet", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700795 }
796 else if (STAId == HDD_WLAN_INVALID_STA_ID)
797 {
c_hpothu32490782014-03-14 19:14:34 +0530798 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshif9520d62013-10-18 04:11:46 -0700799 "%s: Received Unicast frame with invalid staID", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700800 ++pAdapter->stats.tx_dropped;
801 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700802 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Shailender Karmuchia734f332013-04-19 14:02:48 -0700803 kfree_skb(skb);
804 return NETDEV_TX_OK;
805 }
806 }
807 else
808 {
809 STAId = pHddStaCtx->conn_info.staId[0];
810 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700811
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530812 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 //select_queue call back function
814 up = skb->priority;
815
816 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
817
818#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530819 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700820 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700821#endif // HDD_WMM_DEBUG
822
Mukul Sharma84f27252014-07-14 18:11:42 +0530823#ifdef DEBUG_ROAM_DELAY
824 vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
825 //Should we check below global to avoid function call each time ??
826/*
827 if(gRoamDelayMetaInfo.hdd_monitor_tx)
828 {
829 }
830 */
831#endif
832
Jeff Johnson295189b2012-06-20 16:38:30 -0700833 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700834 /*CR 463598,384996*/
835 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
836 *We check for +1 in the logic,to take care of Zero count which
837 *occurs very frequently in low traffic cases */
838 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
839 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700840 /* Use the following debug statement during Engineering Debugging.There are chance that this will lead to a Watchdog Bark
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700841 * if it is in the mainline code and if the log level is enabled by someone for debugging
c_hpothu32490782014-03-14 19:14:34 +0530842 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"%s:Queue is Filling up.Inform TL again about pending packets", __func__);*/
Shailender Karmuchia734f332013-04-19 14:02:48 -0700843
Ravi Joshi8a934352013-09-25 16:46:58 -0700844 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
845 STAId, ac
846 );
847 if ( !VOS_IS_STATUS_SUCCESS( status ) )
848 {
c_hpothu32490782014-03-14 19:14:34 +0530849 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700850 "%s: WLANTL_STAPktPending() returned error code %d",
851 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700852 ++pAdapter->stats.tx_dropped;
853 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
854 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Ravi Joshi8a934352013-09-25 16:46:58 -0700855 kfree_skb(skb);
856 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
857 return NETDEV_TX_OK;
858 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700859 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700860 //If we have already reached the max queue size, disable the TX queue
861 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
862 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700863 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
864 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
865 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
866 pAdapter->isTxSuspended[ac] = VOS_TRUE;
867 txSuspended = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700868 }
869
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530870 /* If 3/4th of the max queue size is used then enable the flag.
871 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
872 if (WLANTL_AC_BE == ac)
873 {
874 if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
875 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530876 pAdapter->isVosLowResource = VOS_TRUE;
877 }
878 else
879 {
880 pAdapter->isVosLowResource = VOS_FALSE;
881 }
882 }
883
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530884 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530885
886 if ( ( NULL != pHddCtx ) && pHddCtx->cfg_ini->enableDhcpDebug )
887 {
888 hdd_dump_dhcp_pkt(skb, TX_PATH);
889 }
890
Jeff Johnson295189b2012-06-20 16:38:30 -0700891 if (VOS_TRUE == txSuspended)
892 {
c_hpothu32490782014-03-14 19:14:34 +0530893 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530894 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700895 __func__, ac );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530896 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700897 }
898
899 //Use the skb->cb field to hold the list node information
900 pktNode = (skb_list_node_t *)&skb->cb;
901
902 //Stick the OS packet inside this node.
903 pktNode->skb = skb;
904
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530905 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700906 pktNode->userPriority = up;
907
908
909 INIT_LIST_HEAD(&pktNode->anchor);
910
911 //Insert the OS packet into the appropriate AC queue
912 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
913 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
914 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
915
916 if ( !VOS_IS_STATUS_SUCCESS( status ) )
917 {
c_hpothu32490782014-03-14 19:14:34 +0530918 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
920 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
921 ++pAdapter->stats.tx_dropped;
922 kfree_skb(skb);
923 return NETDEV_TX_OK;
924 }
925
926 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
927 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700928 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700929
Kiet Lamf040f472013-11-20 21:15:23 +0530930 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
931 {
932 /* Function which will determine acquire admittance for a
933 * WMM AC is required or not based on psb configuration done
934 * in the framework
935 */
936 hdd_wmm_acquire_access_required(pAdapter, ac);
937 }
938
Jeff Johnson295189b2012-06-20 16:38:30 -0700939 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530940 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
941 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700942 {
943 granted = VOS_TRUE;
944 }
945 else
946 {
947 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530948 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700949 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700950 if ( granted && ( pktListSize == 1 ))
951 {
952 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +0530953 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700954 status = WLANTL_STAPktPending(
955 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
956 STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700957 if ( !VOS_IS_STATUS_SUCCESS( status ) )
958 {
c_hpothu32490782014-03-14 19:14:34 +0530959 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d", __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700960
961 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
962 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
963 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
964 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
965 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Mihir Shetef8f74532014-12-04 11:53:34 +0530966 /* Free the skb only if we are able to remove it from the list.
967 * If we are not able to retrieve it from the list it means that
968 * the skb was pulled by TX Thread and is use so we should not free
969 * it here
970 */
971 if (VOS_IS_STATUS_SUCCESS(status))
972 {
973 pktNode = list_entry(anchor, skb_list_node_t, anchor);
974 skb1 = pktNode->skb;
975 kfree_skb(skb1);
976 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700977 ++pAdapter->stats.tx_dropped;
978 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
979 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Jeff Johnson295189b2012-06-20 16:38:30 -0700980 return NETDEV_TX_OK;
981 }
982 }
983
984 dev->trans_start = jiffies;
985
986 return NETDEV_TX_OK;
987}
988
989/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -0700990 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
991
992 @param pHddStaCtx : [in] pointer to HDD Station Context
993 pMacAddress [in] pointer to Peer Mac address
994 staID [out] pointer to Station Index
995 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
996 ===========================================================================*/
997
998VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
999{
1000 v_U8_t idx;
1001
1002 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
1003 {
1004 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
1005 pMacAddress, sizeof(v_MACADDR_t)))
1006 {
1007 *staId = pHddStaCtx->conn_info.staId[idx];
1008 return VOS_STATUS_SUCCESS;
1009 }
1010 }
1011
1012 return VOS_STATUS_E_FAILURE;
1013}
1014
1015/**============================================================================
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301016 @brief __hdd_tx_timeout() - Function handles timeout during transmission.
Jeff Johnson295189b2012-06-20 16:38:30 -07001017
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301018 @param dev : [in] pointer to network device
Jeff Johnson295189b2012-06-20 16:38:30 -07001019 @return : None
1020 ===========================================================================*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301021void __hdd_tx_timeout(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001022{
Ravi Joshicc57ed42013-10-12 16:31:25 -07001023 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1024 struct netdev_queue *txq;
1025 int i = 0;
Mukul Sharma42b3d432014-10-16 16:13:40 +05301026 v_ULONG_t diff_in_jiffies = 0;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001027
Mihir Shetef3473692014-06-27 15:13:20 +05301028 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1029 "%s: Transmission timeout occurred", __func__);
1030
c_hpothub8245442013-11-20 23:41:09 +05301031 if ( NULL == pAdapter )
1032 {
c_hpothu32490782014-03-14 19:14:34 +05301033 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301034 FL("pAdapter is NULL"));
1035 VOS_ASSERT(0);
1036 return;
1037 }
1038
Mihir Shetef3473692014-06-27 15:13:20 +05301039 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
1040
Jeff Johnson295189b2012-06-20 16:38:30 -07001041 //Getting here implies we disabled the TX queues for too long. Queues are
1042 //disabled either because of disassociation or low resource scenarios. In
1043 //case of disassociation it is ok to ignore this. But if associated, we have
1044 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -07001045
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301046 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001047 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
1048 pAdapter->wmm_tx_queue[0].count,
1049 pAdapter->wmm_tx_queue[1].count,
1050 pAdapter->wmm_tx_queue[2].count,
1051 pAdapter->wmm_tx_queue[3].count);
1052
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301053 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001054 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
1055 pAdapter->isTxSuspended[0],
1056 pAdapter->isTxSuspended[1],
1057 pAdapter->isTxSuspended[2],
1058 pAdapter->isTxSuspended[3]);
1059
1060 for (i = 0; i < 8; i++)
1061 {
1062 txq = netdev_get_tx_queue(dev, i);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301063 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001064 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
1065 }
1066
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301067 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001068 "carrier state: %d", netif_carrier_ok(dev));
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301069
Mihir Shetef3473692014-06-27 15:13:20 +05301070 /* continuousTxTimeoutCount will be reset whenever TL fetches packet
1071 * from HDD
1072 */
1073 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
1074
Mukul Sharma42b3d432014-10-16 16:13:40 +05301075 diff_in_jiffies = jiffies - pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut;
1076 if((pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount > 1)&&
1077 ((diff_in_jiffies) > (HDD_TX_TIMEOUT * 2 ))
1078 )
1079 {
1080 /*
1081 * In Open security case when there is no traffic is running, it may possible
1082 * tx time-out may once happen and later we recovered then we need to
1083 * reset the continuousTxTimeoutCount because it is only getting modified
1084 * when traffic is running. So if over a period of time if this count reaches
1085 * to HDD_TX_STALL_SSR_THRESHOLD then host is triggering false subsystem restart.
1086 * so in genuine Tx Time out case kernel will call the tx time-out back to back at
1087 * interval of HDD_TX_TIMEOUT.So now we are checking if previous TX TIME out was
1088 * occurred more then twice of HDD_TX_TIMEOUT back then we may recovered here.
1089 */
1090 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1091 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1092 FL("This is false alarm so resetting the continuousTxTimeoutCount"));
1093 }
1094
1095 //update last jiffies after the check
1096 pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut = jiffies;
1097
Mihir Shete327c2ab2014-11-13 15:17:02 +05301098 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
1099 HDD_TX_STALL_RECOVERY_THRESHOLD)
1100 {
1101 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1102 "%s: Request firmware for recovery",__func__);
1103 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
1104 }
1105
Mihir Shetef3473692014-06-27 15:13:20 +05301106 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1107 HDD_TX_STALL_SSR_THRESHOLD)
1108 {
1109 // Driver could not recover, issue SSR
1110 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1111 "%s: Cannot recover from Data stall Issue SSR",
1112 __func__);
Mihir Shetefd62d9d2014-08-06 15:08:21 +05301113 WLANTL_FatalError();
Mihir Shetef3473692014-06-27 15:13:20 +05301114 return;
1115 }
1116
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301117 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
1118 * every 5sec. The TL debug spits out a lot of information on the
1119 * serial console, if it is called every time *hdd_tx_timeout* is
1120 * called then we may get a watchdog bite on the Application
1121 * processor, so ratelimit the TL debug logs.
1122 */
1123 if (__ratelimit(&hdd_tx_timeout_rs))
1124 {
1125 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +05301126 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301127 }
Mihir Shetef3473692014-06-27 15:13:20 +05301128
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301129}
Jeff Johnson295189b2012-06-20 16:38:30 -07001130
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301131/**============================================================================
1132 @brief hdd_tx_timeout() - Function called by OS if there is any
1133 timeout during transmission. Since HDD simply enqueues packet
1134 and returns control to OS right away, this would never be invoked
1135
1136 @param dev : [in] pointer to network device
1137 @return : None
1138 ===========================================================================*/
1139void hdd_tx_timeout(struct net_device *dev)
1140{
1141 vos_ssr_protect(__func__);
1142 __hdd_tx_timeout(dev);
1143 vos_ssr_unprotect(__func__);
1144}
Jeff Johnson295189b2012-06-20 16:38:30 -07001145
1146/**============================================================================
1147 @brief hdd_stats() - Function registered with the Linux OS for
1148 device TX/RX statistic
1149
1150 @param dev : [in] pointer to Libra network device
1151
1152 @return : pointer to net_device_stats structure
1153 ===========================================================================*/
1154struct net_device_stats* hdd_stats(struct net_device *dev)
1155{
1156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +05301157
1158 if ( NULL == pAdapter )
1159 {
c_hpothu32490782014-03-14 19:14:34 +05301160 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301161 FL("pAdapter is NULL"));
1162 VOS_ASSERT(0);
1163 return NULL;
1164 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001165
1166 return &pAdapter->stats;
1167}
1168
1169
1170/**============================================================================
1171 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
1172 modules in HDD
1173
1174 @param pAdapter : [in] pointer to adapter context
1175 @return : VOS_STATUS_E_FAILURE if any errors encountered
1176 : VOS_STATUS_SUCCESS otherwise
1177 ===========================================================================*/
1178VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
1179{
1180 VOS_STATUS status = VOS_STATUS_SUCCESS;
1181 v_SINT_t i = -1;
1182
c_hpothub8245442013-11-20 23:41:09 +05301183 if ( NULL == pAdapter )
1184 {
c_hpothu32490782014-03-14 19:14:34 +05301185 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301186 FL("pAdapter is NULL"));
1187 VOS_ASSERT(0);
1188 return VOS_STATUS_E_FAILURE;
1189 }
1190
Jeff Johnson295189b2012-06-20 16:38:30 -07001191 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301192 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001193
1194 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
1195 //Will be zeroed out during alloc
1196
1197 while (++i != NUM_TX_QUEUES)
1198 {
1199 pAdapter->isTxSuspended[i] = VOS_FALSE;
1200 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1201 }
1202
1203 return status;
1204}
1205
1206
1207/**============================================================================
1208 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
1209 modules in HDD
1210
1211 @param pAdapter : [in] pointer to adapter context
1212 @return : VOS_STATUS_E_FAILURE if any errors encountered
1213 : VOS_STATUS_SUCCESS otherwise
1214 ===========================================================================*/
1215VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
1216{
1217 VOS_STATUS status = VOS_STATUS_SUCCESS;
1218 v_SINT_t i = -1;
1219
c_hpothub8245442013-11-20 23:41:09 +05301220 if ( NULL == pAdapter )
1221 {
c_hpothu32490782014-03-14 19:14:34 +05301222 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301223 FL("pAdapter is NULL"));
1224 VOS_ASSERT(0);
1225 return VOS_STATUS_E_FAILURE;
1226 }
1227
Jeff Johnson295189b2012-06-20 16:38:30 -07001228 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301229 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301230 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301231 FL("failed to flush tx queues"));
1232
Jeff Johnson295189b2012-06-20 16:38:30 -07001233 while (++i != NUM_TX_QUEUES)
1234 {
1235 //Free up actual list elements in the Tx queue
1236 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1237 }
1238
1239 return status;
1240}
1241
1242
1243/**============================================================================
1244 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1245 modules in HDD
1246
1247 @param pAdapter : [in] pointer to adapter context
1248 @return : VOS_STATUS_E_FAILURE if any errors encountered
1249 : VOS_STATUS_SUCCESS otherwise
1250 ===========================================================================*/
1251VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1252{
1253 return hdd_flush_tx_queues(pAdapter);
1254}
1255
1256
1257/**============================================================================
1258 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1259
1260 @param pVosPacket : [in] pointer to vos packet
1261 @return : VOS_TRUE if the packet is EAPOL
1262 : VOS_FALSE otherwise
1263 ===========================================================================*/
1264
1265v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1266{
1267 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1268 v_BOOL_t fEAPOL = VOS_FALSE;
1269 void *pBuffer = NULL;
1270
1271
1272 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1273 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
Abhishek Singhfa011222014-04-14 10:57:08 +05301274 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001275 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301276 if ( pBuffer && *(unsigned short*)pBuffer ==
1277 vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001278 {
1279 fEAPOL = VOS_TRUE;
1280 }
1281 }
1282
1283 return fEAPOL;
1284}
1285
Abhishek Singhfa011222014-04-14 10:57:08 +05301286/**============================================================================
1287 @brief hdd_IsARP() - Checks the packet is ARP or not.
1288
1289 @param pVosPacket : [in] pointer to vos packet
1290 @return : VOS_TRUE if the packet is ARP
1291 : VOS_FALSE otherwise
1292 ===========================================================================*/
1293
1294v_BOOL_t hdd_IsARP( vos_pkt_t *pVosPacket )
1295{
1296 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1297 v_BOOL_t fIsARP = VOS_FALSE;
1298 void *pBuffer = NULL;
1299
1300
1301 vosStatus = vos_pkt_peek_data( pVosPacket,
1302 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1303 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1304 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1305 {
1306 if ( pBuffer && *(unsigned short*)pBuffer ==
1307 vos_cpu_to_be16(HDD_ETHERTYPE_ARP) )
1308 {
1309 fIsARP = VOS_TRUE;
1310 }
1311 }
1312
1313 return fIsARP;
1314}
Jeff Johnson295189b2012-06-20 16:38:30 -07001315
1316#ifdef FEATURE_WLAN_WAPI // Need to update this function
1317/**============================================================================
1318 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1319
1320 @param pVosPacket : [in] pointer to vos packet
1321 @return : VOS_TRUE if the packet is WAI
1322 : VOS_FALSE otherwise
1323 ===========================================================================*/
1324
1325v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1326{
1327 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1328 v_BOOL_t fIsWAI = VOS_FALSE;
1329 void *pBuffer = NULL;
1330
1331 // Need to update this function
1332 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1333 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1334
1335 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1336 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301337 if ( pBuffer && *(unsigned short*)pBuffer ==
1338 vos_cpu_to_be16(HDD_ETHERTYPE_WAI) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001339 {
1340 fIsWAI = VOS_TRUE;
1341 }
1342 }
1343
1344 return fIsWAI;
1345}
1346#endif /* FEATURE_WLAN_WAPI */
1347
1348/**============================================================================
1349 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1350 to indicate that a packet has been transmitted across the SDIO bus
1351 succesfully. OS packet resources can be released after this cbk.
1352
1353 @param vosContext : [in] pointer to VOS context
1354 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1355 @param vosStatusIn : [in] status of the transmission
1356
1357 @return : VOS_STATUS_E_FAILURE if any errors encountered
1358 : VOS_STATUS_SUCCESS otherwise
1359 ===========================================================================*/
1360VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1361 vos_pkt_t *pVosPacket,
1362 VOS_STATUS vosStatusIn )
1363{
1364 VOS_STATUS status = VOS_STATUS_SUCCESS;
1365 hdd_adapter_t *pAdapter = NULL;
1366 hdd_context_t *pHddCtx = NULL;
1367 void* pOsPkt = NULL;
1368
1369 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1370 {
c_hpothu32490782014-03-14 19:14:34 +05301371 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301372 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001373 return VOS_STATUS_E_FAILURE;
1374 }
1375
1376 //Return the skb to the OS
1377 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301378 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001379 {
1380 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301381 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301382 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001383 vos_pkt_return_packet( pVosPacket );
1384 return VOS_STATUS_E_FAILURE;
1385 }
1386
1387 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001388 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001389 //Get the Adapter context.
1390 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Agarwal Ashish971c2882013-10-30 20:11:12 +05301391 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07001392 {
c_hpothu32490782014-03-14 19:14:34 +05301393 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301394 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001395 }
1396 else
1397 {
1398 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1399 }
1400
1401 kfree_skb((struct sk_buff *)pOsPkt);
1402
1403 //Return the VOS packet resources.
1404 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301405 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001406 {
c_hpothu32490782014-03-14 19:14:34 +05301407 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301408 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001409 }
1410
1411 return status;
1412}
1413
1414
1415/**============================================================================
1416 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1417 fetch a packet for transmission.
1418
1419 @param vosContext : [in] pointer to VOS context
1420 @param staId : [in] Station for which TL is requesting a pkt
1421 @param ac : [in] access category requested by TL
1422 @param pVosPacket : [out] pointer to VOS packet packet pointer
1423 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1424
1425 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1426 : VOS_STATUS_E_FAILURE if any errors encountered
1427 : VOS_STATUS_SUCCESS otherwise
1428 ===========================================================================*/
1429VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1430 v_U8_t *pStaId,
1431 WLANTL_ACEnumType ac,
1432 vos_pkt_t **ppVosPacket,
1433 WLANTL_MetaInfoType *pPktMetaInfo )
1434{
1435 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1436 hdd_adapter_t *pAdapter = NULL;
1437 hdd_context_t *pHddCtx = NULL;
1438 hdd_list_node_t *anchor = NULL;
1439 skb_list_node_t *pktNode = NULL;
1440 struct sk_buff *skb = NULL;
1441 vos_pkt_t *pVosPacket = NULL;
1442 v_MACADDR_t* pDestMacAddress = NULL;
1443 v_TIME_t timestamp;
1444 WLANTL_ACEnumType newAc;
1445 v_SIZE_t size = 0;
Abhishek Singhfa011222014-04-14 10:57:08 +05301446 v_U16_t packet_size;
Jeff Johnson295189b2012-06-20 16:38:30 -07001447 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001448 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001449
1450 //Sanity check on inputs
1451 if ( ( NULL == vosContext ) ||
1452 ( NULL == pStaId ) ||
1453 ( NULL == ppVosPacket ) ||
1454 ( NULL == pPktMetaInfo ) )
1455 {
c_hpothu32490782014-03-14 19:14:34 +05301456 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301457 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001458 return VOS_STATUS_E_FAILURE;
1459 }
1460
1461 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001462 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001463 if(pHddCtx == NULL)
1464 {
c_hpothu32490782014-03-14 19:14:34 +05301465 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301466 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001467 return VOS_STATUS_E_FAILURE;
1468 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001469 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001470 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001471 {
c_hpothu32490782014-03-14 19:14:34 +05301472 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301473 FL("pAdapter is NULL %u"), *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001474 VOS_ASSERT(0);
1475 return VOS_STATUS_E_FAILURE;
1476 }
1477
1478 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1479
1480 *ppVosPacket = NULL;
1481
1482 //Make sure the AC being asked for is sane
1483 if( ac >= WLANTL_MAX_AC || ac < 0)
1484 {
c_hpothu32490782014-03-14 19:14:34 +05301485 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301486 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001487 return VOS_STATUS_E_FAILURE;
1488 }
1489
1490 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1491
1492#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301493 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301494 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001495#endif // HDD_WMM_DEBUG
1496
1497 // We find an AC with packets
1498 // or we determine we have no more packets to send
1499 // HDD is not allowed to change AC.
1500
1501 // has this AC been admitted? or
1502 // To allow EAPOL packets when not authenticated
1503 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1504 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1505 {
1506 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1507#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301508 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001509 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001510#endif // HDD_WMM_DEBUG
1511 return VOS_STATUS_E_FAILURE;
1512 }
1513
1514 // do we have any packets pending in this AC?
1515 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1516 if( size > 0 )
1517 {
1518 // yes, so process it
1519#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301520 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001521 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001522#endif // HDD_WMM_DEBUG
1523 }
1524 else
1525 {
1526 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1527#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301528 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001529 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001530#endif // HDD_WMM_DEBUG
1531 return VOS_STATUS_E_FAILURE;
1532 }
1533
1534 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1535 //This simplifies the locking and unlocking of Tx queue
1536 status = vos_pkt_wrap_data_packet( &pVosPacket,
1537 VOS_PKT_TYPE_TX_802_3_DATA,
1538 NULL, //OS Pkt is not being passed
1539 hdd_tx_low_resource_cbk,
1540 pAdapter );
1541
1542 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1543 {
1544 //Remember VOS is in a low resource situation
1545 pAdapter->isVosOutOfResource = VOS_TRUE;
1546 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05301547 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001548 //TL will now think we have no more packets in this AC
1549 return VOS_STATUS_E_FAILURE;
1550 }
1551
1552 //Remove the packet from the queue
1553 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1554 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1555 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1556
1557 if(VOS_STATUS_SUCCESS == status)
1558 {
1559 //If success then we got a valid packet from some AC
1560 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1561 skb = pktNode->skb;
1562 }
1563 else
1564 {
1565 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05301566 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001567 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001568 vos_pkt_return_packet(pVosPacket);
1569 return VOS_STATUS_E_FAILURE;
1570 }
1571
1572 //Attach skb to VOS packet.
1573 status = vos_pkt_set_os_packet( pVosPacket, skb );
1574 if (status != VOS_STATUS_SUCCESS)
1575 {
c_hpothu32490782014-03-14 19:14:34 +05301576 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001577 vos_pkt_return_packet(pVosPacket);
1578 ++pAdapter->stats.tx_dropped;
1579 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1580 kfree_skb(skb);
1581 return VOS_STATUS_E_FAILURE;
1582 }
1583
1584 //Just being paranoid. To be removed later
1585 if(pVosPacket == NULL)
1586 {
c_hpothu32490782014-03-14 19:14:34 +05301587 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 ++pAdapter->stats.tx_dropped;
1589 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1590 kfree_skb(skb);
1591 return VOS_STATUS_E_FAILURE;
1592 }
1593
Dino Mycle3b9536d2014-07-09 22:05:24 +05301594#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1595 {
1596 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
1597 /* vos_is_macaddr_group expects data in v_MACADDR_t format
1598 */
1599 if (vos_is_macaddr_group(pDestMacAddress))
1600 {
1601 pAdapter->hdd_stats.hddTxRxStats.txMcast[ac]++;
1602 }
1603
1604 }
1605
1606#endif
1607
Chilam NG571c65a2013-01-19 12:27:36 +05301608#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001609 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05301610 {
1611 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301612 u8 mac[6];
1613
Hoonki Lee387663d2013-02-05 18:08:43 -08001614 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301615
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001616 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05301617 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301618 "broadcast packet, not adding to peer list");
1619 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1620 mac, 6) != 0) {
c_hpothu32490782014-03-14 19:14:34 +05301621 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001622 "extract mac: " MAC_ADDRESS_STR,
1623 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05301624
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001625 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301626 } else {
c_hpothu32490782014-03-14 19:14:34 +05301627 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301628 "packet da is bssid, not adding to peer list");
1629 }
1630 }
1631#endif
1632
Jeff Johnson295189b2012-06-20 16:38:30 -07001633 //Return VOS packet to TL;
1634 *ppVosPacket = pVosPacket;
1635
1636 //Fill out the meta information needed by TL
1637 //FIXME This timestamp is really the time stamp of wrap_data_packet
1638 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1639 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1640
1641 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1642 pPktMetaInfo->ucIsEapol = 0;
1643 else
1644 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1645
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001646 if (pHddCtx->cfg_ini->gEnableDebugLog)
1647 {
1648 proto_type = vos_pkt_get_proto_type(skb,
1649 pHddCtx->cfg_ini->gEnableDebugLog);
1650 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1651 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301652 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001653 "STA TX EAPOL");
1654 }
1655 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1656 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301657 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001658 "STA TX DHCP");
1659 }
1660 }
1661
Abhishek Singhfa011222014-04-14 10:57:08 +05301662 vos_pkt_get_packet_length( pVosPacket,&packet_size );
1663 if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
1664 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
1665
Jeff Johnson295189b2012-06-20 16:38:30 -07001666#ifdef FEATURE_WLAN_WAPI
1667 // Override usIsEapol value when its zero for WAPI case
1668 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
1669#endif /* FEATURE_WLAN_WAPI */
1670
1671 if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) ||
1672 (!pAdapter->hddWmmStatus.wmmQap))
1673 {
1674 // either we don't want QoS or the AP doesn't support QoS
1675 pPktMetaInfo->ucUP = 0;
1676 pPktMetaInfo->ucTID = 0;
1677 }
1678 else
1679 {
1680 /* 1. Check if ACM is set for this AC
1681 * 2. If set, check if this AC had already admitted
Mukul Sharma95f79cb2014-11-24 12:50:24 +05301682 * 3. If not already admitted, downgrade the UP to next best UP
1683 * 4. Allow only when medium time is non zero when Addts accepted else downgrade traffic.
1684 we opted downgrading over Delts when medium time is zero because while doing downgradig
1685 driver is not clearing the wmm context so consider in subsequent roaming if AP (new or
1686 same AP) accept the Addts with valid medium time no application support is required
1687 where if we have opted delts Applications have to again do Addts or STA will never
1688 go for Addts.*/
1689
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
Mukul Sharma95f79cb2014-11-24 12:50:24 +05301691 (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid &&
1692 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07001693 {
1694 pPktMetaInfo->ucUP = pktNode->userPriority;
1695 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1696 }
1697 else
1698 {
1699 //Downgrade the UP
1700 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1701 newAc = WLANTL_AC_BK;
1702 for (i=ac-1; i>0; i--)
1703 {
1704 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1705 {
1706 newAc = i;
1707 break;
1708 }
1709 }
1710 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1711 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
c_hpothu32490782014-03-14 19:14:34 +05301712 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07001713 }
1714 }
1715
Mukul Sharma84f27252014-07-14 18:11:42 +05301716#ifdef DEBUG_ROAM_DELAY
1717 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
1718#endif
1719
Jeff Johnson295189b2012-06-20 16:38:30 -07001720 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1721 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1722 if ( 1 < size )
1723 {
1724 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1725 }
1726 else
1727 {
1728 pPktMetaInfo->bMorePackets = 0;
1729 }
1730
1731 //Extract the destination address from ethernet frame
1732 pDestMacAddress = (v_MACADDR_t*)skb->data;
1733 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1734 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1735
1736
1737
1738 // if we are in a backpressure situation see if we can turn the hose back on
1739 if ( (pAdapter->isTxSuspended[ac]) &&
1740 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1741 {
1742 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1743 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05301744 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001745 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001746 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1747 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1748 skb_get_queue_mapping(skb) ));
1749 }
1750
1751
1752 // We're giving the packet to TL so consider it transmitted from
1753 // a statistics perspective. We account for it here instead of
1754 // when the packet is returned for two reasons. First, TL will
1755 // manipulate the skb to the point where the len field is not
1756 // accurate, leading to inaccurate byte counts if we account for
1757 // it later. Second, TL does not provide any feedback as to
1758 // whether or not the packet was successfully sent over the air,
1759 // so the packet counts will be the same regardless of where we
1760 // account for them
1761 pAdapter->stats.tx_bytes += skb->len;
1762 ++pAdapter->stats.tx_packets;
1763 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1764 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301765 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001766
Leo Chang50bbd252013-04-25 14:58:01 -07001767 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1768 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001769 {
1770 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1771 {
c_hpothu32490782014-03-14 19:14:34 +05301772 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001773 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001774 return VOS_STATUS_E_FAILURE;
1775 }
1776 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1777 {
1778 if(0 == pHddCtx->tmInfo.txFrameCount)
1779 {
1780 /* Just recovered from sleep timeout */
1781 pHddCtx->tmInfo.lastOpenTs = timestamp;
1782 }
1783
Leo Chang50bbd252013-04-25 14:58:01 -07001784 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1785 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001786 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1787 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001788 /* During TX open duration, TX frame count is larger than threshold
1789 * Block TX during Sleep time */
1790 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001791 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001792 pHddCtx->tmInfo.lastblockTs = timestamp;
1793 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1794 {
1795 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1796 }
1797 }
1798 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1799 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1800 {
1801 /* During TX open duration, TX frame count is less than threshold
1802 * Reset count and timestamp to prepare next cycle */
1803 pHddCtx->tmInfo.lastOpenTs = timestamp;
1804 pHddCtx->tmInfo.txFrameCount = 0;
1805 }
1806 else
1807 {
1808 /* Do Nothing */
1809 }
1810 pHddCtx->tmInfo.txFrameCount++;
1811 }
1812 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1813 }
1814
1815
1816#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301817 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,"%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001818#endif // HDD_WMM_DEBUG
1819
1820 return status;
1821}
1822
1823
1824/**============================================================================
1825 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1826 case where VOS packets are not available at the time of the call to get
1827 packets. This callback function is invoked by VOS when packets are
1828 available.
1829
1830 @param pVosPacket : [in] pointer to VOS packet
1831 @param userData : [in] opaque user data that was passed initially
1832
1833 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1834 : VOS_STATUS_SUCCESS otherwise
1835 =============================================================================*/
1836VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1837 v_VOID_t *userData )
1838{
1839 VOS_STATUS status;
1840 v_SINT_t i = 0;
1841 v_SIZE_t size = 0;
1842 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1843
Agarwal Ashish971c2882013-10-30 20:11:12 +05301844 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001845 {
c_hpothu32490782014-03-14 19:14:34 +05301846 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301847 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001848 return VOS_STATUS_E_FAILURE;
1849 }
1850
1851 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1852 //situation. Here we will only signal TL that there is a pending data for a STA.
1853 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1854 vos_pkt_return_packet( pVosPacket );
1855
1856 pAdapter->isVosOutOfResource = VOS_FALSE;
1857
1858 //Indicate to TL that there is pending data if a queue is non empty
1859 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1860 {
1861 size = 0;
1862 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1863 if ( size > 0 )
1864 {
1865 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1866 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1867 (WLANTL_ACEnumType)i );
1868 if( !VOS_IS_STATUS_SUCCESS( status ) )
1869 {
c_hpothu32490782014-03-14 19:14:34 +05301870 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301871 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001872 }
1873 }
1874 }
1875
1876 return VOS_STATUS_SUCCESS;
1877}
1878
1879
1880/**============================================================================
1881 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1882 TL will call this to notify the HDD when one or more packets were
1883 received for a registered STA.
1884
1885 @param vosContext : [in] pointer to VOS context
1886 @param pVosPacketChain : [in] pointer to VOS packet chain
1887 @param staId : [in] Station Id
1888 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1889
1890 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1891 : VOS_STATUS_SUCCESS otherwise
1892 ===========================================================================*/
1893VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1894 vos_pkt_t *pVosPacketChain,
1895 v_U8_t staId,
1896 WLANTL_RxMetaInfoType* pRxMetaInfo )
1897{
1898 hdd_adapter_t *pAdapter = NULL;
1899 hdd_context_t *pHddCtx = NULL;
1900 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1901 int rxstat;
1902 struct sk_buff *skb = NULL;
1903 vos_pkt_t* pVosPacket;
1904 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001905 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001906
1907 //Sanity check on inputs
1908 if ( ( NULL == vosContext ) ||
1909 ( NULL == pVosPacketChain ) ||
1910 ( NULL == pRxMetaInfo ) )
1911 {
c_hpothu32490782014-03-14 19:14:34 +05301912 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301913 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001914 return VOS_STATUS_E_FAILURE;
1915 }
1916
Kiet Lam3c2ee302014-03-23 23:23:22 -07001917 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001918 if ( NULL == pHddCtx )
1919 {
c_hpothu32490782014-03-14 19:14:34 +05301920 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301921 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 return VOS_STATUS_E_FAILURE;
1923 }
1924
1925 pAdapter = pHddCtx->sta_to_adapter[staId];
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301926 if( (NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 {
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301928 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1929 "%s: pAdapter is Null or adapter has invalid magic for staId %u",
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05301930 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001931 return VOS_STATUS_E_FAILURE;
1932 }
1933
1934 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1935
1936 // walk the chain until all are processed
1937 pVosPacket = pVosPacketChain;
1938 do
1939 {
1940 // get the pointer to the next packet in the chain
1941 // (but don't unlink the packet since we free the entire chain later)
1942 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1943
1944 // both "success" and "empty" are acceptable results
1945 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1946 {
1947 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301948 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301949 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001950 return VOS_STATUS_E_FAILURE;
1951 }
1952
1953 // Extract the OS packet (skb).
1954 // Tell VOS to detach the OS packet from the VOS packet
1955 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1956 if(!VOS_IS_STATUS_SUCCESS( status ))
1957 {
1958 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301959 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301960 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 return VOS_STATUS_E_FAILURE;
1962 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001963
1964 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1965 {
c_hpothu32490782014-03-14 19:14:34 +05301966 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07001967 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
1968 return eHAL_STATUS_FAILURE;
1969 }
1970
Chilam Ng1279e232013-01-25 15:06:52 -08001971#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001972 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
1973 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08001974 {
1975 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08001976 u8 mac[6];
1977
Hoonki Lee387663d2013-02-05 18:08:43 -08001978 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08001979
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001980 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05301981 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08001982 "rx broadcast packet, not adding to peer list");
1983 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1984 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001985 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05301986 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001987 "rx extract mac:" MAC_ADDRESS_STR,
1988 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301989 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05301990 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
1991 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001992 {
1993 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05301994 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001995 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
1996 }
Chilam Ng1279e232013-01-25 15:06:52 -08001997 } else {
c_hpothu32490782014-03-14 19:14:34 +05301998 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08001999 "rx packet sa is bssid, not adding to peer list");
2000 }
2001 }
2002#endif
2003
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002004 if (pHddCtx->cfg_ini->gEnableDebugLog)
2005 {
2006 proto_type = vos_pkt_get_proto_type(skb,
2007 pHddCtx->cfg_ini->gEnableDebugLog);
2008 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2009 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302010 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002011 "STA RX EAPOL");
2012 }
2013 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2014 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302015 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002016 "STA RX DHCP");
2017 }
2018 }
2019
Mukul Sharma84f27252014-07-14 18:11:42 +05302020#ifdef DEBUG_ROAM_DELAY
2021 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2022 //Should we check below global to avoid function call each time ??
2023 /*
2024 if(gRoamDelayMetaInfo.hdd_monitor_rx)
2025 {
2026 }
2027 */
2028#endif
Dino Mycled9b7cc12014-09-04 18:43:07 +05302029 if ( pHddCtx->cfg_ini->enableDhcpDebug )
2030 {
2031 hdd_dump_dhcp_pkt(skb, RX_PATH);
2032 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302033
Jeff Johnson295189b2012-06-20 16:38:30 -07002034 skb->dev = pAdapter->dev;
2035 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002036 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002037 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2038 ++pAdapter->stats.rx_packets;
2039 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002040#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002041#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002042 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002043#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002044#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002045 rxstat = netif_rx_ni(skb);
2046 if (NET_RX_SUCCESS == rxstat)
2047 {
2048 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002049 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002050 }
2051 else
2052 {
2053 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2054 }
2055 // now process the next packet in the chain
2056 pVosPacket = pNextVosPacket;
2057
2058 } while (pVosPacket);
2059
2060 //Return the entire VOS packet chain to the resource pool
2061 status = vos_pkt_return_packet( pVosPacketChain );
2062 if(!VOS_IS_STATUS_SUCCESS( status ))
2063 {
c_hpothu32490782014-03-14 19:14:34 +05302064 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002065 }
2066
2067 pAdapter->dev->last_rx = jiffies;
2068
2069 return status;
2070}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002071/**============================================================================
2072 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2073 Enable/Disable split scan based on TX and RX traffic.
2074 @param HddContext : [in] pointer to Hdd context
2075 @return : None
2076 ===========================================================================*/
2077void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2078{
2079 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2080 hdd_adapter_t *pAdapter = NULL;
2081 hdd_station_ctx_t *pHddStaCtx = NULL;
2082 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2083 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2084 VOS_STATUS status;
2085 v_U8_t staId = 0;
2086 v_U8_t fconnected = 0;
2087
c_hpothub8245442013-11-20 23:41:09 +05302088 if (NULL == phddctx)
2089 {
c_hpothu32490782014-03-14 19:14:34 +05302090 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05302091 FL("phddctx is NULL"));
2092 VOS_ASSERT(0);
2093 return;
2094 }
2095
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002096 if (!cfg_param->dynSplitscan)
2097 {
c_hpothu32490782014-03-14 19:14:34 +05302098 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002099 "%s: Error : Dynamic split scan is not Enabled : %d",
2100 __func__, pHddCtx->cfg_ini->dynSplitscan);
2101 return;
2102 }
2103
2104 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2105 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2106 {
2107 pAdapter = pAdapterNode->pAdapter;
2108
2109 if ( pAdapter )
2110 {
c_hpothu32490782014-03-14 19:14:34 +05302111 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002112 "%s: Adapter with device mode %d exists",
2113 __func__, pAdapter->device_mode);
2114
2115 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2116 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2117 {
2118 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2119 if ((eConnectionState_Associated ==
2120 pHddStaCtx->conn_info.connState) &&
2121 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2122 {
2123 fconnected = TRUE;
2124 }
2125 }
2126 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2127 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2128 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302129 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2130 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2131 if(pSapCtx == NULL){
2132 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2133 FL("psapCtx is NULL"));
2134 return;
2135 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002136 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2137 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302138 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002139 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302140 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002141 {
2142 fconnected = TRUE;
2143 }
2144 }
2145 }
2146 if ( fconnected )
2147 {
c_hpothu32490782014-03-14 19:14:34 +05302148 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002149 "%s: One of the interface is connected check for scan",
2150 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302151 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302152 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
2153 "miracast = %d", __func__,
2154 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
2155 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
2156 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002157
2158 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
2159 cfg_param->trafficMntrTmrForSplitScan);
2160 //Check for the previous statistics count
2161 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
2162 cfg_param->txRxThresholdForSplitScan) ||
2163 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
2164 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05302165 pHddCtx->drvr_miracast ||
2166 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002167 {
2168 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2169 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2170
2171 if (!pHddCtx->issplitscan_enabled)
2172 {
2173 pHddCtx->issplitscan_enabled = TRUE;
2174 sme_enable_disable_split_scan(
2175 WLAN_HDD_GET_HAL_CTX(pAdapter),
2176 cfg_param->nNumStaChanCombinedConc,
2177 cfg_param->nNumP2PChanCombinedConc);
2178 }
2179 return;
2180 }
2181 else
2182 {
2183 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2184 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2185 }
2186 fconnected = FALSE;
2187 }
2188 }
2189 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
2190 pAdapterNode = pNext;
2191 }
2192
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05302193 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
2194 * of disabling the split scan and thus do not disable the same when the
2195 * low TXRX condition is met.
2196 */
2197 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002198 {
c_hpothu32490782014-03-14 19:14:34 +05302199 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002200 "%s: Disable split scan", __func__);
2201 pHddCtx->issplitscan_enabled = FALSE;
2202 sme_enable_disable_split_scan(
2203 pHddCtx->hHal,
2204 SME_DISABLE_SPLIT_SCAN,
2205 SME_DISABLE_SPLIT_SCAN);
2206 }
2207 return;
2208}
Jeff Johnson295189b2012-06-20 16:38:30 -07002209