blob: 95a24e3eb46f5fca125132fe0ba4678e604cbce7 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam3c2ee302014-03-23 23:23:22 -07002 * Copyright (c) 2012-2013 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{
Kiet Lam3c2ee302014-03-23 23:23:22 -070093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
94 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
95 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
96 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
97 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
98 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
99 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700100
Kiet Lam3c2ee302014-03-23 23:23:22 -0700101 VOS_TRACE( VOS_MODULE_ID_HDD, 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]);
Kiet Lam3c2ee302014-03-23 23:23:22 -0700104 VOS_TRACE( VOS_MODULE_ID_HDD, 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 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700122 VOS_TRACE( VOS_MODULE_ID_HDD, 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)
Kiet Lam3c2ee302014-03-23 23:23:22 -0700134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700135 else
Kiet Lam3c2ee302014-03-23 23:23:22 -0700136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700137
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700138 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700139 if (status != VOS_STATUS_SUCCESS)
Kiet Lam3c2ee302014-03-23 23:23:22 -0700140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700141 else
Kiet Lam3c2ee302014-03-23 23:23:22 -0700142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700143
144 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
145 if (status != VOS_STATUS_SUCCESS)
Kiet Lam3c2ee302014-03-23 23:23:22 -0700146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700147 else
Kiet Lam3c2ee302014-03-23 23:23:22 -0700148 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700149
150 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
151 &dummyPacket,
152 staId,
153 &pktRxMetaInfo);
154 if (status != VOS_STATUS_SUCCESS)
Kiet Lam3c2ee302014-03-23 23:23:22 -0700155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700156 else
Kiet Lam3c2ee302014-03-23 23:23:22 -0700157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700158
159}
160#endif
161
162
163/**============================================================================
164 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
165
166 @param pAdapter : [in] pointer to adapter context
167 @return : VOS_STATUS_E_FAILURE if any errors encountered
168 : VOS_STATUS_SUCCESS otherwise
169 ===========================================================================*/
170static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
171{
172 VOS_STATUS status = VOS_STATUS_SUCCESS;
173 v_SINT_t i = -1;
174 hdd_list_node_t *anchor = NULL;
175 skb_list_node_t *pktNode = NULL;
176 struct sk_buff *skb = NULL;
177
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530178 pAdapter->isVosLowResource = VOS_FALSE;
179
Jeff Johnson295189b2012-06-20 16:38:30 -0700180 while (++i != NUM_TX_QUEUES)
181 {
182 //Free up any packets in the Tx queue
183 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
184 while (true)
185 {
186 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
187 if(VOS_STATUS_E_EMPTY != status)
188 {
189 pktNode = list_entry(anchor, skb_list_node_t, anchor);
190 skb = pktNode->skb;
191 //TODO
192 //++pAdapter->stats.tx_dropped;
193 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
194 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
195 kfree_skb(skb);
196 continue;
197 }
198 break;
199 }
200 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
201 // backpressure is no longer in effect
202 pAdapter->isTxSuspended[i] = VOS_FALSE;
203 }
204
205 return status;
206}
207
Ravi Joshif9520d62013-10-18 04:11:46 -0700208/**============================================================================
209 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
210 in IBSS mode
211
212 @param pAdapter : [in] pointer to adapter context
213 : [in] Staion Id
214 @return : VOS_STATUS_E_FAILURE if any errors encountered
215 : VOS_STATUS_SUCCESS otherwise
216 ===========================================================================*/
217void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
218{
219 v_U8_t i;
Ravi Joshi41914632013-10-21 23:02:21 -0700220 v_SIZE_t size = 0;
Ravi Joshif9520d62013-10-18 04:11:46 -0700221 v_U8_t skbStaIdx;
Ravi Joshi41914632013-10-21 23:02:21 -0700222 skb_list_node_t *pktNode = NULL;
223 hdd_list_node_t *tmp = NULL, *next = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700224 struct netdev_queue *txq;
Ravi Joshi41914632013-10-21 23:02:21 -0700225 struct sk_buff *skb = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700226
c_hpothub8245442013-11-20 23:41:09 +0530227 if (NULL == pAdapter)
228 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700229 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530230 FL("pAdapter is NULL %u"), STAId);
231 VOS_ASSERT(0);
232 return;
233 }
234
Ravi Joshif9520d62013-10-18 04:11:46 -0700235 for (i = 0; i < NUM_TX_QUEUES; i++)
236 {
237 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
238
239 if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) )
240 {
241 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
242 continue;
243 }
244
245 /* Iterate through the queue and identify the data for STAId */
Ravi Joshi41914632013-10-21 23:02:21 -0700246 list_for_each_safe(tmp, next, &pAdapter->wmm_tx_queue[i].anchor)
Ravi Joshif9520d62013-10-18 04:11:46 -0700247 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700248 pktNode = list_entry(tmp, skb_list_node_t, anchor);
249 if (pktNode != NULL)
250 {
251 skb = pktNode->skb;
252
253 /* Get the STAId from data */
254 skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
255 if (skbStaIdx == STAId)
256 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700257 /* Data for STAId is freed along with the queue node */
258 kfree_skb(skb);
259 list_del(tmp);
Ravi Joshif9520d62013-10-18 04:11:46 -0700260
261 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
262 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
263 pAdapter->wmm_tx_queue[i].count--;
264 }
265 }
266 }
267
268 /* Restart the queue only-if suspend and the queue was flushed */
Ravi Joshi41914632013-10-21 23:02:21 -0700269 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
Ravi Joshif9520d62013-10-18 04:11:46 -0700270 txq = netdev_get_tx_queue(pAdapter->dev, i);
Ravi Joshi41914632013-10-21 23:02:21 -0700271
272 if (VOS_TRUE == pAdapter->isTxSuspended[i] &&
273 size <= HDD_TX_QUEUE_LOW_WATER_MARK &&
274 netif_tx_queue_stopped(txq) )
Ravi Joshif9520d62013-10-18 04:11:46 -0700275 {
276 netif_tx_start_queue(txq);
Ravi Joshi41914632013-10-21 23:02:21 -0700277 pAdapter->isTxSuspended[i] = VOS_FALSE;
278 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressured;
279 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressuredAC[i];
Ravi Joshif9520d62013-10-18 04:11:46 -0700280 }
281
282 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
283 }
284}
285
Jeff Johnson295189b2012-06-20 16:38:30 -0700286static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
287{
288 skb_list_node_t *pktNode = NULL;
289 struct sk_buff *skb = NULL;
290 v_SIZE_t size = 0;
291 WLANTL_ACEnumType ac = 0;
292 VOS_STATUS status = VOS_STATUS_E_FAILURE;
293 hdd_list_node_t *anchor = NULL;
294
c_hpothu77731d42014-01-23 13:59:03 +0530295 if (NULL == pAdapter)
296 {
297 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
298 FL("pAdapter is NULL"));
299 VOS_ASSERT(0);
300 return NULL;
301 }
302
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 // do we have any packets pending in this AC?
304 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
305 if( size == 0 )
306 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700308 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700309 return NULL;
310 }
311
312 //Remove the packet from the queue
313 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
314 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
315 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
316
317 if(VOS_STATUS_SUCCESS == status)
318 {
319 //If success then we got a valid packet from some AC
320 pktNode = list_entry(anchor, skb_list_node_t, anchor);
321 skb = pktNode->skb;
322 }
323 else
324 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700327 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700328
329 return NULL;
330 }
331
332 // if we are in a backpressure situation see if we can turn the hose back on
333 if ( (pAdapter->isTxSuspended[ac]) &&
334 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
335 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700337 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 pAdapter->isTxSuspended[ac] = VOS_FALSE;
339 /* Enable Queues which we have disabled earlier */
340 netif_tx_start_all_queues( pAdapter->dev );
341 }
342
343 return skb;
344}
345
346void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
347{
348 hdd_cfg80211_state_t *cfgState;
349 struct sk_buff* skb;
350 hdd_adapter_t* pMonAdapter = NULL;
351 struct ieee80211_hdr *hdr;
352
353 if (pAdapter == NULL )
354 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700355 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530356 FL("pAdapter is NULL"));
357 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700358 return;
359 }
360
361 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
362
363 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
364
365 if( NULL != cfgState->buf )
366 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700368 "%s: Already one MGMT packet Tx going on", __func__);
369 return;
370 }
371
372 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
373
374 if (NULL == skb)
375 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700377 "%s: No Packet Pending", __func__);
378 return;
379 }
380
381 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
382 if( cfgState->buf == NULL )
383 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 "%s: Failed to Allocate memory", __func__);
386 goto fail;
387 }
388
389 cfgState->len = skb->len;
390
391 vos_mem_copy( cfgState->buf, skb->data, skb->len);
392
393 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800394 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700395
396 hdr = (struct ieee80211_hdr *)skb->data;
397 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
398 == HDD_FRAME_TYPE_MGMT )
399 {
400 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
401 == HDD_FRAME_SUBTYPE_DEAUTH )
402 {
403 hdd_softap_sta_deauth( pAdapter, hdr->addr1 );
404 goto mgmt_handled;
405 }
406 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
407 == HDD_FRAME_SUBTYPE_DISASSOC )
408 {
409 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
410 goto mgmt_handled;
411 }
412 }
Kiet Lam3c2ee302014-03-23 23:23:22 -0700413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700414 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
415
Jeff Johnson43971f52012-07-17 12:26:56 -0700416 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700417 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700418 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700419 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700421 "%s: WLANSAP_SendAction returned fail", __func__);
422 hdd_sendActionCnf( pAdapter, FALSE );
423 }
424 return;
425
426mgmt_handled:
427 hdd_sendActionCnf( pAdapter, TRUE );
428 return;
429fail:
430 kfree_skb(pAdapter->skb_to_tx);
431 pAdapter->skb_to_tx = NULL;
432 return;
433}
434
435void hdd_mon_tx_work_queue(struct work_struct *work)
436{
437 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
438 hdd_mon_tx_mgmt_pkt(pAdapter);
439}
440
441int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
442{
443 v_U16_t rt_hdr_len;
444 struct ieee80211_hdr *hdr;
445 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
446 struct ieee80211_radiotap_header *rtap_hdr =
447 (struct ieee80211_radiotap_header *)skb->data;
448
449 /*Supplicant sends the EAPOL packet on monitor interface*/
450 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
451 if(pPgBkAdapter == NULL)
452 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
455 __func__);
456 goto fail; /* too short to be possibly valid */
457 }
458
459 /* check if toal skb length is greater then radio tab header length of not */
460 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
461 goto fail; /* too short to be possibly valid */
462
463 /* check if radio tap header version is correct or not */
464 if (unlikely(rtap_hdr->it_version))
465 goto fail; /* only version 0 is supported */
466
467 /*Strip off the radio tap header*/
468 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
469
470 /* check if skb length if greator then total radio tap header length ot not*/
471 if (unlikely(skb->len < rt_hdr_len))
472 goto fail;
473
474 /* Update the trans_start for this netdev */
475 dev->trans_start = jiffies;
476 /*
477 * fix up the pointers accounting for the radiotap
478 * header still being in there.
479 */
480 skb_set_mac_header(skb, rt_hdr_len);
481 skb_set_network_header(skb, rt_hdr_len);
482 skb_set_transport_header(skb, rt_hdr_len);
483
484 /* Pull rtap header out of the skb */
485 skb_pull(skb, rt_hdr_len);
486
487 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
488 * radio tap header and 802.11 header starts
489 */
490 hdr = (struct ieee80211_hdr *)skb->data;
491
492 /* Send data frames through the normal Data path. In this path we will
493 * conver rcvd 802.11 packet to 802.3 packet */
494 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
495 {
496 v_U8_t da[6];
497 v_U8_t sa[6];
498
499 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
500 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
501
502 /* Pull 802.11 MAC header */
503 skb_pull(skb, HDD_80211_HEADER_LEN);
504
505 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
506 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
507 {
508 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
509 }
510
511 /* Pull LLC header */
512 skb_pull(skb, HDD_LLC_HDR_LEN);
513
514 /* Create space for Ethernet header */
515 skb_push(skb, HDD_MAC_HDR_SIZE*2);
516 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
517 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
518
519 /* Only EAPOL Data packets are allowed through monitor interface */
520 if (vos_be16_to_cpu(
521 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
522 != HDD_ETHERTYPE_802_1_X)
523 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700525 "%s: Not a Eapol packet. Drop this frame", __func__);
526 //If not EAPOL frames, drop them.
527 kfree_skb(skb);
528 return NETDEV_TX_OK;
529 }
530
531 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
532
533 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
534 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
535 }
536 else
537 {
538 VOS_STATUS status;
539 WLANTL_ACEnumType ac = 0;
540 skb_list_node_t *pktNode = NULL;
541 v_SIZE_t pktListSize = 0;
542
543 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
544 //If we have already reached the max queue size, disable the TX queue
545 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
546 {
547 /* We want to process one packet at a time, so lets disable all TX queues
548 * and re-enable the queues once we get TX feedback for this packet */
549 netif_tx_stop_all_queues(pAdapter->dev);
550 pAdapter->isTxSuspended[ac] = VOS_TRUE;
551 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
552 return NETDEV_TX_BUSY;
553 }
554 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
555
556 //Use the skb->cb field to hold the list node information
557 pktNode = (skb_list_node_t *)&skb->cb;
558
559 //Stick the OS packet inside this node.
560 pktNode->skb = skb;
561
562 INIT_LIST_HEAD(&pktNode->anchor);
563
564 //Insert the OS packet into the appropriate AC queue
565 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
566 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
567 &pktNode->anchor, &pktListSize );
568 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
569
570 if ( !VOS_IS_STATUS_SUCCESS( status ) )
571 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700573 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700574 kfree_skb(skb);
575 return NETDEV_TX_OK;
576 }
577
578 if ( pktListSize == 1 )
579 {
580 /* In this context we cannot acquire any mutex etc. And to transmit
581 * this packet we need to call SME API. So to take care of this we will
582 * schedule a workqueue
583 */
584 schedule_work(&pPgBkAdapter->monTxWorkQueue);
585 }
586 return NETDEV_TX_OK;
587 }
588
589fail:
Kiet Lam3c2ee302014-03-23 23:23:22 -0700590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700591 "%s: Packet Rcvd at Monitor interface is not proper,"
592 " Dropping the packet",
593 __func__);
594 kfree_skb(skb);
595 return NETDEV_TX_OK;
596}
Jeff Johnson295189b2012-06-20 16:38:30 -0700597/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530598 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700599 transmitting packets. There are 2 versions of this function. One that uses
600 locked queue and other that uses lockless queues. Both have been retained to
601 do some performance testing
602
603 @param skb : [in] pointer to OS packet (sk_buff)
604 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530605
Jeff Johnson295189b2012-06-20 16:38:30 -0700606 @return : NET_XMIT_DROP if packets are dropped
607 : NET_XMIT_SUCCESS if packet is enqueued succesfully
608 ===========================================================================*/
609int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
610{
611 VOS_STATUS status;
612 WLANTL_ACEnumType ac;
613 sme_QosWmmUpType up;
614 skb_list_node_t *pktNode = NULL;
615 hdd_list_node_t *anchor = NULL;
616 v_SIZE_t pktListSize = 0;
617 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
618 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700619 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Jeff Johnson295189b2012-06-20 16:38:30 -0700621 v_BOOL_t txSuspended = VOS_FALSE;
622
623 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
624
Ravi Joshif9520d62013-10-18 04:11:46 -0700625 if (unlikely(netif_subqueue_stopped(dev, skb))) {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700626 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700627 "%s is called when netif TX %d is disabled",
628 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530629 return NETDEV_TX_BUSY;
630 }
631
Ravi Joshicc57ed42013-10-12 16:31:25 -0700632 //Get TL AC corresponding to Qdisc queue index/AC.
633 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
634
635 if (WLAN_HDD_IBSS == pAdapter->device_mode)
Shailender Karmuchia734f332013-04-19 14:02:48 -0700636 {
637 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
638
Ravi Joshif9520d62013-10-18 04:11:46 -0700639 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
Ravi Joshicc57ed42013-10-12 16:31:25 -0700640 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700641 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700642 "%s: Tx frame in disconnected state in IBSS mode", __func__);
643 ++pAdapter->stats.tx_dropped;
644 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
645 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
646 kfree_skb(skb);
647 return NETDEV_TX_OK;
648 }
649
Shailender Karmuchia734f332013-04-19 14:02:48 -0700650 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
651
652 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
653 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
654 vos_is_macaddr_group(pDestMacAddress)))
655 {
656 STAId = IBSS_BROADCAST_STAID;
Kiet Lam3c2ee302014-03-23 23:23:22 -0700657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
Ravi Joshif9520d62013-10-18 04:11:46 -0700658 "%s: BC/MC packet", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700659 }
660 else if (STAId == HDD_WLAN_INVALID_STA_ID)
661 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshif9520d62013-10-18 04:11:46 -0700663 "%s: Received Unicast frame with invalid staID", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700664 ++pAdapter->stats.tx_dropped;
665 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700666 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Shailender Karmuchia734f332013-04-19 14:02:48 -0700667 kfree_skb(skb);
668 return NETDEV_TX_OK;
669 }
670 }
671 else
672 {
673 STAId = pHddStaCtx->conn_info.staId[0];
674 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700675
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530676 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700677 //select_queue call back function
678 up = skb->priority;
679
680 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
681
682#ifdef HDD_WMM_DEBUG
Kiet Lam3c2ee302014-03-23 23:23:22 -0700683 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700684 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700685#endif // HDD_WMM_DEBUG
686
687 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700688 /*CR 463598,384996*/
689 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
690 *We check for +1 in the logic,to take care of Zero count which
691 *occurs very frequently in low traffic cases */
692 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
693 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700694 /* 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 -0700695 * if it is in the mainline code and if the log level is enabled by someone for debugging
Kiet Lam3c2ee302014-03-23 23:23:22 -0700696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s:Queue is Filling up.Inform TL again about pending packets", __func__);*/
Shailender Karmuchia734f332013-04-19 14:02:48 -0700697
Ravi Joshi8a934352013-09-25 16:46:58 -0700698 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
699 STAId, ac
700 );
701 if ( !VOS_IS_STATUS_SUCCESS( status ) )
702 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700703 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700704 "%s: WLANTL_STAPktPending() returned error code %d",
705 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700706 ++pAdapter->stats.tx_dropped;
707 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
708 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Ravi Joshi8a934352013-09-25 16:46:58 -0700709 kfree_skb(skb);
710 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
711 return NETDEV_TX_OK;
712 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700713 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700714 //If we have already reached the max queue size, disable the TX queue
715 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
716 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700717 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
718 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
719 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
720 pAdapter->isTxSuspended[ac] = VOS_TRUE;
721 txSuspended = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700722 }
723
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530724 /* If 3/4th of the max queue size is used then enable the flag.
725 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
726 if (WLANTL_AC_BE == ac)
727 {
728 if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
729 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530730 pAdapter->isVosLowResource = VOS_TRUE;
731 }
732 else
733 {
734 pAdapter->isVosLowResource = VOS_FALSE;
735 }
736 }
737
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530738 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700739 if (VOS_TRUE == txSuspended)
740 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530742 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700743 __func__, ac );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530744 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700745 }
746
747 //Use the skb->cb field to hold the list node information
748 pktNode = (skb_list_node_t *)&skb->cb;
749
750 //Stick the OS packet inside this node.
751 pktNode->skb = skb;
752
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530753 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 pktNode->userPriority = up;
755
756
757 INIT_LIST_HEAD(&pktNode->anchor);
758
759 //Insert the OS packet into the appropriate AC queue
760 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
761 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
762 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
763
764 if ( !VOS_IS_STATUS_SUCCESS( status ) )
765 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700766 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700767 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
768 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
769 ++pAdapter->stats.tx_dropped;
770 kfree_skb(skb);
771 return NETDEV_TX_OK;
772 }
773
774 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
775 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700776 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700777
Kiet Lamf040f472013-11-20 21:15:23 +0530778 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
779 {
780 /* Function which will determine acquire admittance for a
781 * WMM AC is required or not based on psb configuration done
782 * in the framework
783 */
784 hdd_wmm_acquire_access_required(pAdapter, ac);
785 }
786
Jeff Johnson295189b2012-06-20 16:38:30 -0700787 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530788 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
789 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700790 {
791 granted = VOS_TRUE;
792 }
793 else
794 {
795 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530796 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700797 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700798 if ( granted && ( pktListSize == 1 ))
799 {
800 //Let TL know we have a packet to send for this AC
Kiet Lam3c2ee302014-03-23 23:23:22 -0700801 //VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700802 status = WLANTL_STAPktPending(
803 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
804 STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700805 if ( !VOS_IS_STATUS_SUCCESS( status ) )
806 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d", __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700808
809 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
810 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
811 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
812 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
813 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
814 ++pAdapter->stats.tx_dropped;
815 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
816 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
817 kfree_skb(skb);
818 return NETDEV_TX_OK;
819 }
820 }
821
822 dev->trans_start = jiffies;
823
824 return NETDEV_TX_OK;
825}
826
827/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -0700828 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
829
830 @param pHddStaCtx : [in] pointer to HDD Station Context
831 pMacAddress [in] pointer to Peer Mac address
832 staID [out] pointer to Station Index
833 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
834 ===========================================================================*/
835
836VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
837{
838 v_U8_t idx;
839
840 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
841 {
842 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
843 pMacAddress, sizeof(v_MACADDR_t)))
844 {
845 *staId = pHddStaCtx->conn_info.staId[idx];
846 return VOS_STATUS_SUCCESS;
847 }
848 }
849
850 return VOS_STATUS_E_FAILURE;
851}
852
853/**============================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -0700854 @brief hdd_tx_timeout() - Function called by OS if there is any
855 timeout during transmission. Since HDD simply enqueues packet
856 and returns control to OS right away, this would never be invoked
857
858 @param dev : [in] pointer to Libra network device
859 @return : None
860 ===========================================================================*/
861void hdd_tx_timeout(struct net_device *dev)
862{
Ravi Joshicc57ed42013-10-12 16:31:25 -0700863 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
864 struct netdev_queue *txq;
865 int i = 0;
866
c_hpothub8245442013-11-20 23:41:09 +0530867 if ( NULL == pAdapter )
868 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530870 FL("pAdapter is NULL"));
871 VOS_ASSERT(0);
872 return;
873 }
874
Kiet Lam3c2ee302014-03-23 23:23:22 -0700875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700876 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700877 //Getting here implies we disabled the TX queues for too long. Queues are
878 //disabled either because of disassociation or low resource scenarios. In
879 //case of disassociation it is ok to ignore this. But if associated, we have
880 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -0700881
Kiet Lam3c2ee302014-03-23 23:23:22 -0700882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700883 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
884 pAdapter->wmm_tx_queue[0].count,
885 pAdapter->wmm_tx_queue[1].count,
886 pAdapter->wmm_tx_queue[2].count,
887 pAdapter->wmm_tx_queue[3].count);
888
Kiet Lam3c2ee302014-03-23 23:23:22 -0700889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700890 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
891 pAdapter->isTxSuspended[0],
892 pAdapter->isTxSuspended[1],
893 pAdapter->isTxSuspended[2],
894 pAdapter->isTxSuspended[3]);
895
896 for (i = 0; i < 8; i++)
897 {
898 txq = netdev_get_tx_queue(dev, i);
Kiet Lam3c2ee302014-03-23 23:23:22 -0700899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700900 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
901 }
902
Kiet Lam3c2ee302014-03-23 23:23:22 -0700903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700904 "carrier state: %d", netif_carrier_ok(dev));
Jeff Johnson295189b2012-06-20 16:38:30 -0700905}
906
907
908/**============================================================================
909 @brief hdd_stats() - Function registered with the Linux OS for
910 device TX/RX statistic
911
912 @param dev : [in] pointer to Libra network device
913
914 @return : pointer to net_device_stats structure
915 ===========================================================================*/
916struct net_device_stats* hdd_stats(struct net_device *dev)
917{
918 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +0530919
920 if ( NULL == pAdapter )
921 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530923 FL("pAdapter is NULL"));
924 VOS_ASSERT(0);
925 return NULL;
926 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700927
928 return &pAdapter->stats;
929}
930
931
932/**============================================================================
933 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
934 modules in HDD
935
936 @param pAdapter : [in] pointer to adapter context
937 @return : VOS_STATUS_E_FAILURE if any errors encountered
938 : VOS_STATUS_SUCCESS otherwise
939 ===========================================================================*/
940VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
941{
942 VOS_STATUS status = VOS_STATUS_SUCCESS;
943 v_SINT_t i = -1;
944
c_hpothub8245442013-11-20 23:41:09 +0530945 if ( NULL == pAdapter )
946 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530948 FL("pAdapter is NULL"));
949 VOS_ASSERT(0);
950 return VOS_STATUS_E_FAILURE;
951 }
952
Jeff Johnson295189b2012-06-20 16:38:30 -0700953 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530954 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700955
956 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
957 //Will be zeroed out during alloc
958
959 while (++i != NUM_TX_QUEUES)
960 {
961 pAdapter->isTxSuspended[i] = VOS_FALSE;
962 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
963 }
964
965 return status;
966}
967
968
969/**============================================================================
970 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
971 modules in HDD
972
973 @param pAdapter : [in] pointer to adapter context
974 @return : VOS_STATUS_E_FAILURE if any errors encountered
975 : VOS_STATUS_SUCCESS otherwise
976 ===========================================================================*/
977VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
978{
979 VOS_STATUS status = VOS_STATUS_SUCCESS;
980 v_SINT_t i = -1;
981
c_hpothub8245442013-11-20 23:41:09 +0530982 if ( NULL == pAdapter )
983 {
Kiet Lam3c2ee302014-03-23 23:23:22 -0700984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530985 FL("pAdapter is NULL"));
986 VOS_ASSERT(0);
987 return VOS_STATUS_E_FAILURE;
988 }
989
Jeff Johnson295189b2012-06-20 16:38:30 -0700990 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +0530991 if (VOS_STATUS_SUCCESS != status)
Kiet Lam3c2ee302014-03-23 23:23:22 -0700992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +0530993 FL("failed to flush tx queues"));
994
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 while (++i != NUM_TX_QUEUES)
996 {
997 //Free up actual list elements in the Tx queue
998 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
999 }
1000
1001 return status;
1002}
1003
1004
1005/**============================================================================
1006 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1007 modules in HDD
1008
1009 @param pAdapter : [in] pointer to adapter context
1010 @return : VOS_STATUS_E_FAILURE if any errors encountered
1011 : VOS_STATUS_SUCCESS otherwise
1012 ===========================================================================*/
1013VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1014{
1015 return hdd_flush_tx_queues(pAdapter);
1016}
1017
1018
1019/**============================================================================
1020 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1021
1022 @param pVosPacket : [in] pointer to vos packet
1023 @return : VOS_TRUE if the packet is EAPOL
1024 : VOS_FALSE otherwise
1025 ===========================================================================*/
1026
1027v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1028{
1029 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1030 v_BOOL_t fEAPOL = VOS_FALSE;
1031 void *pBuffer = NULL;
1032
1033
1034 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1035 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1036 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1037 {
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08001038 if (pBuffer && vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_802_1_X )
Jeff Johnson295189b2012-06-20 16:38:30 -07001039 {
1040 fEAPOL = VOS_TRUE;
1041 }
1042 }
1043
1044 return fEAPOL;
1045}
1046
1047
1048#ifdef FEATURE_WLAN_WAPI // Need to update this function
1049/**============================================================================
1050 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1051
1052 @param pVosPacket : [in] pointer to vos packet
1053 @return : VOS_TRUE if the packet is WAI
1054 : VOS_FALSE otherwise
1055 ===========================================================================*/
1056
1057v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1058{
1059 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1060 v_BOOL_t fIsWAI = VOS_FALSE;
1061 void *pBuffer = NULL;
1062
1063 // Need to update this function
1064 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1065 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1066
1067 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1068 {
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08001069 if (pBuffer && vos_be16_to_cpu( *((unsigned short*)pBuffer)) == HDD_ETHERTYPE_WAI)
Jeff Johnson295189b2012-06-20 16:38:30 -07001070 {
1071 fIsWAI = VOS_TRUE;
1072 }
1073 }
1074
1075 return fIsWAI;
1076}
1077#endif /* FEATURE_WLAN_WAPI */
1078
1079/**============================================================================
1080 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1081 to indicate that a packet has been transmitted across the SDIO bus
1082 succesfully. OS packet resources can be released after this cbk.
1083
1084 @param vosContext : [in] pointer to VOS context
1085 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1086 @param vosStatusIn : [in] status of the transmission
1087
1088 @return : VOS_STATUS_E_FAILURE if any errors encountered
1089 : VOS_STATUS_SUCCESS otherwise
1090 ===========================================================================*/
1091VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1092 vos_pkt_t *pVosPacket,
1093 VOS_STATUS vosStatusIn )
1094{
1095 VOS_STATUS status = VOS_STATUS_SUCCESS;
1096 hdd_adapter_t *pAdapter = NULL;
1097 hdd_context_t *pHddCtx = NULL;
1098 void* pOsPkt = NULL;
1099
1100 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1101 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301103 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 return VOS_STATUS_E_FAILURE;
1105 }
1106
1107 //Return the skb to the OS
1108 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301109 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 {
1111 //This is bad but still try to free the VOSS resources if we can
Kiet Lam3c2ee302014-03-23 23:23:22 -07001112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301113 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001114 vos_pkt_return_packet( pVosPacket );
1115 return VOS_STATUS_E_FAILURE;
1116 }
1117
1118 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001119 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001120 //Get the Adapter context.
1121 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Agarwal Ashish971c2882013-10-30 20:11:12 +05301122 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07001123 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301125 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001126 }
1127 else
1128 {
1129 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1130 }
1131
1132 kfree_skb((struct sk_buff *)pOsPkt);
1133
1134 //Return the VOS packet resources.
1135 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301136 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001137 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301139 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001140 }
1141
1142 return status;
1143}
1144
1145
1146/**============================================================================
1147 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1148 fetch a packet for transmission.
1149
1150 @param vosContext : [in] pointer to VOS context
1151 @param staId : [in] Station for which TL is requesting a pkt
1152 @param ac : [in] access category requested by TL
1153 @param pVosPacket : [out] pointer to VOS packet packet pointer
1154 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1155
1156 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1157 : VOS_STATUS_E_FAILURE if any errors encountered
1158 : VOS_STATUS_SUCCESS otherwise
1159 ===========================================================================*/
1160VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1161 v_U8_t *pStaId,
1162 WLANTL_ACEnumType ac,
1163 vos_pkt_t **ppVosPacket,
1164 WLANTL_MetaInfoType *pPktMetaInfo )
1165{
1166 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1167 hdd_adapter_t *pAdapter = NULL;
1168 hdd_context_t *pHddCtx = NULL;
1169 hdd_list_node_t *anchor = NULL;
1170 skb_list_node_t *pktNode = NULL;
1171 struct sk_buff *skb = NULL;
1172 vos_pkt_t *pVosPacket = NULL;
1173 v_MACADDR_t* pDestMacAddress = NULL;
1174 v_TIME_t timestamp;
1175 WLANTL_ACEnumType newAc;
1176 v_SIZE_t size = 0;
1177 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001178 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001179
1180 //Sanity check on inputs
1181 if ( ( NULL == vosContext ) ||
1182 ( NULL == pStaId ) ||
1183 ( NULL == ppVosPacket ) ||
1184 ( NULL == pPktMetaInfo ) )
1185 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301187 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001188 return VOS_STATUS_E_FAILURE;
1189 }
1190
1191 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001192 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001193 if(pHddCtx == NULL)
1194 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301196 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001197 return VOS_STATUS_E_FAILURE;
1198 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001199 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001200 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001201 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301203 FL("pAdapter is NULL %u"), *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001204 VOS_ASSERT(0);
1205 return VOS_STATUS_E_FAILURE;
1206 }
1207
1208 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1209
1210 *ppVosPacket = NULL;
1211
1212 //Make sure the AC being asked for is sane
1213 if( ac >= WLANTL_MAX_AC || ac < 0)
1214 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301216 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001217 return VOS_STATUS_E_FAILURE;
1218 }
1219
1220 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1221
1222#ifdef HDD_WMM_DEBUG
Kiet Lam3c2ee302014-03-23 23:23:22 -07001223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301224 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001225#endif // HDD_WMM_DEBUG
1226
1227 // We find an AC with packets
1228 // or we determine we have no more packets to send
1229 // HDD is not allowed to change AC.
1230
1231 // has this AC been admitted? or
1232 // To allow EAPOL packets when not authenticated
1233 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1234 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1235 {
1236 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1237#ifdef HDD_WMM_DEBUG
Kiet Lam3c2ee302014-03-23 23:23:22 -07001238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001239 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001240#endif // HDD_WMM_DEBUG
1241 return VOS_STATUS_E_FAILURE;
1242 }
1243
1244 // do we have any packets pending in this AC?
1245 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1246 if( size > 0 )
1247 {
1248 // yes, so process it
1249#ifdef HDD_WMM_DEBUG
Kiet Lam3c2ee302014-03-23 23:23:22 -07001250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001251 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001252#endif // HDD_WMM_DEBUG
1253 }
1254 else
1255 {
1256 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1257#ifdef HDD_WMM_DEBUG
Kiet Lam3c2ee302014-03-23 23:23:22 -07001258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001259 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001260#endif // HDD_WMM_DEBUG
1261 return VOS_STATUS_E_FAILURE;
1262 }
1263
1264 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1265 //This simplifies the locking and unlocking of Tx queue
1266 status = vos_pkt_wrap_data_packet( &pVosPacket,
1267 VOS_PKT_TYPE_TX_802_3_DATA,
1268 NULL, //OS Pkt is not being passed
1269 hdd_tx_low_resource_cbk,
1270 pAdapter );
1271
1272 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1273 {
1274 //Remember VOS is in a low resource situation
1275 pAdapter->isVosOutOfResource = VOS_TRUE;
1276 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
Kiet Lam3c2ee302014-03-23 23:23:22 -07001277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001278 //TL will now think we have no more packets in this AC
1279 return VOS_STATUS_E_FAILURE;
1280 }
1281
1282 //Remove the packet from the queue
1283 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1284 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1285 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1286
1287 if(VOS_STATUS_SUCCESS == status)
1288 {
1289 //If success then we got a valid packet from some AC
1290 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1291 skb = pktNode->skb;
1292 }
1293 else
1294 {
1295 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
Kiet Lam3c2ee302014-03-23 23:23:22 -07001296 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001297 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001298 vos_pkt_return_packet(pVosPacket);
1299 return VOS_STATUS_E_FAILURE;
1300 }
1301
1302 //Attach skb to VOS packet.
1303 status = vos_pkt_set_os_packet( pVosPacket, skb );
1304 if (status != VOS_STATUS_SUCCESS)
1305 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001307 vos_pkt_return_packet(pVosPacket);
1308 ++pAdapter->stats.tx_dropped;
1309 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1310 kfree_skb(skb);
1311 return VOS_STATUS_E_FAILURE;
1312 }
1313
1314 //Just being paranoid. To be removed later
1315 if(pVosPacket == NULL)
1316 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001317 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 ++pAdapter->stats.tx_dropped;
1319 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1320 kfree_skb(skb);
1321 return VOS_STATUS_E_FAILURE;
1322 }
1323
Chilam NG571c65a2013-01-19 12:27:36 +05301324#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001325 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05301326 {
1327 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301328 u8 mac[6];
1329
Hoonki Lee387663d2013-02-05 18:08:43 -08001330 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301331
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001332 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001333 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301334 "broadcast packet, not adding to peer list");
1335 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1336 mac, 6) != 0) {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001338 "extract mac: " MAC_ADDRESS_STR,
1339 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05301340
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001341 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301342 } else {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301344 "packet da is bssid, not adding to peer list");
1345 }
1346 }
1347#endif
1348
Jeff Johnson295189b2012-06-20 16:38:30 -07001349 //Return VOS packet to TL;
1350 *ppVosPacket = pVosPacket;
1351
1352 //Fill out the meta information needed by TL
1353 //FIXME This timestamp is really the time stamp of wrap_data_packet
1354 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1355 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1356
1357 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1358 pPktMetaInfo->ucIsEapol = 0;
1359 else
1360 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1361
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001362 if (pHddCtx->cfg_ini->gEnableDebugLog)
1363 {
1364 proto_type = vos_pkt_get_proto_type(skb,
1365 pHddCtx->cfg_ini->gEnableDebugLog);
1366 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1367 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001369 "STA TX EAPOL");
1370 }
1371 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1372 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001374 "STA TX DHCP");
1375 }
1376 }
1377
Jeff Johnson295189b2012-06-20 16:38:30 -07001378#ifdef FEATURE_WLAN_WAPI
1379 // Override usIsEapol value when its zero for WAPI case
1380 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
1381#endif /* FEATURE_WLAN_WAPI */
1382
1383 if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) ||
1384 (!pAdapter->hddWmmStatus.wmmQap))
1385 {
1386 // either we don't want QoS or the AP doesn't support QoS
1387 pPktMetaInfo->ucUP = 0;
1388 pPktMetaInfo->ucTID = 0;
1389 }
1390 else
1391 {
1392 /* 1. Check if ACM is set for this AC
1393 * 2. If set, check if this AC had already admitted
1394 * 3. If not already admitted, downgrade the UP to next best UP */
1395 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
1396 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid)
1397 {
1398 pPktMetaInfo->ucUP = pktNode->userPriority;
1399 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1400 }
1401 else
1402 {
1403 //Downgrade the UP
1404 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1405 newAc = WLANTL_AC_BK;
1406 for (i=ac-1; i>0; i--)
1407 {
1408 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1409 {
1410 newAc = i;
1411 break;
1412 }
1413 }
1414 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1415 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
Kiet Lam3c2ee302014-03-23 23:23:22 -07001416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07001417 }
1418 }
1419
1420 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1421 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1422 if ( 1 < size )
1423 {
1424 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1425 }
1426 else
1427 {
1428 pPktMetaInfo->bMorePackets = 0;
1429 }
1430
1431 //Extract the destination address from ethernet frame
1432 pDestMacAddress = (v_MACADDR_t*)skb->data;
1433 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1434 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1435
1436
1437
1438 // if we are in a backpressure situation see if we can turn the hose back on
1439 if ( (pAdapter->isTxSuspended[ac]) &&
1440 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1441 {
1442 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1443 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
Kiet Lam3c2ee302014-03-23 23:23:22 -07001444 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001445 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1447 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1448 skb_get_queue_mapping(skb) ));
1449 }
1450
1451
1452 // We're giving the packet to TL so consider it transmitted from
1453 // a statistics perspective. We account for it here instead of
1454 // when the packet is returned for two reasons. First, TL will
1455 // manipulate the skb to the point where the len field is not
1456 // accurate, leading to inaccurate byte counts if we account for
1457 // it later. Second, TL does not provide any feedback as to
1458 // whether or not the packet was successfully sent over the air,
1459 // so the packet counts will be the same regardless of where we
1460 // account for them
1461 pAdapter->stats.tx_bytes += skb->len;
1462 ++pAdapter->stats.tx_packets;
1463 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1464 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1465
Leo Chang50bbd252013-04-25 14:58:01 -07001466 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1467 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001468 {
1469 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1470 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001472 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001473 return VOS_STATUS_E_FAILURE;
1474 }
1475 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1476 {
1477 if(0 == pHddCtx->tmInfo.txFrameCount)
1478 {
1479 /* Just recovered from sleep timeout */
1480 pHddCtx->tmInfo.lastOpenTs = timestamp;
1481 }
1482
Leo Chang50bbd252013-04-25 14:58:01 -07001483 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1484 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001485 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1486 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001487 /* During TX open duration, TX frame count is larger than threshold
1488 * Block TX during Sleep time */
1489 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001490 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001491 pHddCtx->tmInfo.lastblockTs = timestamp;
1492 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1493 {
1494 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1495 }
1496 }
1497 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1498 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1499 {
1500 /* During TX open duration, TX frame count is less than threshold
1501 * Reset count and timestamp to prepare next cycle */
1502 pHddCtx->tmInfo.lastOpenTs = timestamp;
1503 pHddCtx->tmInfo.txFrameCount = 0;
1504 }
1505 else
1506 {
1507 /* Do Nothing */
1508 }
1509 pHddCtx->tmInfo.txFrameCount++;
1510 }
1511 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1512 }
1513
1514
1515#ifdef HDD_WMM_DEBUG
Kiet Lam3c2ee302014-03-23 23:23:22 -07001516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001517#endif // HDD_WMM_DEBUG
1518
1519 return status;
1520}
1521
1522
1523/**============================================================================
1524 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1525 case where VOS packets are not available at the time of the call to get
1526 packets. This callback function is invoked by VOS when packets are
1527 available.
1528
1529 @param pVosPacket : [in] pointer to VOS packet
1530 @param userData : [in] opaque user data that was passed initially
1531
1532 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1533 : VOS_STATUS_SUCCESS otherwise
1534 =============================================================================*/
1535VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1536 v_VOID_t *userData )
1537{
1538 VOS_STATUS status;
1539 v_SINT_t i = 0;
1540 v_SIZE_t size = 0;
1541 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1542
Agarwal Ashish971c2882013-10-30 20:11:12 +05301543 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001544 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301546 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001547 return VOS_STATUS_E_FAILURE;
1548 }
1549
1550 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1551 //situation. Here we will only signal TL that there is a pending data for a STA.
1552 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1553 vos_pkt_return_packet( pVosPacket );
1554
1555 pAdapter->isVosOutOfResource = VOS_FALSE;
1556
1557 //Indicate to TL that there is pending data if a queue is non empty
1558 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1559 {
1560 size = 0;
1561 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1562 if ( size > 0 )
1563 {
1564 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1565 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1566 (WLANTL_ACEnumType)i );
1567 if( !VOS_IS_STATUS_SUCCESS( status ) )
1568 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301570 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001571 }
1572 }
1573 }
1574
1575 return VOS_STATUS_SUCCESS;
1576}
1577
1578
1579/**============================================================================
1580 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1581 TL will call this to notify the HDD when one or more packets were
1582 received for a registered STA.
1583
1584 @param vosContext : [in] pointer to VOS context
1585 @param pVosPacketChain : [in] pointer to VOS packet chain
1586 @param staId : [in] Station Id
1587 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1588
1589 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1590 : VOS_STATUS_SUCCESS otherwise
1591 ===========================================================================*/
1592VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1593 vos_pkt_t *pVosPacketChain,
1594 v_U8_t staId,
1595 WLANTL_RxMetaInfoType* pRxMetaInfo )
1596{
1597 hdd_adapter_t *pAdapter = NULL;
1598 hdd_context_t *pHddCtx = NULL;
1599 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1600 int rxstat;
1601 struct sk_buff *skb = NULL;
1602 vos_pkt_t* pVosPacket;
1603 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001604 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001605
1606 //Sanity check on inputs
1607 if ( ( NULL == vosContext ) ||
1608 ( NULL == pVosPacketChain ) ||
1609 ( NULL == pRxMetaInfo ) )
1610 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301612 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001613 return VOS_STATUS_E_FAILURE;
1614 }
1615
Kiet Lam3c2ee302014-03-23 23:23:22 -07001616 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 if ( NULL == pHddCtx )
1618 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301620 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001621 return VOS_STATUS_E_FAILURE;
1622 }
1623
1624 pAdapter = pHddCtx->sta_to_adapter[staId];
1625 if( NULL == pAdapter )
1626 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: pAdapter is Null for staId %u",
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05301628 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 return VOS_STATUS_E_FAILURE;
1630 }
1631
1632 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1633
1634 // walk the chain until all are processed
1635 pVosPacket = pVosPacketChain;
1636 do
1637 {
1638 // get the pointer to the next packet in the chain
1639 // (but don't unlink the packet since we free the entire chain later)
1640 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1641
1642 // both "success" and "empty" are acceptable results
1643 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1644 {
1645 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Kiet Lam3c2ee302014-03-23 23:23:22 -07001646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301647 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001648 return VOS_STATUS_E_FAILURE;
1649 }
1650
1651 // Extract the OS packet (skb).
1652 // Tell VOS to detach the OS packet from the VOS packet
1653 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1654 if(!VOS_IS_STATUS_SUCCESS( status ))
1655 {
1656 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Kiet Lam3c2ee302014-03-23 23:23:22 -07001657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301658 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 return VOS_STATUS_E_FAILURE;
1660 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001661
1662 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1663 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07001665 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
1666 return eHAL_STATUS_FAILURE;
1667 }
1668
Chilam Ng1279e232013-01-25 15:06:52 -08001669#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001670 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
1671 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08001672 {
1673 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08001674 u8 mac[6];
1675
Hoonki Lee387663d2013-02-05 18:08:43 -08001676 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08001677
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001678 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08001680 "rx broadcast packet, not adding to peer list");
1681 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1682 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001683 hddTdlsPeer_t *curr_peer;
Kiet Lam3c2ee302014-03-23 23:23:22 -07001684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001685 "rx extract mac:" MAC_ADDRESS_STR,
1686 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301687 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05301688 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
1689 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001690 {
1691 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
Kiet Lam3c2ee302014-03-23 23:23:22 -07001692 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001693 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
1694 }
Chilam Ng1279e232013-01-25 15:06:52 -08001695 } else {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08001697 "rx packet sa is bssid, not adding to peer list");
1698 }
1699 }
1700#endif
1701
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001702 if (pHddCtx->cfg_ini->gEnableDebugLog)
1703 {
1704 proto_type = vos_pkt_get_proto_type(skb,
1705 pHddCtx->cfg_ini->gEnableDebugLog);
1706 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1707 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001708 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001709 "STA RX EAPOL");
1710 }
1711 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1712 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001713 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001714 "STA RX DHCP");
1715 }
1716 }
1717
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 skb->dev = pAdapter->dev;
1719 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001720 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001721 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1722 ++pAdapter->stats.rx_packets;
1723 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001724#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001725#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001726 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001727#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001728#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001729 rxstat = netif_rx_ni(skb);
1730 if (NET_RX_SUCCESS == rxstat)
1731 {
1732 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001733 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001734 }
1735 else
1736 {
1737 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1738 }
1739 // now process the next packet in the chain
1740 pVosPacket = pNextVosPacket;
1741
1742 } while (pVosPacket);
1743
1744 //Return the entire VOS packet chain to the resource pool
1745 status = vos_pkt_return_packet( pVosPacketChain );
1746 if(!VOS_IS_STATUS_SUCCESS( status ))
1747 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001749 }
1750
1751 pAdapter->dev->last_rx = jiffies;
1752
1753 return status;
1754}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001755/**============================================================================
1756 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
1757 Enable/Disable split scan based on TX and RX traffic.
1758 @param HddContext : [in] pointer to Hdd context
1759 @return : None
1760 ===========================================================================*/
1761void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
1762{
1763 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1764 hdd_adapter_t *pAdapter = NULL;
1765 hdd_station_ctx_t *pHddStaCtx = NULL;
1766 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
1767 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
1768 VOS_STATUS status;
1769 v_U8_t staId = 0;
1770 v_U8_t fconnected = 0;
1771
c_hpothub8245442013-11-20 23:41:09 +05301772 if (NULL == phddctx)
1773 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301775 FL("phddctx is NULL"));
1776 VOS_ASSERT(0);
1777 return;
1778 }
1779
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001780 if (!cfg_param->dynSplitscan)
1781 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001782 hddLog(VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001783 "%s: Error : Dynamic split scan is not Enabled : %d",
1784 __func__, pHddCtx->cfg_ini->dynSplitscan);
1785 return;
1786 }
1787
1788 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1789 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1790 {
1791 pAdapter = pAdapterNode->pAdapter;
1792
1793 if ( pAdapter )
1794 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001795 hddLog(VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001796 "%s: Adapter with device mode %d exists",
1797 __func__, pAdapter->device_mode);
1798
1799 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1800 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
1801 {
1802 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1803 if ((eConnectionState_Associated ==
1804 pHddStaCtx->conn_info.connState) &&
1805 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
1806 {
1807 fconnected = TRUE;
1808 }
1809 }
1810 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1811 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
1812 {
1813 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1814 {
1815 if ((pAdapter->aStaInfo[staId].isUsed) &&
1816 (WLANTL_STA_AUTHENTICATED ==
1817 pAdapter->aStaInfo[staId].tlSTAState))
1818 {
1819 fconnected = TRUE;
1820 }
1821 }
1822 }
1823 if ( fconnected )
1824 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001825 hddLog(VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001826 "%s: One of the interface is connected check for scan",
1827 __func__);
Kiet Lam3c2ee302014-03-23 23:23:22 -07001828 hddLog(VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001829 "%s: pkt_tx_count: %d, pkt_rx_count: %d", __func__,
1830 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
1831 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count);
1832
1833 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1834 cfg_param->trafficMntrTmrForSplitScan);
1835 //Check for the previous statistics count
1836 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
1837 cfg_param->txRxThresholdForSplitScan) ||
1838 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
1839 cfg_param->txRxThresholdForSplitScan) ||
1840 pHddCtx->drvr_miracast)
1841 {
1842 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
1843 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
1844
1845 if (!pHddCtx->issplitscan_enabled)
1846 {
1847 pHddCtx->issplitscan_enabled = TRUE;
1848 sme_enable_disable_split_scan(
1849 WLAN_HDD_GET_HAL_CTX(pAdapter),
1850 cfg_param->nNumStaChanCombinedConc,
1851 cfg_param->nNumP2PChanCombinedConc);
1852 }
1853 return;
1854 }
1855 else
1856 {
1857 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
1858 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
1859 }
1860 fconnected = FALSE;
1861 }
1862 }
1863 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
1864 pAdapterNode = pNext;
1865 }
1866
1867 if (pHddCtx->issplitscan_enabled)
1868 {
Kiet Lam3c2ee302014-03-23 23:23:22 -07001869 hddLog(VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001870 "%s: Disable split scan", __func__);
1871 pHddCtx->issplitscan_enabled = FALSE;
1872 sme_enable_disable_split_scan(
1873 pHddCtx->hHal,
1874 SME_DISABLE_SPLIT_SCAN,
1875 SME_DISABLE_SPLIT_SCAN);
1876 }
1877 return;
1878}
Jeff Johnson295189b2012-06-20 16:38:30 -07001879