blob: 36e451d373148776f198985f99aacfdd1e72deac [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
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530184 pAdapter->isVosLowResource = VOS_FALSE;
185
Jeff Johnson295189b2012-06-20 16:38:30 -0700186 while (++i != NUM_TX_QUEUES)
187 {
188 //Free up any packets in the Tx queue
189 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
190 while (true)
191 {
192 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
193 if(VOS_STATUS_E_EMPTY != status)
194 {
195 pktNode = list_entry(anchor, skb_list_node_t, anchor);
196 skb = pktNode->skb;
197 //TODO
198 //++pAdapter->stats.tx_dropped;
199 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
200 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
201 kfree_skb(skb);
202 continue;
203 }
204 break;
205 }
206 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
207 // backpressure is no longer in effect
208 pAdapter->isTxSuspended[i] = VOS_FALSE;
209 }
210
211 return status;
212}
213
Ravi Joshif9520d62013-10-18 04:11:46 -0700214/**============================================================================
215 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
216 in IBSS mode
217
218 @param pAdapter : [in] pointer to adapter context
219 : [in] Staion Id
220 @return : VOS_STATUS_E_FAILURE if any errors encountered
221 : VOS_STATUS_SUCCESS otherwise
222 ===========================================================================*/
223void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
224{
225 v_U8_t i;
226 skb_list_node_t *pktNode = NULL;
227 struct sk_buff *skb = NULL;
228 v_U8_t skbStaIdx;
229 hdd_list_node_t *tmp = NULL;
230 struct netdev_queue *txq;
231
232 for (i = 0; i < NUM_TX_QUEUES; i++)
233 {
234 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
235
236 if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) )
237 {
238 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
239 continue;
240 }
241
242 /* Iterate through the queue and identify the data for STAId */
243 list_for_each(tmp, &pAdapter->wmm_tx_queue[i].anchor)
244 {
245 hdd_list_node_t *tmpNext = NULL;
246
247 pktNode = list_entry(tmp, skb_list_node_t, anchor);
248 if (pktNode != NULL)
249 {
250 skb = pktNode->skb;
251
252 /* Get the STAId from data */
253 skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
254 if (skbStaIdx == STAId)
255 {
256 tmpNext = tmp->next;
257
258 /* Data for STAId is freed along with the queue node */
259 kfree_skb(skb);
260 list_del(tmp);
261 tmp = tmpNext;
262
263 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
264 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
265 pAdapter->wmm_tx_queue[i].count--;
266 }
267 }
268 }
269
270 /* Restart the queue only-if suspend and the queue was flushed */
271 txq = netdev_get_tx_queue(pAdapter->dev, i);
272 if ( (pAdapter->wmm_tx_queue[i].count <
273 pAdapter->wmm_tx_queue[i].max_size) &&
274 (netif_tx_queue_stopped(txq)))
275 {
276 netif_tx_start_queue(txq);
277 }
278
279 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
280 }
281}
282
Jeff Johnson295189b2012-06-20 16:38:30 -0700283static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
284{
285 skb_list_node_t *pktNode = NULL;
286 struct sk_buff *skb = NULL;
287 v_SIZE_t size = 0;
288 WLANTL_ACEnumType ac = 0;
289 VOS_STATUS status = VOS_STATUS_E_FAILURE;
290 hdd_list_node_t *anchor = NULL;
291
292 if( NULL == pAdapter )
293 {
294 VOS_ASSERT(0);
295 return NULL;
296 }
297
298 // do we have any packets pending in this AC?
299 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
300 if( size == 0 )
301 {
302 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700303 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 return NULL;
305 }
306
307 //Remove the packet from the queue
308 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
309 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
310 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
311
312 if(VOS_STATUS_SUCCESS == status)
313 {
314 //If success then we got a valid packet from some AC
315 pktNode = list_entry(anchor, skb_list_node_t, anchor);
316 skb = pktNode->skb;
317 }
318 else
319 {
320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
321 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700322 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323
324 return NULL;
325 }
326
327 // if we are in a backpressure situation see if we can turn the hose back on
328 if ( (pAdapter->isTxSuspended[ac]) &&
329 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
330 {
331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700332 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700333 pAdapter->isTxSuspended[ac] = VOS_FALSE;
334 /* Enable Queues which we have disabled earlier */
335 netif_tx_start_all_queues( pAdapter->dev );
336 }
337
338 return skb;
339}
340
341void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
342{
343 hdd_cfg80211_state_t *cfgState;
344 struct sk_buff* skb;
345 hdd_adapter_t* pMonAdapter = NULL;
346 struct ieee80211_hdr *hdr;
347
348 if (pAdapter == NULL )
349 {
350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
351 "%s: pAdapter is NULL", __func__);
352 return;
353 }
354
355 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
356
357 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
358
359 if( NULL != cfgState->buf )
360 {
361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
362 "%s: Already one MGMT packet Tx going on", __func__);
363 return;
364 }
365
366 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
367
368 if (NULL == skb)
369 {
370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
371 "%s: No Packet Pending", __func__);
372 return;
373 }
374
375 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
376 if( cfgState->buf == NULL )
377 {
378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
379 "%s: Failed to Allocate memory", __func__);
380 goto fail;
381 }
382
383 cfgState->len = skb->len;
384
385 vos_mem_copy( cfgState->buf, skb->data, skb->len);
386
387 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800388 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700389
390 hdr = (struct ieee80211_hdr *)skb->data;
391 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
392 == HDD_FRAME_TYPE_MGMT )
393 {
394 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
395 == HDD_FRAME_SUBTYPE_DEAUTH )
396 {
397 hdd_softap_sta_deauth( pAdapter, hdr->addr1 );
398 goto mgmt_handled;
399 }
400 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
401 == HDD_FRAME_SUBTYPE_DISASSOC )
402 {
403 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
404 goto mgmt_handled;
405 }
406 }
407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
408 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
409
Jeff Johnson43971f52012-07-17 12:26:56 -0700410 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700411 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700412 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700413 {
414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
415 "%s: WLANSAP_SendAction returned fail", __func__);
416 hdd_sendActionCnf( pAdapter, FALSE );
417 }
418 return;
419
420mgmt_handled:
421 hdd_sendActionCnf( pAdapter, TRUE );
422 return;
423fail:
424 kfree_skb(pAdapter->skb_to_tx);
425 pAdapter->skb_to_tx = NULL;
426 return;
427}
428
429void hdd_mon_tx_work_queue(struct work_struct *work)
430{
431 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
432 hdd_mon_tx_mgmt_pkt(pAdapter);
433}
434
435int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
436{
437 v_U16_t rt_hdr_len;
438 struct ieee80211_hdr *hdr;
439 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
440 struct ieee80211_radiotap_header *rtap_hdr =
441 (struct ieee80211_radiotap_header *)skb->data;
442
443 /*Supplicant sends the EAPOL packet on monitor interface*/
444 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
445 if(pPgBkAdapter == NULL)
446 {
447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
448 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
449 __func__);
450 goto fail; /* too short to be possibly valid */
451 }
452
453 /* check if toal skb length is greater then radio tab header length of not */
454 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
455 goto fail; /* too short to be possibly valid */
456
457 /* check if radio tap header version is correct or not */
458 if (unlikely(rtap_hdr->it_version))
459 goto fail; /* only version 0 is supported */
460
461 /*Strip off the radio tap header*/
462 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
463
464 /* check if skb length if greator then total radio tap header length ot not*/
465 if (unlikely(skb->len < rt_hdr_len))
466 goto fail;
467
468 /* Update the trans_start for this netdev */
469 dev->trans_start = jiffies;
470 /*
471 * fix up the pointers accounting for the radiotap
472 * header still being in there.
473 */
474 skb_set_mac_header(skb, rt_hdr_len);
475 skb_set_network_header(skb, rt_hdr_len);
476 skb_set_transport_header(skb, rt_hdr_len);
477
478 /* Pull rtap header out of the skb */
479 skb_pull(skb, rt_hdr_len);
480
481 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
482 * radio tap header and 802.11 header starts
483 */
484 hdr = (struct ieee80211_hdr *)skb->data;
485
486 /* Send data frames through the normal Data path. In this path we will
487 * conver rcvd 802.11 packet to 802.3 packet */
488 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
489 {
490 v_U8_t da[6];
491 v_U8_t sa[6];
492
493 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
494 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
495
496 /* Pull 802.11 MAC header */
497 skb_pull(skb, HDD_80211_HEADER_LEN);
498
499 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
500 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
501 {
502 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
503 }
504
505 /* Pull LLC header */
506 skb_pull(skb, HDD_LLC_HDR_LEN);
507
508 /* Create space for Ethernet header */
509 skb_push(skb, HDD_MAC_HDR_SIZE*2);
510 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
511 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
512
513 /* Only EAPOL Data packets are allowed through monitor interface */
514 if (vos_be16_to_cpu(
515 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
516 != HDD_ETHERTYPE_802_1_X)
517 {
518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
519 "%s: Not a Eapol packet. Drop this frame", __func__);
520 //If not EAPOL frames, drop them.
521 kfree_skb(skb);
522 return NETDEV_TX_OK;
523 }
524
525 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
526
527 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
528 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
529 }
530 else
531 {
532 VOS_STATUS status;
533 WLANTL_ACEnumType ac = 0;
534 skb_list_node_t *pktNode = NULL;
535 v_SIZE_t pktListSize = 0;
536
537 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
538 //If we have already reached the max queue size, disable the TX queue
539 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
540 {
541 /* We want to process one packet at a time, so lets disable all TX queues
542 * and re-enable the queues once we get TX feedback for this packet */
543 netif_tx_stop_all_queues(pAdapter->dev);
544 pAdapter->isTxSuspended[ac] = VOS_TRUE;
545 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
546 return NETDEV_TX_BUSY;
547 }
548 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
549
550 //Use the skb->cb field to hold the list node information
551 pktNode = (skb_list_node_t *)&skb->cb;
552
553 //Stick the OS packet inside this node.
554 pktNode->skb = skb;
555
556 INIT_LIST_HEAD(&pktNode->anchor);
557
558 //Insert the OS packet into the appropriate AC queue
559 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
560 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
561 &pktNode->anchor, &pktListSize );
562 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
563
564 if ( !VOS_IS_STATUS_SUCCESS( status ) )
565 {
566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700567 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700568 kfree_skb(skb);
569 return NETDEV_TX_OK;
570 }
571
572 if ( pktListSize == 1 )
573 {
574 /* In this context we cannot acquire any mutex etc. And to transmit
575 * this packet we need to call SME API. So to take care of this we will
576 * schedule a workqueue
577 */
578 schedule_work(&pPgBkAdapter->monTxWorkQueue);
579 }
580 return NETDEV_TX_OK;
581 }
582
583fail:
584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
585 "%s: Packet Rcvd at Monitor interface is not proper,"
586 " Dropping the packet",
587 __func__);
588 kfree_skb(skb);
589 return NETDEV_TX_OK;
590}
Jeff Johnson295189b2012-06-20 16:38:30 -0700591/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530592 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700593 transmitting packets. There are 2 versions of this function. One that uses
594 locked queue and other that uses lockless queues. Both have been retained to
595 do some performance testing
596
597 @param skb : [in] pointer to OS packet (sk_buff)
598 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530599
Jeff Johnson295189b2012-06-20 16:38:30 -0700600 @return : NET_XMIT_DROP if packets are dropped
601 : NET_XMIT_SUCCESS if packet is enqueued succesfully
602 ===========================================================================*/
603int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
604{
605 VOS_STATUS status;
606 WLANTL_ACEnumType ac;
607 sme_QosWmmUpType up;
608 skb_list_node_t *pktNode = NULL;
609 hdd_list_node_t *anchor = NULL;
610 v_SIZE_t pktListSize = 0;
611 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
612 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700613 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700614 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 v_BOOL_t txSuspended = VOS_FALSE;
616
617 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
618
Ravi Joshif9520d62013-10-18 04:11:46 -0700619 if (unlikely(netif_subqueue_stopped(dev, skb))) {
620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
621 "%s is called when netif TX %d is disabled",
622 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530623 return NETDEV_TX_BUSY;
624 }
625
Ravi Joshicc57ed42013-10-12 16:31:25 -0700626 //Get TL AC corresponding to Qdisc queue index/AC.
627 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
628
629 if (WLAN_HDD_IBSS == pAdapter->device_mode)
Shailender Karmuchia734f332013-04-19 14:02:48 -0700630 {
631 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
632
Ravi Joshif9520d62013-10-18 04:11:46 -0700633 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
Ravi Joshicc57ed42013-10-12 16:31:25 -0700634 {
635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
636 "%s: Tx frame in disconnected state in IBSS mode", __func__);
637 ++pAdapter->stats.tx_dropped;
638 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
639 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
640 kfree_skb(skb);
641 return NETDEV_TX_OK;
642 }
643
Shailender Karmuchia734f332013-04-19 14:02:48 -0700644 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
645
646 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
647 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
648 vos_is_macaddr_group(pDestMacAddress)))
649 {
650 STAId = IBSS_BROADCAST_STAID;
651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
Ravi Joshif9520d62013-10-18 04:11:46 -0700652 "%s: BC/MC packet", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700653 }
654 else if (STAId == HDD_WLAN_INVALID_STA_ID)
655 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshif9520d62013-10-18 04:11:46 -0700657 "%s: Received Unicast frame with invalid staID", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700658 ++pAdapter->stats.tx_dropped;
659 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700660 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Shailender Karmuchia734f332013-04-19 14:02:48 -0700661 kfree_skb(skb);
662 return NETDEV_TX_OK;
663 }
664 }
665 else
666 {
667 STAId = pHddStaCtx->conn_info.staId[0];
668 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700669
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530670 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700671 //select_queue call back function
672 up = skb->priority;
673
674 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
675
676#ifdef HDD_WMM_DEBUG
677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700678 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700679#endif // HDD_WMM_DEBUG
680
681 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700682 /*CR 463598,384996*/
683 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
684 *We check for +1 in the logic,to take care of Zero count which
685 *occurs very frequently in low traffic cases */
686 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
687 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700688 /* 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 -0700689 * if it is in the mainline code and if the log level is enabled by someone for debugging
690 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 -0700691
Ravi Joshi8a934352013-09-25 16:46:58 -0700692 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
693 STAId, ac
694 );
695 if ( !VOS_IS_STATUS_SUCCESS( status ) )
696 {
697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
698 "%s: WLANTL_STAPktPending() returned error code %d",
699 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700700 ++pAdapter->stats.tx_dropped;
701 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
702 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Ravi Joshi8a934352013-09-25 16:46:58 -0700703 kfree_skb(skb);
704 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
705 return NETDEV_TX_OK;
706 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700707 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700708 //If we have already reached the max queue size, disable the TX queue
709 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
710 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700711 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
712 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
713 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
714 pAdapter->isTxSuspended[ac] = VOS_TRUE;
715 txSuspended = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700716 }
717
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530718 /* If 3/4th of the max queue size is used then enable the flag.
719 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
720 if (WLANTL_AC_BE == ac)
721 {
722 if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
723 {
724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
725 "%s: Best Effort AC Tx queue is 3/4th full", __func__);
726 pAdapter->isVosLowResource = VOS_TRUE;
727 }
728 else
729 {
730 pAdapter->isVosLowResource = VOS_FALSE;
731 }
732 }
733
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530734 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700735 if (VOS_TRUE == txSuspended)
736 {
Gopichand Nakkala8fbc3d42013-03-05 21:06:41 -0800737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530738 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700739 __func__, ac );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530740 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 }
742
743 //Use the skb->cb field to hold the list node information
744 pktNode = (skb_list_node_t *)&skb->cb;
745
746 //Stick the OS packet inside this node.
747 pktNode->skb = skb;
748
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530749 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700750 pktNode->userPriority = up;
751
752
753 INIT_LIST_HEAD(&pktNode->anchor);
754
755 //Insert the OS packet into the appropriate AC queue
756 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
757 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
758 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
759
760 if ( !VOS_IS_STATUS_SUCCESS( status ) )
761 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700762 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 -0700763 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
764 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
765 ++pAdapter->stats.tx_dropped;
766 kfree_skb(skb);
767 return NETDEV_TX_OK;
768 }
769
770 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
771 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700772 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700773
Kiet Lamf040f472013-11-20 21:15:23 +0530774 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
775 {
776 /* Function which will determine acquire admittance for a
777 * WMM AC is required or not based on psb configuration done
778 * in the framework
779 */
780 hdd_wmm_acquire_access_required(pAdapter, ac);
781 }
782
Jeff Johnson295189b2012-06-20 16:38:30 -0700783 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530784 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
785 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700786 {
787 granted = VOS_TRUE;
788 }
789 else
790 {
791 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530792 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700793 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700794 if ( granted && ( pktListSize == 1 ))
795 {
796 //Let TL know we have a packet to send for this AC
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700797 //VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700798 status = WLANTL_STAPktPending(
799 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
800 STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700801 if ( !VOS_IS_STATUS_SUCCESS( status ) )
802 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700803 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 -0700804
805 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
806 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
807 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
808 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
809 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
810 ++pAdapter->stats.tx_dropped;
811 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
812 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
813 kfree_skb(skb);
814 return NETDEV_TX_OK;
815 }
816 }
817
818 dev->trans_start = jiffies;
819
820 return NETDEV_TX_OK;
821}
822
823/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -0700824 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
825
826 @param pHddStaCtx : [in] pointer to HDD Station Context
827 pMacAddress [in] pointer to Peer Mac address
828 staID [out] pointer to Station Index
829 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
830 ===========================================================================*/
831
832VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
833{
834 v_U8_t idx;
835
836 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
837 {
838 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
839 pMacAddress, sizeof(v_MACADDR_t)))
840 {
841 *staId = pHddStaCtx->conn_info.staId[idx];
842 return VOS_STATUS_SUCCESS;
843 }
844 }
845
846 return VOS_STATUS_E_FAILURE;
847}
848
849/**============================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 @brief hdd_tx_timeout() - Function called by OS if there is any
851 timeout during transmission. Since HDD simply enqueues packet
852 and returns control to OS right away, this would never be invoked
853
854 @param dev : [in] pointer to Libra network device
855 @return : None
856 ===========================================================================*/
857void hdd_tx_timeout(struct net_device *dev)
858{
Ravi Joshicc57ed42013-10-12 16:31:25 -0700859 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
860 struct netdev_queue *txq;
861 int i = 0;
862
Jeff Johnson295189b2012-06-20 16:38:30 -0700863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700864 "%s: Transmission timeout occurred", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700865 //Getting here implies we disabled the TX queues for too long. Queues are
866 //disabled either because of disassociation or low resource scenarios. In
867 //case of disassociation it is ok to ignore this. But if associated, we have
868 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -0700869
Ravi Joshif9520d62013-10-18 04:11:46 -0700870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700871 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
872 pAdapter->wmm_tx_queue[0].count,
873 pAdapter->wmm_tx_queue[1].count,
874 pAdapter->wmm_tx_queue[2].count,
875 pAdapter->wmm_tx_queue[3].count);
876
Ravi Joshif9520d62013-10-18 04:11:46 -0700877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700878 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
879 pAdapter->isTxSuspended[0],
880 pAdapter->isTxSuspended[1],
881 pAdapter->isTxSuspended[2],
882 pAdapter->isTxSuspended[3]);
883
884 for (i = 0; i < 8; i++)
885 {
886 txq = netdev_get_tx_queue(dev, i);
Ravi Joshif9520d62013-10-18 04:11:46 -0700887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700888 "Queue%d status: %d", i, netif_tx_queue_stopped(txq));
889 }
890
Ravi Joshif9520d62013-10-18 04:11:46 -0700891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700892 "carrier state: %d", netif_carrier_ok(dev));
Jeff Johnson295189b2012-06-20 16:38:30 -0700893}
894
895
896/**============================================================================
897 @brief hdd_stats() - Function registered with the Linux OS for
898 device TX/RX statistic
899
900 @param dev : [in] pointer to Libra network device
901
902 @return : pointer to net_device_stats structure
903 ===========================================================================*/
904struct net_device_stats* hdd_stats(struct net_device *dev)
905{
906 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
907
908 return &pAdapter->stats;
909}
910
911
912/**============================================================================
913 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
914 modules in HDD
915
916 @param pAdapter : [in] pointer to adapter context
917 @return : VOS_STATUS_E_FAILURE if any errors encountered
918 : VOS_STATUS_SUCCESS otherwise
919 ===========================================================================*/
920VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
921{
922 VOS_STATUS status = VOS_STATUS_SUCCESS;
923 v_SINT_t i = -1;
924
925 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530926 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700927
928 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
929 //Will be zeroed out during alloc
930
931 while (++i != NUM_TX_QUEUES)
932 {
933 pAdapter->isTxSuspended[i] = VOS_FALSE;
934 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
935 }
936
937 return status;
938}
939
940
941/**============================================================================
942 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
943 modules in HDD
944
945 @param pAdapter : [in] pointer to adapter context
946 @return : VOS_STATUS_E_FAILURE if any errors encountered
947 : VOS_STATUS_SUCCESS otherwise
948 ===========================================================================*/
949VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
950{
951 VOS_STATUS status = VOS_STATUS_SUCCESS;
952 v_SINT_t i = -1;
953
954 status = hdd_flush_tx_queues(pAdapter);
955 while (++i != NUM_TX_QUEUES)
956 {
957 //Free up actual list elements in the Tx queue
958 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
959 }
960
961 return status;
962}
963
964
965/**============================================================================
966 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
967 modules in HDD
968
969 @param pAdapter : [in] pointer to adapter context
970 @return : VOS_STATUS_E_FAILURE if any errors encountered
971 : VOS_STATUS_SUCCESS otherwise
972 ===========================================================================*/
973VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
974{
975 return hdd_flush_tx_queues(pAdapter);
976}
977
978
979/**============================================================================
980 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
981
982 @param pVosPacket : [in] pointer to vos packet
983 @return : VOS_TRUE if the packet is EAPOL
984 : VOS_FALSE otherwise
985 ===========================================================================*/
986
987v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
988{
989 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
990 v_BOOL_t fEAPOL = VOS_FALSE;
991 void *pBuffer = NULL;
992
993
994 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
995 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
996 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
997 {
998 if ( vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_802_1_X )
999 {
1000 fEAPOL = VOS_TRUE;
1001 }
1002 }
1003
1004 return fEAPOL;
1005}
1006
1007
1008#ifdef FEATURE_WLAN_WAPI // Need to update this function
1009/**============================================================================
1010 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1011
1012 @param pVosPacket : [in] pointer to vos packet
1013 @return : VOS_TRUE if the packet is WAI
1014 : VOS_FALSE otherwise
1015 ===========================================================================*/
1016
1017v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1018{
1019 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1020 v_BOOL_t fIsWAI = VOS_FALSE;
1021 void *pBuffer = NULL;
1022
1023 // Need to update this function
1024 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1025 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1026
1027 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1028 {
1029 if ( vos_be16_to_cpu( *(unsigned short*)pBuffer ) == HDD_ETHERTYPE_WAI)
1030 {
1031 fIsWAI = VOS_TRUE;
1032 }
1033 }
1034
1035 return fIsWAI;
1036}
1037#endif /* FEATURE_WLAN_WAPI */
1038
1039/**============================================================================
1040 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1041 to indicate that a packet has been transmitted across the SDIO bus
1042 succesfully. OS packet resources can be released after this cbk.
1043
1044 @param vosContext : [in] pointer to VOS context
1045 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1046 @param vosStatusIn : [in] status of the transmission
1047
1048 @return : VOS_STATUS_E_FAILURE if any errors encountered
1049 : VOS_STATUS_SUCCESS otherwise
1050 ===========================================================================*/
1051VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1052 vos_pkt_t *pVosPacket,
1053 VOS_STATUS vosStatusIn )
1054{
1055 VOS_STATUS status = VOS_STATUS_SUCCESS;
1056 hdd_adapter_t *pAdapter = NULL;
1057 hdd_context_t *pHddCtx = NULL;
1058 void* pOsPkt = NULL;
1059
1060 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1061 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001063 return VOS_STATUS_E_FAILURE;
1064 }
1065
1066 //Return the skb to the OS
1067 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
1068 if(!VOS_IS_STATUS_SUCCESS( status ))
1069 {
1070 //This is bad but still try to free the VOSS resources if we can
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001071 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 -07001072 vos_pkt_return_packet( pVosPacket );
1073 return VOS_STATUS_E_FAILURE;
1074 }
1075
1076 //Get the HDD context.
1077 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1078 //Get the Adapter context.
1079 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
1080 if(pAdapter == NULL)
1081 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 }
1084 else
1085 {
1086 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1087 }
1088
1089 kfree_skb((struct sk_buff *)pOsPkt);
1090
1091 //Return the VOS packet resources.
1092 status = vos_pkt_return_packet( pVosPacket );
1093 if(!VOS_IS_STATUS_SUCCESS( status ))
1094 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001095 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 -07001096 }
1097
1098 return status;
1099}
1100
1101
1102/**============================================================================
1103 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1104 fetch a packet for transmission.
1105
1106 @param vosContext : [in] pointer to VOS context
1107 @param staId : [in] Station for which TL is requesting a pkt
1108 @param ac : [in] access category requested by TL
1109 @param pVosPacket : [out] pointer to VOS packet packet pointer
1110 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1111
1112 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1113 : VOS_STATUS_E_FAILURE if any errors encountered
1114 : VOS_STATUS_SUCCESS otherwise
1115 ===========================================================================*/
1116VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1117 v_U8_t *pStaId,
1118 WLANTL_ACEnumType ac,
1119 vos_pkt_t **ppVosPacket,
1120 WLANTL_MetaInfoType *pPktMetaInfo )
1121{
1122 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1123 hdd_adapter_t *pAdapter = NULL;
1124 hdd_context_t *pHddCtx = NULL;
1125 hdd_list_node_t *anchor = NULL;
1126 skb_list_node_t *pktNode = NULL;
1127 struct sk_buff *skb = NULL;
1128 vos_pkt_t *pVosPacket = NULL;
1129 v_MACADDR_t* pDestMacAddress = NULL;
1130 v_TIME_t timestamp;
1131 WLANTL_ACEnumType newAc;
1132 v_SIZE_t size = 0;
1133 tANI_U8 acAdmitted, i;
1134
1135 //Sanity check on inputs
1136 if ( ( NULL == vosContext ) ||
1137 ( NULL == pStaId ) ||
1138 ( NULL == ppVosPacket ) ||
1139 ( NULL == pPktMetaInfo ) )
1140 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001142 return VOS_STATUS_E_FAILURE;
1143 }
1144
1145 //Get the HDD context.
1146 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1147 if(pHddCtx == NULL)
1148 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001150 return VOS_STATUS_E_FAILURE;
1151 }
1152
1153 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
1154 if( NULL == pAdapter )
1155 {
1156 VOS_ASSERT(0);
1157 return VOS_STATUS_E_FAILURE;
1158 }
1159
1160 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1161
1162 *ppVosPacket = NULL;
1163
1164 //Make sure the AC being asked for is sane
1165 if( ac >= WLANTL_MAX_AC || ac < 0)
1166 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001167 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 -07001168 return VOS_STATUS_E_FAILURE;
1169 }
1170
1171 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1172
1173#ifdef HDD_WMM_DEBUG
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001174 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 -07001175#endif // HDD_WMM_DEBUG
1176
1177 // We find an AC with packets
1178 // or we determine we have no more packets to send
1179 // HDD is not allowed to change AC.
1180
1181 // has this AC been admitted? or
1182 // To allow EAPOL packets when not authenticated
1183 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1184 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1185 {
1186 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1187#ifdef HDD_WMM_DEBUG
1188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001189 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001190#endif // HDD_WMM_DEBUG
1191 return VOS_STATUS_E_FAILURE;
1192 }
1193
1194 // do we have any packets pending in this AC?
1195 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1196 if( size > 0 )
1197 {
1198 // yes, so process it
1199#ifdef HDD_WMM_DEBUG
1200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001201 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001202#endif // HDD_WMM_DEBUG
1203 }
1204 else
1205 {
1206 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1207#ifdef HDD_WMM_DEBUG
1208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001209 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001210#endif // HDD_WMM_DEBUG
1211 return VOS_STATUS_E_FAILURE;
1212 }
1213
1214 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1215 //This simplifies the locking and unlocking of Tx queue
1216 status = vos_pkt_wrap_data_packet( &pVosPacket,
1217 VOS_PKT_TYPE_TX_802_3_DATA,
1218 NULL, //OS Pkt is not being passed
1219 hdd_tx_low_resource_cbk,
1220 pAdapter );
1221
1222 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1223 {
1224 //Remember VOS is in a low resource situation
1225 pAdapter->isVosOutOfResource = VOS_TRUE;
1226 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001228 //TL will now think we have no more packets in this AC
1229 return VOS_STATUS_E_FAILURE;
1230 }
1231
1232 //Remove the packet from the queue
1233 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1234 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1235 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1236
1237 if(VOS_STATUS_SUCCESS == status)
1238 {
1239 //If success then we got a valid packet from some AC
1240 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1241 skb = pktNode->skb;
1242 }
1243 else
1244 {
1245 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
Madan Mohan Koyyalamudi60a6a8d2012-10-21 11:57:42 -07001246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001247 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001248 vos_pkt_return_packet(pVosPacket);
1249 return VOS_STATUS_E_FAILURE;
1250 }
1251
1252 //Attach skb to VOS packet.
1253 status = vos_pkt_set_os_packet( pVosPacket, skb );
1254 if (status != VOS_STATUS_SUCCESS)
1255 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 vos_pkt_return_packet(pVosPacket);
1258 ++pAdapter->stats.tx_dropped;
1259 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1260 kfree_skb(skb);
1261 return VOS_STATUS_E_FAILURE;
1262 }
1263
1264 //Just being paranoid. To be removed later
1265 if(pVosPacket == NULL)
1266 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001267 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 -07001268 ++pAdapter->stats.tx_dropped;
1269 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1270 kfree_skb(skb);
1271 return VOS_STATUS_E_FAILURE;
1272 }
1273
Chilam NG571c65a2013-01-19 12:27:36 +05301274#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001275 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05301276 {
1277 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301278 u8 mac[6];
1279
Hoonki Lee387663d2013-02-05 18:08:43 -08001280 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301281
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001282 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
Chilam NG571c65a2013-01-19 12:27:36 +05301283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1284 "broadcast packet, not adding to peer list");
1285 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1286 mac, 6) != 0) {
1287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001288 "extract mac: " MAC_ADDRESS_STR,
1289 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05301290
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001291 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301292 } else {
1293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1294 "packet da is bssid, not adding to peer list");
1295 }
1296 }
1297#endif
1298
Jeff Johnson295189b2012-06-20 16:38:30 -07001299 //Return VOS packet to TL;
1300 *ppVosPacket = pVosPacket;
1301
1302 //Fill out the meta information needed by TL
1303 //FIXME This timestamp is really the time stamp of wrap_data_packet
1304 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1305 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1306
1307 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1308 pPktMetaInfo->ucIsEapol = 0;
1309 else
1310 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1311
1312#ifdef FEATURE_WLAN_WAPI
1313 // Override usIsEapol value when its zero for WAPI case
1314 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
1315#endif /* FEATURE_WLAN_WAPI */
1316
1317 if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) ||
1318 (!pAdapter->hddWmmStatus.wmmQap))
1319 {
1320 // either we don't want QoS or the AP doesn't support QoS
1321 pPktMetaInfo->ucUP = 0;
1322 pPktMetaInfo->ucTID = 0;
1323 }
1324 else
1325 {
1326 /* 1. Check if ACM is set for this AC
1327 * 2. If set, check if this AC had already admitted
1328 * 3. If not already admitted, downgrade the UP to next best UP */
1329 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
1330 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid)
1331 {
1332 pPktMetaInfo->ucUP = pktNode->userPriority;
1333 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1334 }
1335 else
1336 {
1337 //Downgrade the UP
1338 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1339 newAc = WLANTL_AC_BK;
1340 for (i=ac-1; i>0; i--)
1341 {
1342 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1343 {
1344 newAc = i;
1345 break;
1346 }
1347 }
1348 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1349 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP);
1351 }
1352 }
1353
1354 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1355 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1356 if ( 1 < size )
1357 {
1358 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1359 }
1360 else
1361 {
1362 pPktMetaInfo->bMorePackets = 0;
1363 }
1364
1365 //Extract the destination address from ethernet frame
1366 pDestMacAddress = (v_MACADDR_t*)skb->data;
1367 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1368 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1369
1370
1371
1372 // if we are in a backpressure situation see if we can turn the hose back on
1373 if ( (pAdapter->isTxSuspended[ac]) &&
1374 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1375 {
1376 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1377 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
Gopichand Nakkala8fbc3d42013-03-05 21:06:41 -08001378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001379 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001380 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1381 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1382 skb_get_queue_mapping(skb) ));
1383 }
1384
1385
1386 // We're giving the packet to TL so consider it transmitted from
1387 // a statistics perspective. We account for it here instead of
1388 // when the packet is returned for two reasons. First, TL will
1389 // manipulate the skb to the point where the len field is not
1390 // accurate, leading to inaccurate byte counts if we account for
1391 // it later. Second, TL does not provide any feedback as to
1392 // whether or not the packet was successfully sent over the air,
1393 // so the packet counts will be the same regardless of where we
1394 // account for them
1395 pAdapter->stats.tx_bytes += skb->len;
1396 ++pAdapter->stats.tx_packets;
1397 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1398 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1399
Leo Chang50bbd252013-04-25 14:58:01 -07001400 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1401 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001402 {
1403 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1404 {
1405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001406 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 return VOS_STATUS_E_FAILURE;
1408 }
1409 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1410 {
1411 if(0 == pHddCtx->tmInfo.txFrameCount)
1412 {
1413 /* Just recovered from sleep timeout */
1414 pHddCtx->tmInfo.lastOpenTs = timestamp;
1415 }
1416
Leo Chang50bbd252013-04-25 14:58:01 -07001417 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1418 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001419 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1420 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001421 /* During TX open duration, TX frame count is larger than threshold
1422 * Block TX during Sleep time */
1423 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001424 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001425 pHddCtx->tmInfo.lastblockTs = timestamp;
1426 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1427 {
1428 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1429 }
1430 }
1431 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1432 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1433 {
1434 /* During TX open duration, TX frame count is less than threshold
1435 * Reset count and timestamp to prepare next cycle */
1436 pHddCtx->tmInfo.lastOpenTs = timestamp;
1437 pHddCtx->tmInfo.txFrameCount = 0;
1438 }
1439 else
1440 {
1441 /* Do Nothing */
1442 }
1443 pHddCtx->tmInfo.txFrameCount++;
1444 }
1445 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1446 }
1447
1448
1449#ifdef HDD_WMM_DEBUG
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001450 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 -07001451#endif // HDD_WMM_DEBUG
1452
1453 return status;
1454}
1455
1456
1457/**============================================================================
1458 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1459 case where VOS packets are not available at the time of the call to get
1460 packets. This callback function is invoked by VOS when packets are
1461 available.
1462
1463 @param pVosPacket : [in] pointer to VOS packet
1464 @param userData : [in] opaque user data that was passed initially
1465
1466 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1467 : VOS_STATUS_SUCCESS otherwise
1468 =============================================================================*/
1469VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1470 v_VOID_t *userData )
1471{
1472 VOS_STATUS status;
1473 v_SINT_t i = 0;
1474 v_SIZE_t size = 0;
1475 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1476
1477 if(pAdapter == NULL)
1478 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001480 return VOS_STATUS_E_FAILURE;
1481 }
1482
1483 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1484 //situation. Here we will only signal TL that there is a pending data for a STA.
1485 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1486 vos_pkt_return_packet( pVosPacket );
1487
1488 pAdapter->isVosOutOfResource = VOS_FALSE;
1489
1490 //Indicate to TL that there is pending data if a queue is non empty
1491 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1492 {
1493 size = 0;
1494 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1495 if ( size > 0 )
1496 {
1497 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1498 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1499 (WLANTL_ACEnumType)i );
1500 if( !VOS_IS_STATUS_SUCCESS( status ) )
1501 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001502 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 -07001503 }
1504 }
1505 }
1506
1507 return VOS_STATUS_SUCCESS;
1508}
1509
1510
1511/**============================================================================
1512 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1513 TL will call this to notify the HDD when one or more packets were
1514 received for a registered STA.
1515
1516 @param vosContext : [in] pointer to VOS context
1517 @param pVosPacketChain : [in] pointer to VOS packet chain
1518 @param staId : [in] Station Id
1519 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1520
1521 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1522 : VOS_STATUS_SUCCESS otherwise
1523 ===========================================================================*/
1524VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1525 vos_pkt_t *pVosPacketChain,
1526 v_U8_t staId,
1527 WLANTL_RxMetaInfoType* pRxMetaInfo )
1528{
1529 hdd_adapter_t *pAdapter = NULL;
1530 hdd_context_t *pHddCtx = NULL;
1531 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1532 int rxstat;
1533 struct sk_buff *skb = NULL;
1534 vos_pkt_t* pVosPacket;
1535 vos_pkt_t* pNextVosPacket;
1536
1537 //Sanity check on inputs
1538 if ( ( NULL == vosContext ) ||
1539 ( NULL == pVosPacketChain ) ||
1540 ( NULL == pRxMetaInfo ) )
1541 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001543 return VOS_STATUS_E_FAILURE;
1544 }
1545
1546 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1547 if ( NULL == pHddCtx )
1548 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001550 return VOS_STATUS_E_FAILURE;
1551 }
1552
1553 pAdapter = pHddCtx->sta_to_adapter[staId];
1554 if( NULL == pAdapter )
1555 {
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05301556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: pAdapter is Null for staId %u",
1557 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001558 return VOS_STATUS_E_FAILURE;
1559 }
1560
1561 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1562
1563 // walk the chain until all are processed
1564 pVosPacket = pVosPacketChain;
1565 do
1566 {
1567 // get the pointer to the next packet in the chain
1568 // (but don't unlink the packet since we free the entire chain later)
1569 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1570
1571 // both "success" and "empty" are acceptable results
1572 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1573 {
1574 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001576 return VOS_STATUS_E_FAILURE;
1577 }
1578
1579 // Extract the OS packet (skb).
1580 // Tell VOS to detach the OS packet from the VOS packet
1581 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1582 if(!VOS_IS_STATUS_SUCCESS( status ))
1583 {
1584 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001585 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 -07001586 return VOS_STATUS_E_FAILURE;
1587 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001588
1589 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1590 {
1591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1592 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
1593 return eHAL_STATUS_FAILURE;
1594 }
1595
Chilam Ng1279e232013-01-25 15:06:52 -08001596#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001597 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
1598 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08001599 {
1600 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08001601 u8 mac[6];
1602
Hoonki Lee387663d2013-02-05 18:08:43 -08001603 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08001604
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001605 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
Chilam Ng1279e232013-01-25 15:06:52 -08001606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1607 "rx broadcast packet, not adding to peer list");
1608 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1609 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001610 hddTdlsPeer_t *curr_peer;
Chilam Ng1279e232013-01-25 15:06:52 -08001611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001612 "rx extract mac:" MAC_ADDRESS_STR,
1613 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05301614 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05301615 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
1616 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001617 {
1618 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
1619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
1620 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
1621 }
Chilam Ng1279e232013-01-25 15:06:52 -08001622 } else {
1623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
1624 "rx packet sa is bssid, not adding to peer list");
1625 }
1626 }
1627#endif
1628
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 skb->dev = pAdapter->dev;
1630 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001631 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001632 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
1633 ++pAdapter->stats.rx_packets;
1634 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001635#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001636#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001637 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001638#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001639#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001640 rxstat = netif_rx_ni(skb);
1641 if (NET_RX_SUCCESS == rxstat)
1642 {
1643 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001644 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 }
1646 else
1647 {
1648 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
1649 }
1650 // now process the next packet in the chain
1651 pVosPacket = pNextVosPacket;
1652
1653 } while (pVosPacket);
1654
1655 //Return the entire VOS packet chain to the resource pool
1656 status = vos_pkt_return_packet( pVosPacketChain );
1657 if(!VOS_IS_STATUS_SUCCESS( status ))
1658 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001660 }
1661
1662 pAdapter->dev->last_rx = jiffies;
1663
1664 return status;
1665}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001666/**============================================================================
1667 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
1668 Enable/Disable split scan based on TX and RX traffic.
1669 @param HddContext : [in] pointer to Hdd context
1670 @return : None
1671 ===========================================================================*/
1672void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
1673{
1674 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1675 hdd_adapter_t *pAdapter = NULL;
1676 hdd_station_ctx_t *pHddStaCtx = NULL;
1677 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
1678 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
1679 VOS_STATUS status;
1680 v_U8_t staId = 0;
1681 v_U8_t fconnected = 0;
1682
1683 if (!cfg_param->dynSplitscan)
1684 {
1685 hddLog(VOS_TRACE_LEVEL_INFO,
1686 "%s: Error : Dynamic split scan is not Enabled : %d",
1687 __func__, pHddCtx->cfg_ini->dynSplitscan);
1688 return;
1689 }
1690
1691 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1692 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1693 {
1694 pAdapter = pAdapterNode->pAdapter;
1695
1696 if ( pAdapter )
1697 {
1698 hddLog(VOS_TRACE_LEVEL_INFO,
1699 "%s: Adapter with device mode %d exists",
1700 __func__, pAdapter->device_mode);
1701
1702 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1703 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
1704 {
1705 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1706 if ((eConnectionState_Associated ==
1707 pHddStaCtx->conn_info.connState) &&
1708 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
1709 {
1710 fconnected = TRUE;
1711 }
1712 }
1713 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1714 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
1715 {
1716 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
1717 {
1718 if ((pAdapter->aStaInfo[staId].isUsed) &&
1719 (WLANTL_STA_AUTHENTICATED ==
1720 pAdapter->aStaInfo[staId].tlSTAState))
1721 {
1722 fconnected = TRUE;
1723 }
1724 }
1725 }
1726 if ( fconnected )
1727 {
1728 hddLog(VOS_TRACE_LEVEL_INFO,
1729 "%s: One of the interface is connected check for scan",
1730 __func__);
1731 hddLog(VOS_TRACE_LEVEL_INFO,
1732 "%s: pkt_tx_count: %d, pkt_rx_count: %d", __func__,
1733 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
1734 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count);
1735
1736 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
1737 cfg_param->trafficMntrTmrForSplitScan);
1738 //Check for the previous statistics count
1739 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
1740 cfg_param->txRxThresholdForSplitScan) ||
1741 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
1742 cfg_param->txRxThresholdForSplitScan) ||
1743 pHddCtx->drvr_miracast)
1744 {
1745 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
1746 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
1747
1748 if (!pHddCtx->issplitscan_enabled)
1749 {
1750 pHddCtx->issplitscan_enabled = TRUE;
1751 sme_enable_disable_split_scan(
1752 WLAN_HDD_GET_HAL_CTX(pAdapter),
1753 cfg_param->nNumStaChanCombinedConc,
1754 cfg_param->nNumP2PChanCombinedConc);
1755 }
1756 return;
1757 }
1758 else
1759 {
1760 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
1761 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
1762 }
1763 fconnected = FALSE;
1764 }
1765 }
1766 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
1767 pAdapterNode = pNext;
1768 }
1769
1770 if (pHddCtx->issplitscan_enabled)
1771 {
1772 hddLog(VOS_TRACE_LEVEL_ERROR,
1773 "%s: Disable split scan", __func__);
1774 pHddCtx->issplitscan_enabled = FALSE;
1775 sme_enable_disable_split_scan(
1776 pHddCtx->hHal,
1777 SME_DISABLE_SPLIT_SCAN,
1778 SME_DISABLE_SPLIT_SCAN);
1779 }
1780 return;
1781}
Jeff Johnson295189b2012-06-20 16:38:30 -07001782