blob: 980a7fe430b38c78dd6efb65376ee8532e5b9131 [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>
49
Jeff Johnson295189b2012-06-20 16:38:30 -070050#include <wlan_hdd_p2p.h>
51#include <linux/wireless.h>
52#include <net/cfg80211.h>
53#include <net/ieee80211_radiotap.h>
54#include "sapApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070055
Chilam NG571c65a2013-01-19 12:27:36 +053056#ifdef FEATURE_WLAN_TDLS
57#include "wlan_hdd_tdls.h"
58#endif
59
Jeff Johnson295189b2012-06-20 16:38:30 -070060/*---------------------------------------------------------------------------
61 Preprocessor definitions and constants
62 -------------------------------------------------------------------------*/
63
64const v_U8_t hddWmmAcToHighestUp[] = {
65 SME_QOS_WMM_UP_RESV,
66 SME_QOS_WMM_UP_EE,
67 SME_QOS_WMM_UP_VI,
68 SME_QOS_WMM_UP_NC
69};
70
71//Mapping Linux AC interpretation to TL AC.
72const v_U8_t hdd_QdiscAcToTlAC[] = {
73 WLANTL_AC_VO,
74 WLANTL_AC_VI,
75 WLANTL_AC_BE,
76 WLANTL_AC_BK,
77};
78
Jeff Johnson295189b2012-06-20 16:38:30 -070079static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070080
81/*---------------------------------------------------------------------------
82 Type declarations
83 -------------------------------------------------------------------------*/
84
85/*---------------------------------------------------------------------------
86 Function definitions and documenation
87 -------------------------------------------------------------------------*/
88
89#ifdef DATA_PATH_UNIT_TEST
90//Utility function to dump an sk_buff
91static void dump_sk_buff(struct sk_buff * skb)
92{
c_hpothu32490782014-03-14 19:14:34 +053093 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
94 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
95 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
96 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
97 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
98 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
99 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 -0700100
c_hpothu32490782014-03-14 19:14:34 +0530101 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 -0700102 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
103 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu32490782014-03-14 19:14:34 +0530104 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 -0700105 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
106 skb->data[13], skb->data[14], skb->data[15]);
107}
108
109//Function for Unit Test only
110static void transport_thread(hdd_adapter_t *pAdapter)
111{
112 v_U8_t staId;
113 WLANTL_ACEnumType ac = WLANTL_AC_BE;
114 vos_pkt_t *pVosPacket = NULL ;
115 vos_pkt_t dummyPacket;
116 WLANTL_MetaInfoType pktMetaInfo;
117 WLANTL_RxMetaInfoType pktRxMetaInfo;
118 VOS_STATUS status = VOS_STATUS_E_FAILURE;
119
c_hpothub8245442013-11-20 23:41:09 +0530120 if (NULL == pAdapter)
121 {
c_hpothu32490782014-03-14 19:14:34 +0530122 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530123 FL("pAdapter is NULL"));
124 VOS_ASSERT(0);
125 return;
126 }
127
Jeff Johnson295189b2012-06-20 16:38:30 -0700128 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
129 &staId,
130 &ac,
131 &pVosPacket,
132 &pktMetaInfo );
133 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530134 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
135 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700136 else
c_hpothu32490782014-03-14 19:14:34 +0530137 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
138 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700139
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700140 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700141 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530142 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
143 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700144 else
c_hpothu32490782014-03-14 19:14:34 +0530145 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
146 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700147
148 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
149 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530150 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
151 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700152 else
c_hpothu32490782014-03-14 19:14:34 +0530153 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
154 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
156 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
157 &dummyPacket,
158 staId,
159 &pktRxMetaInfo);
160 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_rx_packet_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_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700166
167}
168#endif
169
170
171/**============================================================================
172 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
173
174 @param pAdapter : [in] pointer to adapter context
175 @return : VOS_STATUS_E_FAILURE if any errors encountered
176 : VOS_STATUS_SUCCESS otherwise
177 ===========================================================================*/
178static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
179{
180 VOS_STATUS status = VOS_STATUS_SUCCESS;
181 v_SINT_t i = -1;
182 hdd_list_node_t *anchor = NULL;
183 skb_list_node_t *pktNode = NULL;
184 struct sk_buff *skb = NULL;
185
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530186 pAdapter->isVosLowResource = VOS_FALSE;
187
Jeff Johnson295189b2012-06-20 16:38:30 -0700188 while (++i != NUM_TX_QUEUES)
189 {
190 //Free up any packets in the Tx queue
191 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
192 while (true)
193 {
194 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
195 if(VOS_STATUS_E_EMPTY != status)
196 {
197 pktNode = list_entry(anchor, skb_list_node_t, anchor);
198 skb = pktNode->skb;
199 //TODO
200 //++pAdapter->stats.tx_dropped;
201 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
202 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
203 kfree_skb(skb);
204 continue;
205 }
206 break;
207 }
208 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
209 // backpressure is no longer in effect
210 pAdapter->isTxSuspended[i] = VOS_FALSE;
211 }
212
213 return status;
214}
215
Ravi Joshif9520d62013-10-18 04:11:46 -0700216/**============================================================================
217 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
218 in IBSS mode
219
220 @param pAdapter : [in] pointer to adapter context
221 : [in] Staion Id
222 @return : VOS_STATUS_E_FAILURE if any errors encountered
223 : VOS_STATUS_SUCCESS otherwise
224 ===========================================================================*/
225void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
226{
227 v_U8_t i;
Ravi Joshi41914632013-10-21 23:02:21 -0700228 v_SIZE_t size = 0;
Ravi Joshif9520d62013-10-18 04:11:46 -0700229 v_U8_t skbStaIdx;
Ravi Joshi41914632013-10-21 23:02:21 -0700230 skb_list_node_t *pktNode = NULL;
231 hdd_list_node_t *tmp = NULL, *next = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700232 struct netdev_queue *txq;
Ravi Joshi41914632013-10-21 23:02:21 -0700233 struct sk_buff *skb = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700234
c_hpothub8245442013-11-20 23:41:09 +0530235 if (NULL == pAdapter)
236 {
c_hpothu32490782014-03-14 19:14:34 +0530237 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530238 FL("pAdapter is NULL %u"), STAId);
239 VOS_ASSERT(0);
240 return;
241 }
242
Ravi Joshif9520d62013-10-18 04:11:46 -0700243 for (i = 0; i < NUM_TX_QUEUES; i++)
244 {
245 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
246
247 if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) )
248 {
249 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
250 continue;
251 }
252
253 /* Iterate through the queue and identify the data for STAId */
Ravi Joshi41914632013-10-21 23:02:21 -0700254 list_for_each_safe(tmp, next, &pAdapter->wmm_tx_queue[i].anchor)
Ravi Joshif9520d62013-10-18 04:11:46 -0700255 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700256 pktNode = list_entry(tmp, skb_list_node_t, anchor);
257 if (pktNode != NULL)
258 {
259 skb = pktNode->skb;
260
261 /* Get the STAId from data */
262 skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
263 if (skbStaIdx == STAId)
264 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700265 /* Data for STAId is freed along with the queue node */
Ravi Joshif9520d62013-10-18 04:11:46 -0700266 list_del(tmp);
Mihir Shete31e1e392014-03-24 17:09:09 +0530267 kfree_skb(skb);
Ravi Joshif9520d62013-10-18 04:11:46 -0700268
269 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
270 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
271 pAdapter->wmm_tx_queue[i].count--;
272 }
273 }
274 }
275
276 /* Restart the queue only-if suspend and the queue was flushed */
Ravi Joshi41914632013-10-21 23:02:21 -0700277 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
Ravi Joshif9520d62013-10-18 04:11:46 -0700278 txq = netdev_get_tx_queue(pAdapter->dev, i);
Ravi Joshi41914632013-10-21 23:02:21 -0700279
280 if (VOS_TRUE == pAdapter->isTxSuspended[i] &&
281 size <= HDD_TX_QUEUE_LOW_WATER_MARK &&
282 netif_tx_queue_stopped(txq) )
Ravi Joshif9520d62013-10-18 04:11:46 -0700283 {
284 netif_tx_start_queue(txq);
Ravi Joshi41914632013-10-21 23:02:21 -0700285 pAdapter->isTxSuspended[i] = VOS_FALSE;
286 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressured;
287 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressuredAC[i];
Ravi Joshif9520d62013-10-18 04:11:46 -0700288 }
289
290 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
291 }
292}
293
Jeff Johnson295189b2012-06-20 16:38:30 -0700294static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
295{
296 skb_list_node_t *pktNode = NULL;
297 struct sk_buff *skb = NULL;
298 v_SIZE_t size = 0;
299 WLANTL_ACEnumType ac = 0;
300 VOS_STATUS status = VOS_STATUS_E_FAILURE;
301 hdd_list_node_t *anchor = NULL;
302
c_hpothu77731d42014-01-23 13:59:03 +0530303 if (NULL == pAdapter)
304 {
305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
306 FL("pAdapter is NULL"));
307 VOS_ASSERT(0);
308 return NULL;
309 }
310
Jeff Johnson295189b2012-06-20 16:38:30 -0700311 // do we have any packets pending in this AC?
312 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
313 if( size == 0 )
314 {
c_hpothu32490782014-03-14 19:14:34 +0530315 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700316 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700317 return NULL;
318 }
319
320 //Remove the packet from the queue
321 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
322 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
323 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
324
325 if(VOS_STATUS_SUCCESS == status)
326 {
327 //If success then we got a valid packet from some AC
328 pktNode = list_entry(anchor, skb_list_node_t, anchor);
329 skb = pktNode->skb;
330 }
331 else
332 {
c_hpothu32490782014-03-14 19:14:34 +0530333 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700334 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700335 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700336
337 return NULL;
338 }
339
340 // if we are in a backpressure situation see if we can turn the hose back on
341 if ( (pAdapter->isTxSuspended[ac]) &&
342 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
343 {
c_hpothu32490782014-03-14 19:14:34 +0530344 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700345 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700346 pAdapter->isTxSuspended[ac] = VOS_FALSE;
347 /* Enable Queues which we have disabled earlier */
348 netif_tx_start_all_queues( pAdapter->dev );
349 }
350
351 return skb;
352}
353
354void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
355{
356 hdd_cfg80211_state_t *cfgState;
357 struct sk_buff* skb;
358 hdd_adapter_t* pMonAdapter = NULL;
359 struct ieee80211_hdr *hdr;
360
Mukul Sharma23a92232014-04-07 18:04:00 +0530361 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700362 {
c_hpothu32490782014-03-14 19:14:34 +0530363 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530364 FL("pAdapter is NULL"));
365 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700366 return;
367 }
368
369 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530370 if (pMonAdapter == NULL)
371 {
372 hddLog(VOS_TRACE_LEVEL_ERROR,
373 "%s: pMonAdapter is NULL", __func__);
374 return;
375 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700376 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
377
378 if( NULL != cfgState->buf )
379 {
c_hpothu32490782014-03-14 19:14:34 +0530380 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700381 "%s: Already one MGMT packet Tx going on", __func__);
382 return;
383 }
384
385 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
386
387 if (NULL == skb)
388 {
c_hpothu32490782014-03-14 19:14:34 +0530389 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700390 "%s: No Packet Pending", __func__);
391 return;
392 }
393
394 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
395 if( cfgState->buf == NULL )
396 {
c_hpothu32490782014-03-14 19:14:34 +0530397 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700398 "%s: Failed to Allocate memory", __func__);
399 goto fail;
400 }
401
402 cfgState->len = skb->len;
403
404 vos_mem_copy( cfgState->buf, skb->data, skb->len);
405
406 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800407 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700408
409 hdr = (struct ieee80211_hdr *)skb->data;
410 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
411 == HDD_FRAME_TYPE_MGMT )
412 {
413 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
414 == HDD_FRAME_SUBTYPE_DEAUTH )
415 {
416 hdd_softap_sta_deauth( pAdapter, hdr->addr1 );
417 goto mgmt_handled;
418 }
419 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
420 == HDD_FRAME_SUBTYPE_DISASSOC )
421 {
422 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
423 goto mgmt_handled;
424 }
425 }
c_hpothu32490782014-03-14 19:14:34 +0530426 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700427 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
428
Jeff Johnson43971f52012-07-17 12:26:56 -0700429 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700430 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700431 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700432 {
c_hpothu32490782014-03-14 19:14:34 +0530433 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700434 "%s: WLANSAP_SendAction returned fail", __func__);
435 hdd_sendActionCnf( pAdapter, FALSE );
436 }
437 return;
438
439mgmt_handled:
440 hdd_sendActionCnf( pAdapter, TRUE );
441 return;
442fail:
443 kfree_skb(pAdapter->skb_to_tx);
444 pAdapter->skb_to_tx = NULL;
445 return;
446}
447
448void hdd_mon_tx_work_queue(struct work_struct *work)
449{
450 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
451 hdd_mon_tx_mgmt_pkt(pAdapter);
452}
453
454int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
455{
456 v_U16_t rt_hdr_len;
457 struct ieee80211_hdr *hdr;
458 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
459 struct ieee80211_radiotap_header *rtap_hdr =
460 (struct ieee80211_radiotap_header *)skb->data;
461
462 /*Supplicant sends the EAPOL packet on monitor interface*/
463 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
464 if(pPgBkAdapter == NULL)
465 {
c_hpothu32490782014-03-14 19:14:34 +0530466 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700467 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
468 __func__);
469 goto fail; /* too short to be possibly valid */
470 }
471
472 /* check if toal skb length is greater then radio tab header length of not */
473 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
474 goto fail; /* too short to be possibly valid */
475
476 /* check if radio tap header version is correct or not */
477 if (unlikely(rtap_hdr->it_version))
478 goto fail; /* only version 0 is supported */
479
480 /*Strip off the radio tap header*/
481 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
482
483 /* check if skb length if greator then total radio tap header length ot not*/
484 if (unlikely(skb->len < rt_hdr_len))
485 goto fail;
486
487 /* Update the trans_start for this netdev */
488 dev->trans_start = jiffies;
489 /*
490 * fix up the pointers accounting for the radiotap
491 * header still being in there.
492 */
493 skb_set_mac_header(skb, rt_hdr_len);
494 skb_set_network_header(skb, rt_hdr_len);
495 skb_set_transport_header(skb, rt_hdr_len);
496
497 /* Pull rtap header out of the skb */
498 skb_pull(skb, rt_hdr_len);
499
500 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
501 * radio tap header and 802.11 header starts
502 */
503 hdr = (struct ieee80211_hdr *)skb->data;
504
505 /* Send data frames through the normal Data path. In this path we will
506 * conver rcvd 802.11 packet to 802.3 packet */
507 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
508 {
509 v_U8_t da[6];
510 v_U8_t sa[6];
511
512 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
513 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
514
515 /* Pull 802.11 MAC header */
516 skb_pull(skb, HDD_80211_HEADER_LEN);
517
518 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
519 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
520 {
521 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
522 }
523
524 /* Pull LLC header */
525 skb_pull(skb, HDD_LLC_HDR_LEN);
526
527 /* Create space for Ethernet header */
528 skb_push(skb, HDD_MAC_HDR_SIZE*2);
529 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
530 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
531
532 /* Only EAPOL Data packets are allowed through monitor interface */
533 if (vos_be16_to_cpu(
534 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
535 != HDD_ETHERTYPE_802_1_X)
536 {
c_hpothu32490782014-03-14 19:14:34 +0530537 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700538 "%s: Not a Eapol packet. Drop this frame", __func__);
539 //If not EAPOL frames, drop them.
540 kfree_skb(skb);
541 return NETDEV_TX_OK;
542 }
543
544 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
545
546 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
547 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
548 }
549 else
550 {
551 VOS_STATUS status;
552 WLANTL_ACEnumType ac = 0;
553 skb_list_node_t *pktNode = NULL;
554 v_SIZE_t pktListSize = 0;
555
556 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
557 //If we have already reached the max queue size, disable the TX queue
558 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
559 {
560 /* We want to process one packet at a time, so lets disable all TX queues
561 * and re-enable the queues once we get TX feedback for this packet */
562 netif_tx_stop_all_queues(pAdapter->dev);
563 pAdapter->isTxSuspended[ac] = VOS_TRUE;
564 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
565 return NETDEV_TX_BUSY;
566 }
567 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
568
569 //Use the skb->cb field to hold the list node information
570 pktNode = (skb_list_node_t *)&skb->cb;
571
572 //Stick the OS packet inside this node.
573 pktNode->skb = skb;
574
575 INIT_LIST_HEAD(&pktNode->anchor);
576
577 //Insert the OS packet into the appropriate AC queue
578 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
579 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
580 &pktNode->anchor, &pktListSize );
581 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
582
583 if ( !VOS_IS_STATUS_SUCCESS( status ) )
584 {
c_hpothu32490782014-03-14 19:14:34 +0530585 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700586 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 kfree_skb(skb);
588 return NETDEV_TX_OK;
589 }
590
591 if ( pktListSize == 1 )
592 {
593 /* In this context we cannot acquire any mutex etc. And to transmit
594 * this packet we need to call SME API. So to take care of this we will
595 * schedule a workqueue
596 */
597 schedule_work(&pPgBkAdapter->monTxWorkQueue);
598 }
599 return NETDEV_TX_OK;
600 }
601
602fail:
c_hpothu32490782014-03-14 19:14:34 +0530603 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700604 "%s: Packet Rcvd at Monitor interface is not proper,"
605 " Dropping the packet",
606 __func__);
607 kfree_skb(skb);
608 return NETDEV_TX_OK;
609}
Jeff Johnson295189b2012-06-20 16:38:30 -0700610/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530611 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 transmitting packets. There are 2 versions of this function. One that uses
613 locked queue and other that uses lockless queues. Both have been retained to
614 do some performance testing
615
616 @param skb : [in] pointer to OS packet (sk_buff)
617 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530618
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 @return : NET_XMIT_DROP if packets are dropped
620 : NET_XMIT_SUCCESS if packet is enqueued succesfully
621 ===========================================================================*/
622int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
623{
624 VOS_STATUS status;
625 WLANTL_ACEnumType ac;
626 sme_QosWmmUpType up;
627 skb_list_node_t *pktNode = NULL;
628 hdd_list_node_t *anchor = NULL;
629 v_SIZE_t pktListSize = 0;
630 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
631 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700632 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700633 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Jeff Johnson295189b2012-06-20 16:38:30 -0700634 v_BOOL_t txSuspended = VOS_FALSE;
635
636 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
637
Ravi Joshif9520d62013-10-18 04:11:46 -0700638 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530639 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700640 "%s is called when netif TX %d is disabled",
641 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530642 return NETDEV_TX_BUSY;
643 }
644
Ravi Joshicc57ed42013-10-12 16:31:25 -0700645 //Get TL AC corresponding to Qdisc queue index/AC.
646 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
647
648 if (WLAN_HDD_IBSS == pAdapter->device_mode)
Shailender Karmuchia734f332013-04-19 14:02:48 -0700649 {
650 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
651
Ravi Joshif9520d62013-10-18 04:11:46 -0700652 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
Ravi Joshicc57ed42013-10-12 16:31:25 -0700653 {
c_hpothu32490782014-03-14 19:14:34 +0530654 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700655 "%s: Tx frame in disconnected state in IBSS mode", __func__);
656 ++pAdapter->stats.tx_dropped;
657 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
658 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
659 kfree_skb(skb);
660 return NETDEV_TX_OK;
661 }
662
Shailender Karmuchia734f332013-04-19 14:02:48 -0700663 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
664
665 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
666 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
667 vos_is_macaddr_group(pDestMacAddress)))
668 {
669 STAId = IBSS_BROADCAST_STAID;
c_hpothu32490782014-03-14 19:14:34 +0530670 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Ravi Joshif9520d62013-10-18 04:11:46 -0700671 "%s: BC/MC packet", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700672 }
673 else if (STAId == HDD_WLAN_INVALID_STA_ID)
674 {
c_hpothu32490782014-03-14 19:14:34 +0530675 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshif9520d62013-10-18 04:11:46 -0700676 "%s: Received Unicast frame with invalid staID", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700677 ++pAdapter->stats.tx_dropped;
678 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700679 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Shailender Karmuchia734f332013-04-19 14:02:48 -0700680 kfree_skb(skb);
681 return NETDEV_TX_OK;
682 }
683 }
684 else
685 {
686 STAId = pHddStaCtx->conn_info.staId[0];
687 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700688
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530689 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700690 //select_queue call back function
691 up = skb->priority;
692
693 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
694
695#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530696 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700697 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700698#endif // HDD_WMM_DEBUG
699
700 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700701 /*CR 463598,384996*/
702 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
703 *We check for +1 in the logic,to take care of Zero count which
704 *occurs very frequently in low traffic cases */
705 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
706 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700707 /* 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 -0700708 * 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 +0530709 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 -0700710
Ravi Joshi8a934352013-09-25 16:46:58 -0700711 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
712 STAId, ac
713 );
714 if ( !VOS_IS_STATUS_SUCCESS( status ) )
715 {
c_hpothu32490782014-03-14 19:14:34 +0530716 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700717 "%s: WLANTL_STAPktPending() returned error code %d",
718 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700719 ++pAdapter->stats.tx_dropped;
720 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
721 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Ravi Joshi8a934352013-09-25 16:46:58 -0700722 kfree_skb(skb);
723 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
724 return NETDEV_TX_OK;
725 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700726 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 //If we have already reached the max queue size, disable the TX queue
728 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
729 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700730 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
731 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
732 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
733 pAdapter->isTxSuspended[ac] = VOS_TRUE;
734 txSuspended = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700735 }
736
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530737 /* If 3/4th of the max queue size is used then enable the flag.
738 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
739 if (WLANTL_AC_BE == ac)
740 {
741 if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
742 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530743 pAdapter->isVosLowResource = VOS_TRUE;
744 }
745 else
746 {
747 pAdapter->isVosLowResource = VOS_FALSE;
748 }
749 }
750
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530751 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700752 if (VOS_TRUE == txSuspended)
753 {
c_hpothu32490782014-03-14 19:14:34 +0530754 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530755 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700756 __func__, ac );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530757 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700758 }
759
760 //Use the skb->cb field to hold the list node information
761 pktNode = (skb_list_node_t *)&skb->cb;
762
763 //Stick the OS packet inside this node.
764 pktNode->skb = skb;
765
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530766 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700767 pktNode->userPriority = up;
768
769
770 INIT_LIST_HEAD(&pktNode->anchor);
771
772 //Insert the OS packet into the appropriate AC queue
773 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
774 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
775 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
776
777 if ( !VOS_IS_STATUS_SUCCESS( status ) )
778 {
c_hpothu32490782014-03-14 19:14:34 +0530779 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 -0700780 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
781 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
782 ++pAdapter->stats.tx_dropped;
783 kfree_skb(skb);
784 return NETDEV_TX_OK;
785 }
786
787 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
788 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700789 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700790
Kiet Lamf040f472013-11-20 21:15:23 +0530791 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
792 {
793 /* Function which will determine acquire admittance for a
794 * WMM AC is required or not based on psb configuration done
795 * in the framework
796 */
797 hdd_wmm_acquire_access_required(pAdapter, ac);
798 }
799
Jeff Johnson295189b2012-06-20 16:38:30 -0700800 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530801 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
802 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700803 {
804 granted = VOS_TRUE;
805 }
806 else
807 {
808 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530809 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700810 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700811 if ( granted && ( pktListSize == 1 ))
812 {
813 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +0530814 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700815 status = WLANTL_STAPktPending(
816 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
817 STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700818 if ( !VOS_IS_STATUS_SUCCESS( status ) )
819 {
c_hpothu32490782014-03-14 19:14:34 +0530820 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 -0700821
822 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
823 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
824 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
825 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
826 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
827 ++pAdapter->stats.tx_dropped;
828 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
829 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
830 kfree_skb(skb);
831 return NETDEV_TX_OK;
832 }
833 }
834
835 dev->trans_start = jiffies;
836
837 return NETDEV_TX_OK;
838}
839
840/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -0700841 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
842
843 @param pHddStaCtx : [in] pointer to HDD Station Context
844 pMacAddress [in] pointer to Peer Mac address
845 staID [out] pointer to Station Index
846 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
847 ===========================================================================*/
848
849VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
850{
851 v_U8_t idx;
852
853 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
854 {
855 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
856 pMacAddress, sizeof(v_MACADDR_t)))
857 {
858 *staId = pHddStaCtx->conn_info.staId[idx];
859 return VOS_STATUS_SUCCESS;
860 }
861 }
862
863 return VOS_STATUS_E_FAILURE;
864}
865
866/**============================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -0700867 @brief hdd_tx_timeout() - Function called by OS if there is any
868 timeout during transmission. Since HDD simply enqueues packet
869 and returns control to OS right away, this would never be invoked
870
871 @param dev : [in] pointer to Libra network device
872 @return : None
873 ===========================================================================*/
874void hdd_tx_timeout(struct net_device *dev)
875{
Ravi Joshicc57ed42013-10-12 16:31:25 -0700876 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
877 struct netdev_queue *txq;
878 int i = 0;
879
c_hpothub8245442013-11-20 23:41:09 +0530880 if ( NULL == pAdapter )
881 {
c_hpothu32490782014-03-14 19:14:34 +0530882 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530883 FL("pAdapter is NULL"));
884 VOS_ASSERT(0);
885 return;
886 }
887
c_hpothu32490782014-03-14 19:14:34 +0530888 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700889 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700890 //Getting here implies we disabled the TX queues for too long. Queues are
891 //disabled either because of disassociation or low resource scenarios. In
892 //case of disassociation it is ok to ignore this. But if associated, we have
893 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -0700894
c_hpothu32490782014-03-14 19:14:34 +0530895 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700896 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
897 pAdapter->wmm_tx_queue[0].count,
898 pAdapter->wmm_tx_queue[1].count,
899 pAdapter->wmm_tx_queue[2].count,
900 pAdapter->wmm_tx_queue[3].count);
901
c_hpothu32490782014-03-14 19:14:34 +0530902 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700903 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
904 pAdapter->isTxSuspended[0],
905 pAdapter->isTxSuspended[1],
906 pAdapter->isTxSuspended[2],
907 pAdapter->isTxSuspended[3]);
908
909 for (i = 0; i < 8; i++)
910 {
911 txq = netdev_get_tx_queue(dev, i);
c_hpothu32490782014-03-14 19:14:34 +0530912 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700913 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
914 }
915
c_hpothu32490782014-03-14 19:14:34 +0530916 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700917 "carrier state: %d", netif_carrier_ok(dev));
Jeff Johnson295189b2012-06-20 16:38:30 -0700918}
919
920
921/**============================================================================
922 @brief hdd_stats() - Function registered with the Linux OS for
923 device TX/RX statistic
924
925 @param dev : [in] pointer to Libra network device
926
927 @return : pointer to net_device_stats structure
928 ===========================================================================*/
929struct net_device_stats* hdd_stats(struct net_device *dev)
930{
931 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +0530932
933 if ( NULL == pAdapter )
934 {
c_hpothu32490782014-03-14 19:14:34 +0530935 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530936 FL("pAdapter is NULL"));
937 VOS_ASSERT(0);
938 return NULL;
939 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700940
941 return &pAdapter->stats;
942}
943
944
945/**============================================================================
946 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
947 modules in HDD
948
949 @param pAdapter : [in] pointer to adapter context
950 @return : VOS_STATUS_E_FAILURE if any errors encountered
951 : VOS_STATUS_SUCCESS otherwise
952 ===========================================================================*/
953VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
954{
955 VOS_STATUS status = VOS_STATUS_SUCCESS;
956 v_SINT_t i = -1;
957
c_hpothub8245442013-11-20 23:41:09 +0530958 if ( NULL == pAdapter )
959 {
c_hpothu32490782014-03-14 19:14:34 +0530960 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530961 FL("pAdapter is NULL"));
962 VOS_ASSERT(0);
963 return VOS_STATUS_E_FAILURE;
964 }
965
Jeff Johnson295189b2012-06-20 16:38:30 -0700966 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530967 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700968
969 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
970 //Will be zeroed out during alloc
971
972 while (++i != NUM_TX_QUEUES)
973 {
974 pAdapter->isTxSuspended[i] = VOS_FALSE;
975 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
976 }
977
978 return status;
979}
980
981
982/**============================================================================
983 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
984 modules in HDD
985
986 @param pAdapter : [in] pointer to adapter context
987 @return : VOS_STATUS_E_FAILURE if any errors encountered
988 : VOS_STATUS_SUCCESS otherwise
989 ===========================================================================*/
990VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
991{
992 VOS_STATUS status = VOS_STATUS_SUCCESS;
993 v_SINT_t i = -1;
994
c_hpothub8245442013-11-20 23:41:09 +0530995 if ( NULL == pAdapter )
996 {
c_hpothu32490782014-03-14 19:14:34 +0530997 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530998 FL("pAdapter is NULL"));
999 VOS_ASSERT(0);
1000 return VOS_STATUS_E_FAILURE;
1001 }
1002
Jeff Johnson295189b2012-06-20 16:38:30 -07001003 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301004 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301005 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301006 FL("failed to flush tx queues"));
1007
Jeff Johnson295189b2012-06-20 16:38:30 -07001008 while (++i != NUM_TX_QUEUES)
1009 {
1010 //Free up actual list elements in the Tx queue
1011 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1012 }
1013
1014 return status;
1015}
1016
1017
1018/**============================================================================
1019 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1020 modules in HDD
1021
1022 @param pAdapter : [in] pointer to adapter context
1023 @return : VOS_STATUS_E_FAILURE if any errors encountered
1024 : VOS_STATUS_SUCCESS otherwise
1025 ===========================================================================*/
1026VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1027{
1028 return hdd_flush_tx_queues(pAdapter);
1029}
1030
1031
1032/**============================================================================
1033 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1034
1035 @param pVosPacket : [in] pointer to vos packet
1036 @return : VOS_TRUE if the packet is EAPOL
1037 : VOS_FALSE otherwise
1038 ===========================================================================*/
1039
1040v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1041{
1042 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1043 v_BOOL_t fEAPOL = VOS_FALSE;
1044 void *pBuffer = NULL;
1045
1046
1047 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1048 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1049 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1050 {
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08001051 if (pBuffer && vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_802_1_X )
Jeff Johnson295189b2012-06-20 16:38:30 -07001052 {
1053 fEAPOL = VOS_TRUE;
1054 }
1055 }
1056
1057 return fEAPOL;
1058}
1059
1060
1061#ifdef FEATURE_WLAN_WAPI // Need to update this function
1062/**============================================================================
1063 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1064
1065 @param pVosPacket : [in] pointer to vos packet
1066 @return : VOS_TRUE if the packet is WAI
1067 : VOS_FALSE otherwise
1068 ===========================================================================*/
1069
1070v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1071{
1072 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1073 v_BOOL_t fIsWAI = VOS_FALSE;
1074 void *pBuffer = NULL;
1075
1076 // Need to update this function
1077 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1078 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1079
1080 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1081 {
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08001082 if (pBuffer && vos_be16_to_cpu( *((unsigned short*)pBuffer)) == HDD_ETHERTYPE_WAI)
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 {
1084 fIsWAI = VOS_TRUE;
1085 }
1086 }
1087
1088 return fIsWAI;
1089}
1090#endif /* FEATURE_WLAN_WAPI */
1091
1092/**============================================================================
1093 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1094 to indicate that a packet has been transmitted across the SDIO bus
1095 succesfully. OS packet resources can be released after this cbk.
1096
1097 @param vosContext : [in] pointer to VOS context
1098 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1099 @param vosStatusIn : [in] status of the transmission
1100
1101 @return : VOS_STATUS_E_FAILURE if any errors encountered
1102 : VOS_STATUS_SUCCESS otherwise
1103 ===========================================================================*/
1104VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1105 vos_pkt_t *pVosPacket,
1106 VOS_STATUS vosStatusIn )
1107{
1108 VOS_STATUS status = VOS_STATUS_SUCCESS;
1109 hdd_adapter_t *pAdapter = NULL;
1110 hdd_context_t *pHddCtx = NULL;
1111 void* pOsPkt = NULL;
1112
1113 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1114 {
c_hpothu32490782014-03-14 19:14:34 +05301115 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301116 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001117 return VOS_STATUS_E_FAILURE;
1118 }
1119
1120 //Return the skb to the OS
1121 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301122 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001123 {
1124 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301125 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301126 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001127 vos_pkt_return_packet( pVosPacket );
1128 return VOS_STATUS_E_FAILURE;
1129 }
1130
1131 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001132 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001133 //Get the Adapter context.
1134 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Agarwal Ashish971c2882013-10-30 20:11:12 +05301135 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07001136 {
c_hpothu32490782014-03-14 19:14:34 +05301137 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301138 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001139 }
1140 else
1141 {
1142 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1143 }
1144
1145 kfree_skb((struct sk_buff *)pOsPkt);
1146
1147 //Return the VOS packet resources.
1148 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301149 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001150 {
c_hpothu32490782014-03-14 19:14:34 +05301151 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301152 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001153 }
1154
1155 return status;
1156}
1157
1158
1159/**============================================================================
1160 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1161 fetch a packet for transmission.
1162
1163 @param vosContext : [in] pointer to VOS context
1164 @param staId : [in] Station for which TL is requesting a pkt
1165 @param ac : [in] access category requested by TL
1166 @param pVosPacket : [out] pointer to VOS packet packet pointer
1167 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1168
1169 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1170 : VOS_STATUS_E_FAILURE if any errors encountered
1171 : VOS_STATUS_SUCCESS otherwise
1172 ===========================================================================*/
1173VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1174 v_U8_t *pStaId,
1175 WLANTL_ACEnumType ac,
1176 vos_pkt_t **ppVosPacket,
1177 WLANTL_MetaInfoType *pPktMetaInfo )
1178{
1179 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1180 hdd_adapter_t *pAdapter = NULL;
1181 hdd_context_t *pHddCtx = NULL;
1182 hdd_list_node_t *anchor = NULL;
1183 skb_list_node_t *pktNode = NULL;
1184 struct sk_buff *skb = NULL;
1185 vos_pkt_t *pVosPacket = NULL;
1186 v_MACADDR_t* pDestMacAddress = NULL;
1187 v_TIME_t timestamp;
1188 WLANTL_ACEnumType newAc;
1189 v_SIZE_t size = 0;
1190 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001191 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001192
1193 //Sanity check on inputs
1194 if ( ( NULL == vosContext ) ||
1195 ( NULL == pStaId ) ||
1196 ( NULL == ppVosPacket ) ||
1197 ( NULL == pPktMetaInfo ) )
1198 {
c_hpothu32490782014-03-14 19:14:34 +05301199 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301200 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001201 return VOS_STATUS_E_FAILURE;
1202 }
1203
1204 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001205 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 if(pHddCtx == NULL)
1207 {
c_hpothu32490782014-03-14 19:14:34 +05301208 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301209 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001210 return VOS_STATUS_E_FAILURE;
1211 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001212 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001213 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001214 {
c_hpothu32490782014-03-14 19:14:34 +05301215 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301216 FL("pAdapter is NULL %u"), *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001217 VOS_ASSERT(0);
1218 return VOS_STATUS_E_FAILURE;
1219 }
1220
1221 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1222
1223 *ppVosPacket = NULL;
1224
1225 //Make sure the AC being asked for is sane
1226 if( ac >= WLANTL_MAX_AC || ac < 0)
1227 {
c_hpothu32490782014-03-14 19:14:34 +05301228 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301229 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 return VOS_STATUS_E_FAILURE;
1231 }
1232
1233 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1234
1235#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301236 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301237 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001238#endif // HDD_WMM_DEBUG
1239
1240 // We find an AC with packets
1241 // or we determine we have no more packets to send
1242 // HDD is not allowed to change AC.
1243
1244 // has this AC been admitted? or
1245 // To allow EAPOL packets when not authenticated
1246 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1247 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1248 {
1249 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1250#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301251 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001252 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001253#endif // HDD_WMM_DEBUG
1254 return VOS_STATUS_E_FAILURE;
1255 }
1256
1257 // do we have any packets pending in this AC?
1258 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1259 if( size > 0 )
1260 {
1261 // yes, so process it
1262#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301263 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001264 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001265#endif // HDD_WMM_DEBUG
1266 }
1267 else
1268 {
1269 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1270#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301271 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001272 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001273#endif // HDD_WMM_DEBUG
1274 return VOS_STATUS_E_FAILURE;
1275 }
1276
1277 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1278 //This simplifies the locking and unlocking of Tx queue
1279 status = vos_pkt_wrap_data_packet( &pVosPacket,
1280 VOS_PKT_TYPE_TX_802_3_DATA,
1281 NULL, //OS Pkt is not being passed
1282 hdd_tx_low_resource_cbk,
1283 pAdapter );
1284
1285 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1286 {
1287 //Remember VOS is in a low resource situation
1288 pAdapter->isVosOutOfResource = VOS_TRUE;
1289 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05301290 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 -07001291 //TL will now think we have no more packets in this AC
1292 return VOS_STATUS_E_FAILURE;
1293 }
1294
1295 //Remove the packet from the queue
1296 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1297 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1298 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1299
1300 if(VOS_STATUS_SUCCESS == status)
1301 {
1302 //If success then we got a valid packet from some AC
1303 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1304 skb = pktNode->skb;
1305 }
1306 else
1307 {
1308 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05301309 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001310 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001311 vos_pkt_return_packet(pVosPacket);
1312 return VOS_STATUS_E_FAILURE;
1313 }
1314
1315 //Attach skb to VOS packet.
1316 status = vos_pkt_set_os_packet( pVosPacket, skb );
1317 if (status != VOS_STATUS_SUCCESS)
1318 {
c_hpothu32490782014-03-14 19:14:34 +05301319 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 vos_pkt_return_packet(pVosPacket);
1321 ++pAdapter->stats.tx_dropped;
1322 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1323 kfree_skb(skb);
1324 return VOS_STATUS_E_FAILURE;
1325 }
1326
1327 //Just being paranoid. To be removed later
1328 if(pVosPacket == NULL)
1329 {
c_hpothu32490782014-03-14 19:14:34 +05301330 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 -07001331 ++pAdapter->stats.tx_dropped;
1332 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1333 kfree_skb(skb);
1334 return VOS_STATUS_E_FAILURE;
1335 }
1336
Chilam NG571c65a2013-01-19 12:27:36 +05301337#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001338 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05301339 {
1340 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301341 u8 mac[6];
1342
Hoonki Lee387663d2013-02-05 18:08:43 -08001343 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301344
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001345 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05301346 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301347 "broadcast packet, not adding to peer list");
1348 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1349 mac, 6) != 0) {
c_hpothu32490782014-03-14 19:14:34 +05301350 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001351 "extract mac: " MAC_ADDRESS_STR,
1352 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05301353
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001354 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301355 } else {
c_hpothu32490782014-03-14 19:14:34 +05301356 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301357 "packet da is bssid, not adding to peer list");
1358 }
1359 }
1360#endif
1361
Jeff Johnson295189b2012-06-20 16:38:30 -07001362 //Return VOS packet to TL;
1363 *ppVosPacket = pVosPacket;
1364
1365 //Fill out the meta information needed by TL
1366 //FIXME This timestamp is really the time stamp of wrap_data_packet
1367 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1368 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1369
1370 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1371 pPktMetaInfo->ucIsEapol = 0;
1372 else
1373 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1374
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001375 if (pHddCtx->cfg_ini->gEnableDebugLog)
1376 {
1377 proto_type = vos_pkt_get_proto_type(skb,
1378 pHddCtx->cfg_ini->gEnableDebugLog);
1379 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1380 {
c_hpothu32490782014-03-14 19:14:34 +05301381 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001382 "STA TX EAPOL");
1383 }
1384 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1385 {
c_hpothu32490782014-03-14 19:14:34 +05301386 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001387 "STA TX DHCP");
1388 }
1389 }
1390
Jeff Johnson295189b2012-06-20 16:38:30 -07001391#ifdef FEATURE_WLAN_WAPI
1392 // Override usIsEapol value when its zero for WAPI case
1393 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
1394#endif /* FEATURE_WLAN_WAPI */
1395
1396 if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) ||
1397 (!pAdapter->hddWmmStatus.wmmQap))
1398 {
1399 // either we don't want QoS or the AP doesn't support QoS
1400 pPktMetaInfo->ucUP = 0;
1401 pPktMetaInfo->ucTID = 0;
1402 }
1403 else
1404 {
1405 /* 1. Check if ACM is set for this AC
1406 * 2. If set, check if this AC had already admitted
1407 * 3. If not already admitted, downgrade the UP to next best UP */
1408 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
1409 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid)
1410 {
1411 pPktMetaInfo->ucUP = pktNode->userPriority;
1412 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1413 }
1414 else
1415 {
1416 //Downgrade the UP
1417 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1418 newAc = WLANTL_AC_BK;
1419 for (i=ac-1; i>0; i--)
1420 {
1421 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1422 {
1423 newAc = i;
1424 break;
1425 }
1426 }
1427 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1428 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
c_hpothu32490782014-03-14 19:14:34 +05301429 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 -07001430 }
1431 }
1432
1433 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1434 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1435 if ( 1 < size )
1436 {
1437 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1438 }
1439 else
1440 {
1441 pPktMetaInfo->bMorePackets = 0;
1442 }
1443
1444 //Extract the destination address from ethernet frame
1445 pDestMacAddress = (v_MACADDR_t*)skb->data;
1446 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1447 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1448
1449
1450
1451 // if we are in a backpressure situation see if we can turn the hose back on
1452 if ( (pAdapter->isTxSuspended[ac]) &&
1453 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1454 {
1455 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1456 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05301457 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001458 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001459 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1460 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1461 skb_get_queue_mapping(skb) ));
1462 }
1463
1464
1465 // We're giving the packet to TL so consider it transmitted from
1466 // a statistics perspective. We account for it here instead of
1467 // when the packet is returned for two reasons. First, TL will
1468 // manipulate the skb to the point where the len field is not
1469 // accurate, leading to inaccurate byte counts if we account for
1470 // it later. Second, TL does not provide any feedback as to
1471 // whether or not the packet was successfully sent over the air,
1472 // so the packet counts will be the same regardless of where we
1473 // account for them
1474 pAdapter->stats.tx_bytes += skb->len;
1475 ++pAdapter->stats.tx_packets;
1476 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1477 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1478
Leo Chang50bbd252013-04-25 14:58:01 -07001479 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1480 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001481 {
1482 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1483 {
c_hpothu32490782014-03-14 19:14:34 +05301484 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001485 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001486 return VOS_STATUS_E_FAILURE;
1487 }
1488 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1489 {
1490 if(0 == pHddCtx->tmInfo.txFrameCount)
1491 {
1492 /* Just recovered from sleep timeout */
1493 pHddCtx->tmInfo.lastOpenTs = timestamp;
1494 }
1495
Leo Chang50bbd252013-04-25 14:58:01 -07001496 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1497 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001498 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1499 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001500 /* During TX open duration, TX frame count is larger than threshold
1501 * Block TX during Sleep time */
1502 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001503 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001504 pHddCtx->tmInfo.lastblockTs = timestamp;
1505 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1506 {
1507 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1508 }
1509 }
1510 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1511 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1512 {
1513 /* During TX open duration, TX frame count is less than threshold
1514 * Reset count and timestamp to prepare next cycle */
1515 pHddCtx->tmInfo.lastOpenTs = timestamp;
1516 pHddCtx->tmInfo.txFrameCount = 0;
1517 }
1518 else
1519 {
1520 /* Do Nothing */
1521 }
1522 pHddCtx->tmInfo.txFrameCount++;
1523 }
1524 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1525 }
1526
1527
1528#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301529 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 -07001530#endif // HDD_WMM_DEBUG
1531
1532 return status;
1533}
1534
1535
1536/**============================================================================
1537 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1538 case where VOS packets are not available at the time of the call to get
1539 packets. This callback function is invoked by VOS when packets are
1540 available.
1541
1542 @param pVosPacket : [in] pointer to VOS packet
1543 @param userData : [in] opaque user data that was passed initially
1544
1545 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1546 : VOS_STATUS_SUCCESS otherwise
1547 =============================================================================*/
1548VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1549 v_VOID_t *userData )
1550{
1551 VOS_STATUS status;
1552 v_SINT_t i = 0;
1553 v_SIZE_t size = 0;
1554 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1555
Agarwal Ashish971c2882013-10-30 20:11:12 +05301556 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001557 {
c_hpothu32490782014-03-14 19:14:34 +05301558 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301559 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001560 return VOS_STATUS_E_FAILURE;
1561 }
1562
1563 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1564 //situation. Here we will only signal TL that there is a pending data for a STA.
1565 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1566 vos_pkt_return_packet( pVosPacket );
1567
1568 pAdapter->isVosOutOfResource = VOS_FALSE;
1569
1570 //Indicate to TL that there is pending data if a queue is non empty
1571 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1572 {
1573 size = 0;
1574 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1575 if ( size > 0 )
1576 {
1577 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1578 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1579 (WLANTL_ACEnumType)i );
1580 if( !VOS_IS_STATUS_SUCCESS( status ) )
1581 {
c_hpothu32490782014-03-14 19:14:34 +05301582 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301583 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001584 }
1585 }
1586 }
1587
1588 return VOS_STATUS_SUCCESS;
1589}
1590
1591
1592/**============================================================================
1593 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1594 TL will call this to notify the HDD when one or more packets were
1595 received for a registered STA.
1596
1597 @param vosContext : [in] pointer to VOS context
1598 @param pVosPacketChain : [in] pointer to VOS packet chain
1599 @param staId : [in] Station Id
1600 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1601
1602 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1603 : VOS_STATUS_SUCCESS otherwise
1604 ===========================================================================*/
1605VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1606 vos_pkt_t *pVosPacketChain,
1607 v_U8_t staId,
1608 WLANTL_RxMetaInfoType* pRxMetaInfo )
1609{
1610 hdd_adapter_t *pAdapter = NULL;
1611 hdd_context_t *pHddCtx = NULL;
1612 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1613 int rxstat;
1614 struct sk_buff *skb = NULL;
1615 vos_pkt_t* pVosPacket;
1616 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001617 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001618
1619 //Sanity check on inputs
1620 if ( ( NULL == vosContext ) ||
1621 ( NULL == pVosPacketChain ) ||
1622 ( NULL == pRxMetaInfo ) )
1623 {
c_hpothu32490782014-03-14 19:14:34 +05301624 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301625 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001626 return VOS_STATUS_E_FAILURE;
1627 }
1628
Kiet Lam3c2ee302014-03-23 23:23:22 -07001629 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001630 if ( NULL == pHddCtx )
1631 {
c_hpothu32490782014-03-14 19:14:34 +05301632 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301633 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001634 return VOS_STATUS_E_FAILURE;
1635 }
1636
1637 pAdapter = pHddCtx->sta_to_adapter[staId];
1638 if( NULL == pAdapter )
1639 {
c_hpothu32490782014-03-14 19:14:34 +05301640 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: pAdapter is Null for staId %u",
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05301641 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001642 return VOS_STATUS_E_FAILURE;
1643 }
1644
1645 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1646
1647 // walk the chain until all are processed
1648 pVosPacket = pVosPacketChain;
1649 do
1650 {
1651 // get the pointer to the next packet in the chain
1652 // (but don't unlink the packet since we free the entire chain later)
1653 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1654
1655 // both "success" and "empty" are acceptable results
1656 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1657 {
1658 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301659 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301660 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 return VOS_STATUS_E_FAILURE;
1662 }
1663
1664 // Extract the OS packet (skb).
1665 // Tell VOS to detach the OS packet from the VOS packet
1666 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1667 if(!VOS_IS_STATUS_SUCCESS( status ))
1668 {
1669 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301670 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301671 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 return VOS_STATUS_E_FAILURE;
1673 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001674
1675 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1676 {
c_hpothu32490782014-03-14 19:14:34 +05301677 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07001678 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
1679 return eHAL_STATUS_FAILURE;
1680 }
1681
Chilam Ng1279e232013-01-25 15:06:52 -08001682#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001683 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
1684 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08001685 {
1686 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08001687 u8 mac[6];
1688
Hoonki Lee387663d2013-02-05 18:08:43 -08001689 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08001690
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001691 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05301692 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08001693 "rx broadcast packet, not adding to peer list");
1694 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1695 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001696 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05301697 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001698 "rx extract mac:" MAC_ADDRESS_STR,
1699 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301700 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05301701 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
1702 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001703 {
1704 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05301705 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001706 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
1707 }
Chilam Ng1279e232013-01-25 15:06:52 -08001708 } else {
c_hpothu32490782014-03-14 19:14:34 +05301709 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08001710 "rx packet sa is bssid, not adding to peer list");
1711 }
1712 }
1713#endif
1714
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001715 if (pHddCtx->cfg_ini->gEnableDebugLog)
1716 {
1717 proto_type = vos_pkt_get_proto_type(skb,
1718 pHddCtx->cfg_ini->gEnableDebugLog);
1719 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1720 {
c_hpothu32490782014-03-14 19:14:34 +05301721 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001722 "STA RX EAPOL");
1723 }
1724 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1725 {
c_hpothu32490782014-03-14 19:14:34 +05301726 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001727 "STA RX DHCP");
1728 }
1729 }
1730
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 skb->dev = pAdapter->dev;
1732 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001733 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001734 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1735 ++pAdapter->stats.rx_packets;
1736 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001737#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001738#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001739 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001740#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001741#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001742 rxstat = netif_rx_ni(skb);
1743 if (NET_RX_SUCCESS == rxstat)
1744 {
1745 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001746 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001747 }
1748 else
1749 {
1750 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1751 }
1752 // now process the next packet in the chain
1753 pVosPacket = pNextVosPacket;
1754
1755 } while (pVosPacket);
1756
1757 //Return the entire VOS packet chain to the resource pool
1758 status = vos_pkt_return_packet( pVosPacketChain );
1759 if(!VOS_IS_STATUS_SUCCESS( status ))
1760 {
c_hpothu32490782014-03-14 19:14:34 +05301761 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001762 }
1763
1764 pAdapter->dev->last_rx = jiffies;
1765
1766 return status;
1767}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001768/**============================================================================
1769 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
1770 Enable/Disable split scan based on TX and RX traffic.
1771 @param HddContext : [in] pointer to Hdd context
1772 @return : None
1773 ===========================================================================*/
1774void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
1775{
1776 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1777 hdd_adapter_t *pAdapter = NULL;
1778 hdd_station_ctx_t *pHddStaCtx = NULL;
1779 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
1780 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
1781 VOS_STATUS status;
1782 v_U8_t staId = 0;
1783 v_U8_t fconnected = 0;
1784
c_hpothub8245442013-11-20 23:41:09 +05301785 if (NULL == phddctx)
1786 {
c_hpothu32490782014-03-14 19:14:34 +05301787 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301788 FL("phddctx is NULL"));
1789 VOS_ASSERT(0);
1790 return;
1791 }
1792
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001793 if (!cfg_param->dynSplitscan)
1794 {
c_hpothu32490782014-03-14 19:14:34 +05301795 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001796 "%s: Error : Dynamic split scan is not Enabled : %d",
1797 __func__, pHddCtx->cfg_ini->dynSplitscan);
1798 return;
1799 }
1800
1801 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1802 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1803 {
1804 pAdapter = pAdapterNode->pAdapter;
1805
1806 if ( pAdapter )
1807 {
c_hpothu32490782014-03-14 19:14:34 +05301808 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001809 "%s: Adapter with device mode %d exists",
1810 __func__, pAdapter->device_mode);
1811
1812 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1813 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
1814 {
1815 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1816 if ((eConnectionState_Associated ==
1817 pHddStaCtx->conn_info.connState) &&
1818 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
1819 {
1820 fconnected = TRUE;
1821 }
1822 }
1823 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1824 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
1825 {
1826 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1827 {
1828 if ((pAdapter->aStaInfo[staId].isUsed) &&
1829 (WLANTL_STA_AUTHENTICATED ==
1830 pAdapter->aStaInfo[staId].tlSTAState))
1831 {
1832 fconnected = TRUE;
1833 }
1834 }
1835 }
1836 if ( fconnected )
1837 {
c_hpothu32490782014-03-14 19:14:34 +05301838 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001839 "%s: One of the interface is connected check for scan",
1840 __func__);
c_hpothu32490782014-03-14 19:14:34 +05301841 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001842 "%s: pkt_tx_count: %d, pkt_rx_count: %d", __func__,
1843 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
1844 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count);
1845
1846 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1847 cfg_param->trafficMntrTmrForSplitScan);
1848 //Check for the previous statistics count
1849 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
1850 cfg_param->txRxThresholdForSplitScan) ||
1851 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
1852 cfg_param->txRxThresholdForSplitScan) ||
1853 pHddCtx->drvr_miracast)
1854 {
1855 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
1856 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
1857
1858 if (!pHddCtx->issplitscan_enabled)
1859 {
1860 pHddCtx->issplitscan_enabled = TRUE;
1861 sme_enable_disable_split_scan(
1862 WLAN_HDD_GET_HAL_CTX(pAdapter),
1863 cfg_param->nNumStaChanCombinedConc,
1864 cfg_param->nNumP2PChanCombinedConc);
1865 }
1866 return;
1867 }
1868 else
1869 {
1870 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
1871 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
1872 }
1873 fconnected = FALSE;
1874 }
1875 }
1876 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
1877 pAdapterNode = pNext;
1878 }
1879
1880 if (pHddCtx->issplitscan_enabled)
1881 {
c_hpothu32490782014-03-14 19:14:34 +05301882 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001883 "%s: Disable split scan", __func__);
1884 pHddCtx->issplitscan_enabled = FALSE;
1885 sme_enable_disable_split_scan(
1886 pHddCtx->hHal,
1887 SME_DISABLE_SPLIT_SCAN,
1888 SME_DISABLE_SPLIT_SCAN);
1889 }
1890 return;
1891}
Jeff Johnson295189b2012-06-20 16:38:30 -07001892