blob: 10c07d10da791aed920f04e202bde20ac23b4be3 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**===========================================================================
43
44 \file wlan_hdd_tx_rx.c
45
46 \brief Linux HDD Tx/RX APIs
47 Copyright 2008 (c) Qualcomm, Incorporated.
48 All Rights Reserved.
49 Qualcomm Confidential and Proprietary.
50
51 ==========================================================================*/
52
53/*---------------------------------------------------------------------------
54 Include files
55 -------------------------------------------------------------------------*/
56#include <wlan_hdd_tx_rx.h>
57#include <wlan_hdd_softap_tx_rx.h>
58#include <wlan_hdd_dp_utils.h>
59#include <wlan_qct_tl.h>
60#include <linux/netdevice.h>
61#include <linux/skbuff.h>
62#include <linux/etherdevice.h>
63
Jeff Johnson295189b2012-06-20 16:38:30 -070064#include <wlan_hdd_p2p.h>
65#include <linux/wireless.h>
66#include <net/cfg80211.h>
67#include <net/ieee80211_radiotap.h>
68#include "sapApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070069
Chilam NG571c65a2013-01-19 12:27:36 +053070#ifdef FEATURE_WLAN_TDLS
71#include "wlan_hdd_tdls.h"
72#endif
73
Jeff Johnson295189b2012-06-20 16:38:30 -070074/*---------------------------------------------------------------------------
75 Preprocessor definitions and constants
76 -------------------------------------------------------------------------*/
77
78const v_U8_t hddWmmAcToHighestUp[] = {
79 SME_QOS_WMM_UP_RESV,
80 SME_QOS_WMM_UP_EE,
81 SME_QOS_WMM_UP_VI,
82 SME_QOS_WMM_UP_NC
83};
84
85//Mapping Linux AC interpretation to TL AC.
86const v_U8_t hdd_QdiscAcToTlAC[] = {
87 WLANTL_AC_VO,
88 WLANTL_AC_VI,
89 WLANTL_AC_BE,
90 WLANTL_AC_BK,
91};
92
Jeff Johnson295189b2012-06-20 16:38:30 -070093static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070094
95/*---------------------------------------------------------------------------
96 Type declarations
97 -------------------------------------------------------------------------*/
98
99/*---------------------------------------------------------------------------
100 Function definitions and documenation
101 -------------------------------------------------------------------------*/
102
103#ifdef DATA_PATH_UNIT_TEST
104//Utility function to dump an sk_buff
105static void dump_sk_buff(struct sk_buff * skb)
106{
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: head = %p ", __func__, skb->head);
108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data);
109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p ", __func__, skb->tail);
110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: end = %p ", __func__, skb->end);
111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: len = %d ", __func__, skb->len);
112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d ", __func__, skb->data_len);
113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d\n", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700114
115 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 ",
116 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
117 skb->data[5], skb->data[6], skb->data[7]);
118 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 \n",
119 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
120 skb->data[13], skb->data[14], skb->data[15]);
121}
122
123//Function for Unit Test only
124static void transport_thread(hdd_adapter_t *pAdapter)
125{
126 v_U8_t staId;
127 WLANTL_ACEnumType ac = WLANTL_AC_BE;
128 vos_pkt_t *pVosPacket = NULL ;
129 vos_pkt_t dummyPacket;
130 WLANTL_MetaInfoType pktMetaInfo;
131 WLANTL_RxMetaInfoType pktRxMetaInfo;
132 VOS_STATUS status = VOS_STATUS_E_FAILURE;
133
134 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
135 &staId,
136 &ac,
137 &pVosPacket,
138 &pktMetaInfo );
139 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700140 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 -0700141 else
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700142 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 -0700143
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700144 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700145 if (status != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700146 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 -0700147 else
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700148 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 -0700149
150 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
151 if (status != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700152 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 -0700153 else
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700154 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 -0700155
156 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
157 &dummyPacket,
158 staId,
159 &pktRxMetaInfo);
160 if (status != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700161 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 -0700162 else
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700163 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 -0700164
165}
166#endif
167
168
169/**============================================================================
170 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
171
172 @param pAdapter : [in] pointer to adapter context
173 @return : VOS_STATUS_E_FAILURE if any errors encountered
174 : VOS_STATUS_SUCCESS otherwise
175 ===========================================================================*/
176static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
177{
178 VOS_STATUS status = VOS_STATUS_SUCCESS;
179 v_SINT_t i = -1;
180 hdd_list_node_t *anchor = NULL;
181 skb_list_node_t *pktNode = NULL;
182 struct sk_buff *skb = NULL;
183
184 while (++i != NUM_TX_QUEUES)
185 {
186 //Free up any packets in the Tx queue
187 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
188 while (true)
189 {
190 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
191 if(VOS_STATUS_E_EMPTY != status)
192 {
193 pktNode = list_entry(anchor, skb_list_node_t, anchor);
194 skb = pktNode->skb;
195 //TODO
196 //++pAdapter->stats.tx_dropped;
197 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
198 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
199 kfree_skb(skb);
200 continue;
201 }
202 break;
203 }
204 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
205 // backpressure is no longer in effect
206 pAdapter->isTxSuspended[i] = VOS_FALSE;
207 }
208
209 return status;
210}
211
Jeff Johnson295189b2012-06-20 16:38:30 -0700212static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
213{
214 skb_list_node_t *pktNode = NULL;
215 struct sk_buff *skb = NULL;
216 v_SIZE_t size = 0;
217 WLANTL_ACEnumType ac = 0;
218 VOS_STATUS status = VOS_STATUS_E_FAILURE;
219 hdd_list_node_t *anchor = NULL;
220
221 if( NULL == pAdapter )
222 {
223 VOS_ASSERT(0);
224 return NULL;
225 }
226
227 // do we have any packets pending in this AC?
228 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
229 if( size == 0 )
230 {
231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700232 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700233 return NULL;
234 }
235
236 //Remove the packet from the queue
237 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
238 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
239 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
240
241 if(VOS_STATUS_SUCCESS == status)
242 {
243 //If success then we got a valid packet from some AC
244 pktNode = list_entry(anchor, skb_list_node_t, anchor);
245 skb = pktNode->skb;
246 }
247 else
248 {
249 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
250 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700251 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252
253 return NULL;
254 }
255
256 // if we are in a backpressure situation see if we can turn the hose back on
257 if ( (pAdapter->isTxSuspended[ac]) &&
258 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
259 {
260 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700261 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 pAdapter->isTxSuspended[ac] = VOS_FALSE;
263 /* Enable Queues which we have disabled earlier */
264 netif_tx_start_all_queues( pAdapter->dev );
265 }
266
267 return skb;
268}
269
270void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
271{
272 hdd_cfg80211_state_t *cfgState;
273 struct sk_buff* skb;
274 hdd_adapter_t* pMonAdapter = NULL;
275 struct ieee80211_hdr *hdr;
276
277 if (pAdapter == NULL )
278 {
279 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
280 "%s: pAdapter is NULL", __func__);
281 return;
282 }
283
284 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
285
286 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
287
288 if( NULL != cfgState->buf )
289 {
290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
291 "%s: Already one MGMT packet Tx going on", __func__);
292 return;
293 }
294
295 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
296
297 if (NULL == skb)
298 {
299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
300 "%s: No Packet Pending", __func__);
301 return;
302 }
303
304 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
305 if( cfgState->buf == NULL )
306 {
307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
308 "%s: Failed to Allocate memory", __func__);
309 goto fail;
310 }
311
312 cfgState->len = skb->len;
313
314 vos_mem_copy( cfgState->buf, skb->data, skb->len);
315
316 cfgState->skb = skb; //buf;
317 cfgState->action_cookie = (tANI_U32)cfgState->buf;
318
319 hdr = (struct ieee80211_hdr *)skb->data;
320 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
321 == HDD_FRAME_TYPE_MGMT )
322 {
323 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
324 == HDD_FRAME_SUBTYPE_DEAUTH )
325 {
326 hdd_softap_sta_deauth( pAdapter, hdr->addr1 );
327 goto mgmt_handled;
328 }
329 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
330 == HDD_FRAME_SUBTYPE_DISASSOC )
331 {
332 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
333 goto mgmt_handled;
334 }
335 }
336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
337 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
338
Jeff Johnson43971f52012-07-17 12:26:56 -0700339 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700340 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700341 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700342 {
343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
344 "%s: WLANSAP_SendAction returned fail", __func__);
345 hdd_sendActionCnf( pAdapter, FALSE );
346 }
347 return;
348
349mgmt_handled:
350 hdd_sendActionCnf( pAdapter, TRUE );
351 return;
352fail:
353 kfree_skb(pAdapter->skb_to_tx);
354 pAdapter->skb_to_tx = NULL;
355 return;
356}
357
358void hdd_mon_tx_work_queue(struct work_struct *work)
359{
360 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
361 hdd_mon_tx_mgmt_pkt(pAdapter);
362}
363
364int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
365{
366 v_U16_t rt_hdr_len;
367 struct ieee80211_hdr *hdr;
368 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
369 struct ieee80211_radiotap_header *rtap_hdr =
370 (struct ieee80211_radiotap_header *)skb->data;
371
372 /*Supplicant sends the EAPOL packet on monitor interface*/
373 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
374 if(pPgBkAdapter == NULL)
375 {
376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
377 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
378 __func__);
379 goto fail; /* too short to be possibly valid */
380 }
381
382 /* check if toal skb length is greater then radio tab header length of not */
383 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
384 goto fail; /* too short to be possibly valid */
385
386 /* check if radio tap header version is correct or not */
387 if (unlikely(rtap_hdr->it_version))
388 goto fail; /* only version 0 is supported */
389
390 /*Strip off the radio tap header*/
391 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
392
393 /* check if skb length if greator then total radio tap header length ot not*/
394 if (unlikely(skb->len < rt_hdr_len))
395 goto fail;
396
397 /* Update the trans_start for this netdev */
398 dev->trans_start = jiffies;
399 /*
400 * fix up the pointers accounting for the radiotap
401 * header still being in there.
402 */
403 skb_set_mac_header(skb, rt_hdr_len);
404 skb_set_network_header(skb, rt_hdr_len);
405 skb_set_transport_header(skb, rt_hdr_len);
406
407 /* Pull rtap header out of the skb */
408 skb_pull(skb, rt_hdr_len);
409
410 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
411 * radio tap header and 802.11 header starts
412 */
413 hdr = (struct ieee80211_hdr *)skb->data;
414
415 /* Send data frames through the normal Data path. In this path we will
416 * conver rcvd 802.11 packet to 802.3 packet */
417 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
418 {
419 v_U8_t da[6];
420 v_U8_t sa[6];
421
422 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
423 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
424
425 /* Pull 802.11 MAC header */
426 skb_pull(skb, HDD_80211_HEADER_LEN);
427
428 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
429 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
430 {
431 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
432 }
433
434 /* Pull LLC header */
435 skb_pull(skb, HDD_LLC_HDR_LEN);
436
437 /* Create space for Ethernet header */
438 skb_push(skb, HDD_MAC_HDR_SIZE*2);
439 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
440 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
441
442 /* Only EAPOL Data packets are allowed through monitor interface */
443 if (vos_be16_to_cpu(
444 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
445 != HDD_ETHERTYPE_802_1_X)
446 {
447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
448 "%s: Not a Eapol packet. Drop this frame", __func__);
449 //If not EAPOL frames, drop them.
450 kfree_skb(skb);
451 return NETDEV_TX_OK;
452 }
453
454 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
455
456 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
457 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
458 }
459 else
460 {
461 VOS_STATUS status;
462 WLANTL_ACEnumType ac = 0;
463 skb_list_node_t *pktNode = NULL;
464 v_SIZE_t pktListSize = 0;
465
466 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
467 //If we have already reached the max queue size, disable the TX queue
468 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
469 {
470 /* We want to process one packet at a time, so lets disable all TX queues
471 * and re-enable the queues once we get TX feedback for this packet */
472 netif_tx_stop_all_queues(pAdapter->dev);
473 pAdapter->isTxSuspended[ac] = VOS_TRUE;
474 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
475 return NETDEV_TX_BUSY;
476 }
477 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
478
479 //Use the skb->cb field to hold the list node information
480 pktNode = (skb_list_node_t *)&skb->cb;
481
482 //Stick the OS packet inside this node.
483 pktNode->skb = skb;
484
485 INIT_LIST_HEAD(&pktNode->anchor);
486
487 //Insert the OS packet into the appropriate AC queue
488 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
489 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
490 &pktNode->anchor, &pktListSize );
491 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
492
493 if ( !VOS_IS_STATUS_SUCCESS( status ) )
494 {
495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700496 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700497 kfree_skb(skb);
498 return NETDEV_TX_OK;
499 }
500
501 if ( pktListSize == 1 )
502 {
503 /* In this context we cannot acquire any mutex etc. And to transmit
504 * this packet we need to call SME API. So to take care of this we will
505 * schedule a workqueue
506 */
507 schedule_work(&pPgBkAdapter->monTxWorkQueue);
508 }
509 return NETDEV_TX_OK;
510 }
511
512fail:
513 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
514 "%s: Packet Rcvd at Monitor interface is not proper,"
515 " Dropping the packet",
516 __func__);
517 kfree_skb(skb);
518 return NETDEV_TX_OK;
519}
Jeff Johnson295189b2012-06-20 16:38:30 -0700520/**============================================================================
521 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
522 transmitting packets. There are 2 versions of this function. One that uses
523 locked queue and other that uses lockless queues. Both have been retained to
524 do some performance testing
525
526 @param skb : [in] pointer to OS packet (sk_buff)
527 @param dev : [in] pointer to Libra network device
528
529 @return : NET_XMIT_DROP if packets are dropped
530 : NET_XMIT_SUCCESS if packet is enqueued succesfully
531 ===========================================================================*/
532int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
533{
534 VOS_STATUS status;
535 WLANTL_ACEnumType ac;
536 sme_QosWmmUpType up;
537 skb_list_node_t *pktNode = NULL;
538 hdd_list_node_t *anchor = NULL;
539 v_SIZE_t pktListSize = 0;
540 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
541 v_BOOL_t granted;
542
543 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
544
545 v_BOOL_t txSuspended = VOS_FALSE;
546
547 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
548
549 //Get TL AC corresponding to Qdisc queue index/AC.
550 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
551
552 //user priority from IP header, which is already extracted and set from
553 //select_queue call back function
554 up = skb->priority;
555
556 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
557
558#ifdef HDD_WMM_DEBUG
559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700560 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700561#endif // HDD_WMM_DEBUG
562
563 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Madan Mohan Koyyalamudi992cd442012-10-05 10:56:17 -0700564 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
565 * We check for +1 in the logic,to take care of Zero count which
566 * occurs very frequently in low traffic cases */
567 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
568 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s:Queue is Filling up.Inform TL again about pending packets", __func__);
Madan Mohan Koyyalamudi992cd442012-10-05 10:56:17 -0700570 WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pHddStaCtx->conn_info.staId[0], ac );
571 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700572 //If we have already reached the max queue size, disable the TX queue
573 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
574 {
575 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
576 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
577
578 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
579 pAdapter->isTxSuspended[ac] = VOS_TRUE;
580 txSuspended = VOS_TRUE;
581 }
582
583 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
584 if (VOS_TRUE == txSuspended)
585 {
Gopichand Nakkala8fbc3d42013-03-05 21:06:41 -0800586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700588 __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700589 return NETDEV_TX_BUSY;
590 }
591
592 //Use the skb->cb field to hold the list node information
593 pktNode = (skb_list_node_t *)&skb->cb;
594
595 //Stick the OS packet inside this node.
596 pktNode->skb = skb;
597
598 //Stick the User Priority inside this node
599 pktNode->userPriority = up;
600
601
602 INIT_LIST_HEAD(&pktNode->anchor);
603
604 //Insert the OS packet into the appropriate AC queue
605 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
606 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
607 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
608
609 if ( !VOS_IS_STATUS_SUCCESS( status ) )
610 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700611 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 -0700612 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
613 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
614 ++pAdapter->stats.tx_dropped;
615 kfree_skb(skb);
616 return NETDEV_TX_OK;
617 }
618
619 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
620 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
621
622 //Make sure we have access to this access category
623 if (likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) ||
624 ( pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
625 {
626 granted = VOS_TRUE;
627 }
628 else
629 {
630 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
631 }
632
633 if ( granted && ( pktListSize == 1 ))
634 {
635 //Let TL know we have a packet to send for this AC
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700636 //VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700637 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pHddStaCtx->conn_info.staId[0], ac );
638
639 if ( !VOS_IS_STATUS_SUCCESS( status ) )
640 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700641 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 -0700642
643 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
644 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
645 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
646 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
647 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
648 ++pAdapter->stats.tx_dropped;
649 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
650 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
651 kfree_skb(skb);
652 return NETDEV_TX_OK;
653 }
654 }
655
656 dev->trans_start = jiffies;
657
658 return NETDEV_TX_OK;
659}
660
661/**============================================================================
662 @brief hdd_tx_timeout() - Function called by OS if there is any
663 timeout during transmission. Since HDD simply enqueues packet
664 and returns control to OS right away, this would never be invoked
665
666 @param dev : [in] pointer to Libra network device
667 @return : None
668 ===========================================================================*/
669void hdd_tx_timeout(struct net_device *dev)
670{
schang6295e542013-03-12 15:31:23 -0700671 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
672 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
673
Jeff Johnson295189b2012-06-20 16:38:30 -0700674 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700675 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 //Getting here implies we disabled the TX queues for too long. Queues are
677 //disabled either because of disassociation or low resource scenarios. In
678 //case of disassociation it is ok to ignore this. But if associated, we have
679 //do possible recovery here
Madan Mohan Koyyalamudiea777012012-10-31 14:22:34 -0700680
681 //testing underlying data path stall
schangebd46b52013-03-14 16:28:41 -0700682 //FTM mode, data path is not initiated
683 if (VOS_FTM_MODE == hdd_get_conparam())
684 {
685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
686 "%s: FTM mode, how initiated TX?", __func__);
687 }
688 else
689 {
690 sme_transportDebug(hHal, 0, 1);
691 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700692}
693
694
695/**============================================================================
696 @brief hdd_stats() - Function registered with the Linux OS for
697 device TX/RX statistic
698
699 @param dev : [in] pointer to Libra network device
700
701 @return : pointer to net_device_stats structure
702 ===========================================================================*/
703struct net_device_stats* hdd_stats(struct net_device *dev)
704{
705 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
706
707 return &pAdapter->stats;
708}
709
710
711/**============================================================================
712 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
713 modules in HDD
714
715 @param pAdapter : [in] pointer to adapter context
716 @return : VOS_STATUS_E_FAILURE if any errors encountered
717 : VOS_STATUS_SUCCESS otherwise
718 ===========================================================================*/
719VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
720{
721 VOS_STATUS status = VOS_STATUS_SUCCESS;
722 v_SINT_t i = -1;
723
724 pAdapter->isVosOutOfResource = VOS_FALSE;
725
726 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
727 //Will be zeroed out during alloc
728
729 while (++i != NUM_TX_QUEUES)
730 {
731 pAdapter->isTxSuspended[i] = VOS_FALSE;
732 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
733 }
734
735 return status;
736}
737
738
739/**============================================================================
740 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
741 modules in HDD
742
743 @param pAdapter : [in] pointer to adapter context
744 @return : VOS_STATUS_E_FAILURE if any errors encountered
745 : VOS_STATUS_SUCCESS otherwise
746 ===========================================================================*/
747VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
748{
749 VOS_STATUS status = VOS_STATUS_SUCCESS;
750 v_SINT_t i = -1;
751
752 status = hdd_flush_tx_queues(pAdapter);
753 while (++i != NUM_TX_QUEUES)
754 {
755 //Free up actual list elements in the Tx queue
756 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
757 }
758
759 return status;
760}
761
762
763/**============================================================================
764 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
765 modules in HDD
766
767 @param pAdapter : [in] pointer to adapter context
768 @return : VOS_STATUS_E_FAILURE if any errors encountered
769 : VOS_STATUS_SUCCESS otherwise
770 ===========================================================================*/
771VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
772{
773 return hdd_flush_tx_queues(pAdapter);
774}
775
776
777/**============================================================================
778 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
779
780 @param pVosPacket : [in] pointer to vos packet
781 @return : VOS_TRUE if the packet is EAPOL
782 : VOS_FALSE otherwise
783 ===========================================================================*/
784
785v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
786{
787 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
788 v_BOOL_t fEAPOL = VOS_FALSE;
789 void *pBuffer = NULL;
790
791
792 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
793 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
794 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
795 {
796 if ( vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_802_1_X )
797 {
798 fEAPOL = VOS_TRUE;
799 }
800 }
801
802 return fEAPOL;
803}
804
805
806#ifdef FEATURE_WLAN_WAPI // Need to update this function
807/**============================================================================
808 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
809
810 @param pVosPacket : [in] pointer to vos packet
811 @return : VOS_TRUE if the packet is WAI
812 : VOS_FALSE otherwise
813 ===========================================================================*/
814
815v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
816{
817 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
818 v_BOOL_t fIsWAI = VOS_FALSE;
819 void *pBuffer = NULL;
820
821 // Need to update this function
822 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
823 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
824
825 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
826 {
827 if ( vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_WAI)
828 {
829 fIsWAI = VOS_TRUE;
830 }
831 }
832
833 return fIsWAI;
834}
835#endif /* FEATURE_WLAN_WAPI */
836
837/**============================================================================
838 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
839 to indicate that a packet has been transmitted across the SDIO bus
840 succesfully. OS packet resources can be released after this cbk.
841
842 @param vosContext : [in] pointer to VOS context
843 @param pVosPacket : [in] pointer to VOS packet (containing skb)
844 @param vosStatusIn : [in] status of the transmission
845
846 @return : VOS_STATUS_E_FAILURE if any errors encountered
847 : VOS_STATUS_SUCCESS otherwise
848 ===========================================================================*/
849VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
850 vos_pkt_t *pVosPacket,
851 VOS_STATUS vosStatusIn )
852{
853 VOS_STATUS status = VOS_STATUS_SUCCESS;
854 hdd_adapter_t *pAdapter = NULL;
855 hdd_context_t *pHddCtx = NULL;
856 void* pOsPkt = NULL;
857
858 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
859 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700861 return VOS_STATUS_E_FAILURE;
862 }
863
864 //Return the skb to the OS
865 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
866 if(!VOS_IS_STATUS_SUCCESS( status ))
867 {
868 //This is bad but still try to free the VOSS resources if we can
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700870 vos_pkt_return_packet( pVosPacket );
871 return VOS_STATUS_E_FAILURE;
872 }
873
874 //Get the HDD context.
875 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
876 //Get the Adapter context.
877 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
878 if(pAdapter == NULL)
879 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700881 }
882 else
883 {
884 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
885 }
886
887 kfree_skb((struct sk_buff *)pOsPkt);
888
889 //Return the VOS packet resources.
890 status = vos_pkt_return_packet( pVosPacket );
891 if(!VOS_IS_STATUS_SUCCESS( status ))
892 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700894 }
895
896 return status;
897}
898
899
900/**============================================================================
901 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
902 fetch a packet for transmission.
903
904 @param vosContext : [in] pointer to VOS context
905 @param staId : [in] Station for which TL is requesting a pkt
906 @param ac : [in] access category requested by TL
907 @param pVosPacket : [out] pointer to VOS packet packet pointer
908 @param pPktMetaInfo : [out] pointer to meta info for the pkt
909
910 @return : VOS_STATUS_E_EMPTY if no packets to transmit
911 : VOS_STATUS_E_FAILURE if any errors encountered
912 : VOS_STATUS_SUCCESS otherwise
913 ===========================================================================*/
914VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
915 v_U8_t *pStaId,
916 WLANTL_ACEnumType ac,
917 vos_pkt_t **ppVosPacket,
918 WLANTL_MetaInfoType *pPktMetaInfo )
919{
920 VOS_STATUS status = VOS_STATUS_E_FAILURE;
921 hdd_adapter_t *pAdapter = NULL;
922 hdd_context_t *pHddCtx = NULL;
923 hdd_list_node_t *anchor = NULL;
924 skb_list_node_t *pktNode = NULL;
925 struct sk_buff *skb = NULL;
926 vos_pkt_t *pVosPacket = NULL;
927 v_MACADDR_t* pDestMacAddress = NULL;
928 v_TIME_t timestamp;
929 WLANTL_ACEnumType newAc;
930 v_SIZE_t size = 0;
931 tANI_U8 acAdmitted, i;
932
933 //Sanity check on inputs
934 if ( ( NULL == vosContext ) ||
935 ( NULL == pStaId ) ||
936 ( NULL == ppVosPacket ) ||
937 ( NULL == pPktMetaInfo ) )
938 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700940 return VOS_STATUS_E_FAILURE;
941 }
942
943 //Get the HDD context.
944 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
945 if(pHddCtx == NULL)
946 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700948 return VOS_STATUS_E_FAILURE;
949 }
950
951 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
952 if( NULL == pAdapter )
953 {
954 VOS_ASSERT(0);
955 return VOS_STATUS_E_FAILURE;
956 }
957
958 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
959
960 *ppVosPacket = NULL;
961
962 //Make sure the AC being asked for is sane
963 if( ac >= WLANTL_MAX_AC || ac < 0)
964 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700966 return VOS_STATUS_E_FAILURE;
967 }
968
969 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
970
971#ifdef HDD_WMM_DEBUG
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700973#endif // HDD_WMM_DEBUG
974
975 // We find an AC with packets
976 // or we determine we have no more packets to send
977 // HDD is not allowed to change AC.
978
979 // has this AC been admitted? or
980 // To allow EAPOL packets when not authenticated
981 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
982 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
983 {
984 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
985#ifdef HDD_WMM_DEBUG
986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700987 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700988#endif // HDD_WMM_DEBUG
989 return VOS_STATUS_E_FAILURE;
990 }
991
992 // do we have any packets pending in this AC?
993 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
994 if( size > 0 )
995 {
996 // yes, so process it
997#ifdef HDD_WMM_DEBUG
998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700999 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001000#endif // HDD_WMM_DEBUG
1001 }
1002 else
1003 {
1004 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1005#ifdef HDD_WMM_DEBUG
1006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001007 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001008#endif // HDD_WMM_DEBUG
1009 return VOS_STATUS_E_FAILURE;
1010 }
1011
1012 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1013 //This simplifies the locking and unlocking of Tx queue
1014 status = vos_pkt_wrap_data_packet( &pVosPacket,
1015 VOS_PKT_TYPE_TX_802_3_DATA,
1016 NULL, //OS Pkt is not being passed
1017 hdd_tx_low_resource_cbk,
1018 pAdapter );
1019
1020 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1021 {
1022 //Remember VOS is in a low resource situation
1023 pAdapter->isVosOutOfResource = VOS_TRUE;
1024 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001026 //TL will now think we have no more packets in this AC
1027 return VOS_STATUS_E_FAILURE;
1028 }
1029
1030 //Remove the packet from the queue
1031 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1032 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1033 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1034
1035 if(VOS_STATUS_SUCCESS == status)
1036 {
1037 //If success then we got a valid packet from some AC
1038 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1039 skb = pktNode->skb;
1040 }
1041 else
1042 {
1043 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -07001044 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001045 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001046 vos_pkt_return_packet(pVosPacket);
1047 return VOS_STATUS_E_FAILURE;
1048 }
1049
1050 //Attach skb to VOS packet.
1051 status = vos_pkt_set_os_packet( pVosPacket, skb );
1052 if (status != VOS_STATUS_SUCCESS)
1053 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001055 vos_pkt_return_packet(pVosPacket);
1056 ++pAdapter->stats.tx_dropped;
1057 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1058 kfree_skb(skb);
1059 return VOS_STATUS_E_FAILURE;
1060 }
1061
1062 //Just being paranoid. To be removed later
1063 if(pVosPacket == NULL)
1064 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001065 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 -07001066 ++pAdapter->stats.tx_dropped;
1067 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1068 kfree_skb(skb);
1069 return VOS_STATUS_E_FAILURE;
1070 }
1071
Chilam NG571c65a2013-01-19 12:27:36 +05301072#ifdef FEATURE_WLAN_TDLS
1073 {
1074 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301075 u8 mac[6];
1076
Hoonki Lee387663d2013-02-05 18:08:43 -08001077 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301078
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001079 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
Chilam NG571c65a2013-01-19 12:27:36 +05301080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1081 "broadcast packet, not adding to peer list");
1082 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1083 mac, 6) != 0) {
1084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1085 "extract mac:%x %x %x %x %x %x",
1086 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
1087
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001088 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301089 } else {
1090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1091 "packet da is bssid, not adding to peer list");
1092 }
1093 }
1094#endif
1095
Jeff Johnson295189b2012-06-20 16:38:30 -07001096 //Return VOS packet to TL;
1097 *ppVosPacket = pVosPacket;
1098
1099 //Fill out the meta information needed by TL
1100 //FIXME This timestamp is really the time stamp of wrap_data_packet
1101 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1102 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1103
1104 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1105 pPktMetaInfo->ucIsEapol = 0;
1106 else
1107 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1108
1109#ifdef FEATURE_WLAN_WAPI
1110 // Override usIsEapol value when its zero for WAPI case
1111 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
1112#endif /* FEATURE_WLAN_WAPI */
1113
1114 if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) ||
1115 (!pAdapter->hddWmmStatus.wmmQap))
1116 {
1117 // either we don't want QoS or the AP doesn't support QoS
1118 pPktMetaInfo->ucUP = 0;
1119 pPktMetaInfo->ucTID = 0;
1120 }
1121 else
1122 {
1123 /* 1. Check if ACM is set for this AC
1124 * 2. If set, check if this AC had already admitted
1125 * 3. If not already admitted, downgrade the UP to next best UP */
1126 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
1127 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid)
1128 {
1129 pPktMetaInfo->ucUP = pktNode->userPriority;
1130 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1131 }
1132 else
1133 {
1134 //Downgrade the UP
1135 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1136 newAc = WLANTL_AC_BK;
1137 for (i=ac-1; i>0; i--)
1138 {
1139 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1140 {
1141 newAc = i;
1142 break;
1143 }
1144 }
1145 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1146 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP);
1148 }
1149 }
1150
1151 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1152 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1153 if ( 1 < size )
1154 {
1155 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1156 }
1157 else
1158 {
1159 pPktMetaInfo->bMorePackets = 0;
1160 }
1161
1162 //Extract the destination address from ethernet frame
1163 pDestMacAddress = (v_MACADDR_t*)skb->data;
1164 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1165 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1166
1167
1168
1169 // if we are in a backpressure situation see if we can turn the hose back on
1170 if ( (pAdapter->isTxSuspended[ac]) &&
1171 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1172 {
1173 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1174 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
Gopichand Nakkala8fbc3d42013-03-05 21:06:41 -08001175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001176 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001177 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1178 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1179 skb_get_queue_mapping(skb) ));
1180 }
1181
1182
1183 // We're giving the packet to TL so consider it transmitted from
1184 // a statistics perspective. We account for it here instead of
1185 // when the packet is returned for two reasons. First, TL will
1186 // manipulate the skb to the point where the len field is not
1187 // accurate, leading to inaccurate byte counts if we account for
1188 // it later. Second, TL does not provide any feedback as to
1189 // whether or not the packet was successfully sent over the air,
1190 // so the packet counts will be the same regardless of where we
1191 // account for them
1192 pAdapter->stats.tx_bytes += skb->len;
1193 ++pAdapter->stats.tx_packets;
1194 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1195 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1196
1197 if(pHddCtx->cfg_ini->thermalMitigationEnable)
1198 {
1199 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1200 {
1201 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001202 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001203 return VOS_STATUS_E_FAILURE;
1204 }
1205 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1206 {
1207 if(0 == pHddCtx->tmInfo.txFrameCount)
1208 {
1209 /* Just recovered from sleep timeout */
1210 pHddCtx->tmInfo.lastOpenTs = timestamp;
1211 }
1212
1213 if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1214 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1215 {
1216 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
1217 /* During TX open duration, TX frame count is larger than threshold
1218 * Block TX during Sleep time */
1219 netif_tx_stop_all_queues(pAdapter->dev);
1220 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
1221 pHddCtx->tmInfo.lastblockTs = timestamp;
1222 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1223 {
1224 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1225 }
1226 }
1227 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1228 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1229 {
1230 /* During TX open duration, TX frame count is less than threshold
1231 * Reset count and timestamp to prepare next cycle */
1232 pHddCtx->tmInfo.lastOpenTs = timestamp;
1233 pHddCtx->tmInfo.txFrameCount = 0;
1234 }
1235 else
1236 {
1237 /* Do Nothing */
1238 }
1239 pHddCtx->tmInfo.txFrameCount++;
1240 }
1241 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1242 }
1243
1244
1245#ifdef HDD_WMM_DEBUG
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001246 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 -07001247#endif // HDD_WMM_DEBUG
1248
1249 return status;
1250}
1251
1252
1253/**============================================================================
1254 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1255 case where VOS packets are not available at the time of the call to get
1256 packets. This callback function is invoked by VOS when packets are
1257 available.
1258
1259 @param pVosPacket : [in] pointer to VOS packet
1260 @param userData : [in] opaque user data that was passed initially
1261
1262 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1263 : VOS_STATUS_SUCCESS otherwise
1264 =============================================================================*/
1265VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1266 v_VOID_t *userData )
1267{
1268 VOS_STATUS status;
1269 v_SINT_t i = 0;
1270 v_SIZE_t size = 0;
1271 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1272
1273 if(pAdapter == NULL)
1274 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 return VOS_STATUS_E_FAILURE;
1277 }
1278
1279 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1280 //situation. Here we will only signal TL that there is a pending data for a STA.
1281 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1282 vos_pkt_return_packet( pVosPacket );
1283
1284 pAdapter->isVosOutOfResource = VOS_FALSE;
1285
1286 //Indicate to TL that there is pending data if a queue is non empty
1287 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1288 {
1289 size = 0;
1290 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1291 if ( size > 0 )
1292 {
1293 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1294 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1295 (WLANTL_ACEnumType)i );
1296 if( !VOS_IS_STATUS_SUCCESS( status ) )
1297 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure in indicating pkt to TL for ac=%d", __func__,i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001299 }
1300 }
1301 }
1302
1303 return VOS_STATUS_SUCCESS;
1304}
1305
1306
1307/**============================================================================
1308 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1309 TL will call this to notify the HDD when one or more packets were
1310 received for a registered STA.
1311
1312 @param vosContext : [in] pointer to VOS context
1313 @param pVosPacketChain : [in] pointer to VOS packet chain
1314 @param staId : [in] Station Id
1315 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1316
1317 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1318 : VOS_STATUS_SUCCESS otherwise
1319 ===========================================================================*/
1320VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1321 vos_pkt_t *pVosPacketChain,
1322 v_U8_t staId,
1323 WLANTL_RxMetaInfoType* pRxMetaInfo )
1324{
1325 hdd_adapter_t *pAdapter = NULL;
1326 hdd_context_t *pHddCtx = NULL;
1327 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1328 int rxstat;
1329 struct sk_buff *skb = NULL;
1330 vos_pkt_t* pVosPacket;
1331 vos_pkt_t* pNextVosPacket;
1332
1333 //Sanity check on inputs
1334 if ( ( NULL == vosContext ) ||
1335 ( NULL == pVosPacketChain ) ||
1336 ( NULL == pRxMetaInfo ) )
1337 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001339 return VOS_STATUS_E_FAILURE;
1340 }
1341
1342 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1343 if ( NULL == pHddCtx )
1344 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001346 return VOS_STATUS_E_FAILURE;
1347 }
1348
1349 pAdapter = pHddCtx->sta_to_adapter[staId];
1350 if( NULL == pAdapter )
1351 {
1352 VOS_ASSERT(0);
1353 return VOS_STATUS_E_FAILURE;
1354 }
1355
1356 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1357
1358 // walk the chain until all are processed
1359 pVosPacket = pVosPacketChain;
1360 do
1361 {
1362 // get the pointer to the next packet in the chain
1363 // (but don't unlink the packet since we free the entire chain later)
1364 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1365
1366 // both "success" and "empty" are acceptable results
1367 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1368 {
1369 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 return VOS_STATUS_E_FAILURE;
1372 }
1373
1374 // Extract the OS packet (skb).
1375 // Tell VOS to detach the OS packet from the VOS packet
1376 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1377 if(!VOS_IS_STATUS_SUCCESS( status ))
1378 {
1379 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001381 return VOS_STATUS_E_FAILURE;
1382 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001383
1384 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1385 {
1386 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1387 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
1388 return eHAL_STATUS_FAILURE;
1389 }
1390
Chilam Ng1279e232013-01-25 15:06:52 -08001391#ifdef FEATURE_WLAN_TDLS
1392 {
1393 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08001394 u8 mac[6];
1395
Hoonki Lee387663d2013-02-05 18:08:43 -08001396 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08001397
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001398 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
Chilam Ng1279e232013-01-25 15:06:52 -08001399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1400 "rx broadcast packet, not adding to peer list");
1401 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1402 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001403 hddTdlsPeer_t *curr_peer;
Chilam Ng1279e232013-01-25 15:06:52 -08001404 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001405 "rx extract mac:" MAC_ADDRESS_STR,
1406 MAC_ADDR_ARRAY(mac) );
1407 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
1408 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status))
1409 {
1410 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
1411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
1412 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
1413 }
Chilam Ng1279e232013-01-25 15:06:52 -08001414 } else {
1415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1416 "rx packet sa is bssid, not adding to peer list");
1417 }
1418 }
1419#endif
1420
Jeff Johnson295189b2012-06-20 16:38:30 -07001421 skb->dev = pAdapter->dev;
1422 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001423 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001424 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1425 ++pAdapter->stats.rx_packets;
1426 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001427#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001428#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1429 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1430#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001431#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001432 rxstat = netif_rx_ni(skb);
1433 if (NET_RX_SUCCESS == rxstat)
1434 {
1435 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
1436 }
1437 else
1438 {
1439 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1440 }
1441 // now process the next packet in the chain
1442 pVosPacket = pNextVosPacket;
1443
1444 } while (pVosPacket);
1445
1446 //Return the entire VOS packet chain to the resource pool
1447 status = vos_pkt_return_packet( pVosPacketChain );
1448 if(!VOS_IS_STATUS_SUCCESS( status ))
1449 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001451 }
1452
1453 pAdapter->dev->last_rx = jiffies;
1454
1455 return status;
1456}
1457