blob: 5c6303e94b893116180622b0fe8675a86da1da72 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
c_hpothu32490782014-03-14 19:14:34 +05302 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**===========================================================================
29
30 \file wlan_hdd_tx_rx.c
31
32 \brief Linux HDD Tx/RX APIs
Kiet Lamaa8e15a2014-02-11 23:30:06 -080033 Copyright 2008 (c) Qualcomm, Incorporated.
34 All Rights Reserved.
35 Qualcomm Confidential and Proprietary.
Jeff Johnson295189b2012-06-20 16:38:30 -070036
37 ==========================================================================*/
38
39/*---------------------------------------------------------------------------
40 Include files
41 -------------------------------------------------------------------------*/
42#include <wlan_hdd_tx_rx.h>
43#include <wlan_hdd_softap_tx_rx.h>
44#include <wlan_hdd_dp_utils.h>
45#include <wlan_qct_tl.h>
46#include <linux/netdevice.h>
47#include <linux/skbuff.h>
48#include <linux/etherdevice.h>
Mihir Shetec8fe71b2014-06-16 15:32:59 +053049#include <linux/ratelimit.h>
Mihir Shetef3473692014-06-27 15:13:20 +053050#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
51#include <soc/qcom/subsystem_restart.h>
52#else
53#include <mach/subsystem_restart.h>
54#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070055
Jeff Johnson295189b2012-06-20 16:38:30 -070056#include <wlan_hdd_p2p.h>
57#include <linux/wireless.h>
58#include <net/cfg80211.h>
59#include <net/ieee80211_radiotap.h>
60#include "sapApi.h"
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053061#include <vos_sched.h>
Chilam NG571c65a2013-01-19 12:27:36 +053062#ifdef FEATURE_WLAN_TDLS
63#include "wlan_hdd_tdls.h"
64#endif
65
Mukul Sharma84f27252014-07-14 18:11:42 +053066#ifdef DEBUG_ROAM_DELAY
67#include "vos_utils.h"
68#endif
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053069#include "sapInternal.h"
Mihir Shete5d148f12014-12-16 17:54:49 +053070#include "wlan_hdd_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070071/*---------------------------------------------------------------------------
72 Preprocessor definitions and constants
73 -------------------------------------------------------------------------*/
74
75const v_U8_t hddWmmAcToHighestUp[] = {
76 SME_QOS_WMM_UP_RESV,
77 SME_QOS_WMM_UP_EE,
78 SME_QOS_WMM_UP_VI,
79 SME_QOS_WMM_UP_NC
80};
81
82//Mapping Linux AC interpretation to TL AC.
83const v_U8_t hdd_QdiscAcToTlAC[] = {
84 WLANTL_AC_VO,
85 WLANTL_AC_VI,
86 WLANTL_AC_BE,
87 WLANTL_AC_BK,
88};
89
Mihir Shetec8fe71b2014-06-16 15:32:59 +053090#define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
91#define HDD_TX_TIMEOUT_RATELIMIT_BURST 1
Mihir Shetef3473692014-06-27 15:13:20 +053092#define HDD_TX_STALL_SSR_THRESHOLD 5
Mihir Shete327c2ab2014-11-13 15:17:02 +053093#define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
Mihir Shetec8fe71b2014-06-16 15:32:59 +053094
95static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs, \
96 HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
97 HDD_TX_TIMEOUT_RATELIMIT_BURST);
98
Jeff Johnson295189b2012-06-20 16:38:30 -070099static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700100
101/*---------------------------------------------------------------------------
102 Type declarations
103 -------------------------------------------------------------------------*/
104
105/*---------------------------------------------------------------------------
106 Function definitions and documenation
107 -------------------------------------------------------------------------*/
108
109#ifdef DATA_PATH_UNIT_TEST
110//Utility function to dump an sk_buff
111static void dump_sk_buff(struct sk_buff * skb)
112{
c_hpothu32490782014-03-14 19:14:34 +0530113 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
114 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
115 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
116 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
117 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
118 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
119 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700120
c_hpothu32490782014-03-14 19:14:34 +0530121 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -0700122 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
123 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu32490782014-03-14 19:14:34 +0530124 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -0700125 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
126 skb->data[13], skb->data[14], skb->data[15]);
127}
128
129//Function for Unit Test only
130static void transport_thread(hdd_adapter_t *pAdapter)
131{
132 v_U8_t staId;
133 WLANTL_ACEnumType ac = WLANTL_AC_BE;
134 vos_pkt_t *pVosPacket = NULL ;
135 vos_pkt_t dummyPacket;
136 WLANTL_MetaInfoType pktMetaInfo;
137 WLANTL_RxMetaInfoType pktRxMetaInfo;
138 VOS_STATUS status = VOS_STATUS_E_FAILURE;
139
c_hpothub8245442013-11-20 23:41:09 +0530140 if (NULL == pAdapter)
141 {
c_hpothu32490782014-03-14 19:14:34 +0530142 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530143 FL("pAdapter is NULL"));
144 VOS_ASSERT(0);
145 return;
146 }
147
Jeff Johnson295189b2012-06-20 16:38:30 -0700148 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
149 &staId,
150 &ac,
151 &pVosPacket,
152 &pktMetaInfo );
153 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530154 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
155 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700156 else
c_hpothu32490782014-03-14 19:14:34 +0530157 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
158 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700159
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700160 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700161 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530162 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
163 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700164 else
c_hpothu32490782014-03-14 19:14:34 +0530165 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
166 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700167
168 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
169 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530170 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
171 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700172 else
c_hpothu32490782014-03-14 19:14:34 +0530173 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
174 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
177 &dummyPacket,
178 staId,
179 &pktRxMetaInfo);
180 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530181 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
182 "%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700183 else
c_hpothu32490782014-03-14 19:14:34 +0530184 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
185 "%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700186
187}
188#endif
189
190
191/**============================================================================
192 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
193
194 @param pAdapter : [in] pointer to adapter context
195 @return : VOS_STATUS_E_FAILURE if any errors encountered
196 : VOS_STATUS_SUCCESS otherwise
197 ===========================================================================*/
198static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
199{
200 VOS_STATUS status = VOS_STATUS_SUCCESS;
201 v_SINT_t i = -1;
202 hdd_list_node_t *anchor = NULL;
203 skb_list_node_t *pktNode = NULL;
204 struct sk_buff *skb = NULL;
205
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530206 pAdapter->isVosLowResource = VOS_FALSE;
207
Mihir Shete5d148f12014-12-16 17:54:49 +0530208 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_FLUSH_TX_QUEUES,
209 pAdapter->sessionId, 0));
210
Jeff Johnson295189b2012-06-20 16:38:30 -0700211 while (++i != NUM_TX_QUEUES)
212 {
213 //Free up any packets in the Tx queue
214 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
215 while (true)
216 {
217 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
218 if(VOS_STATUS_E_EMPTY != status)
219 {
220 pktNode = list_entry(anchor, skb_list_node_t, anchor);
221 skb = pktNode->skb;
222 //TODO
223 //++pAdapter->stats.tx_dropped;
224 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
225 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
226 kfree_skb(skb);
227 continue;
228 }
229 break;
230 }
231 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
232 // backpressure is no longer in effect
233 pAdapter->isTxSuspended[i] = VOS_FALSE;
234 }
235
236 return status;
237}
238
Ravi Joshif9520d62013-10-18 04:11:46 -0700239/**============================================================================
240 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
241 in IBSS mode
242
243 @param pAdapter : [in] pointer to adapter context
244 : [in] Staion Id
245 @return : VOS_STATUS_E_FAILURE if any errors encountered
246 : VOS_STATUS_SUCCESS otherwise
247 ===========================================================================*/
248void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
249{
250 v_U8_t i;
Ravi Joshi41914632013-10-21 23:02:21 -0700251 v_SIZE_t size = 0;
Ravi Joshif9520d62013-10-18 04:11:46 -0700252 v_U8_t skbStaIdx;
Ravi Joshi41914632013-10-21 23:02:21 -0700253 skb_list_node_t *pktNode = NULL;
254 hdd_list_node_t *tmp = NULL, *next = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700255 struct netdev_queue *txq;
Ravi Joshi41914632013-10-21 23:02:21 -0700256 struct sk_buff *skb = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700257
c_hpothub8245442013-11-20 23:41:09 +0530258 if (NULL == pAdapter)
259 {
c_hpothu32490782014-03-14 19:14:34 +0530260 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530261 FL("pAdapter is NULL %u"), STAId);
262 VOS_ASSERT(0);
263 return;
264 }
265
Ravi Joshif9520d62013-10-18 04:11:46 -0700266 for (i = 0; i < NUM_TX_QUEUES; i++)
267 {
268 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
269
270 if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) )
271 {
272 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
273 continue;
274 }
275
276 /* Iterate through the queue and identify the data for STAId */
Ravi Joshi41914632013-10-21 23:02:21 -0700277 list_for_each_safe(tmp, next, &pAdapter->wmm_tx_queue[i].anchor)
Ravi Joshif9520d62013-10-18 04:11:46 -0700278 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700279 pktNode = list_entry(tmp, skb_list_node_t, anchor);
280 if (pktNode != NULL)
281 {
282 skb = pktNode->skb;
283
284 /* Get the STAId from data */
285 skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
286 if (skbStaIdx == STAId)
287 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700288 /* Data for STAId is freed along with the queue node */
Ravi Joshif9520d62013-10-18 04:11:46 -0700289 list_del(tmp);
Mihir Shete31e1e392014-03-24 17:09:09 +0530290 kfree_skb(skb);
Ravi Joshif9520d62013-10-18 04:11:46 -0700291
292 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
293 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
294 pAdapter->wmm_tx_queue[i].count--;
295 }
296 }
297 }
298
299 /* Restart the queue only-if suspend and the queue was flushed */
Ravi Joshi41914632013-10-21 23:02:21 -0700300 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
Ravi Joshif9520d62013-10-18 04:11:46 -0700301 txq = netdev_get_tx_queue(pAdapter->dev, i);
Ravi Joshi41914632013-10-21 23:02:21 -0700302
303 if (VOS_TRUE == pAdapter->isTxSuspended[i] &&
304 size <= HDD_TX_QUEUE_LOW_WATER_MARK &&
305 netif_tx_queue_stopped(txq) )
Ravi Joshif9520d62013-10-18 04:11:46 -0700306 {
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530307 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queue for queue %d"),i);
Ravi Joshif9520d62013-10-18 04:11:46 -0700308 netif_tx_start_queue(txq);
Ravi Joshi41914632013-10-21 23:02:21 -0700309 pAdapter->isTxSuspended[i] = VOS_FALSE;
310 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressured;
311 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressuredAC[i];
Ravi Joshif9520d62013-10-18 04:11:46 -0700312 }
313
314 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
315 }
316}
317
Jeff Johnson295189b2012-06-20 16:38:30 -0700318static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
319{
320 skb_list_node_t *pktNode = NULL;
321 struct sk_buff *skb = NULL;
322 v_SIZE_t size = 0;
323 WLANTL_ACEnumType ac = 0;
324 VOS_STATUS status = VOS_STATUS_E_FAILURE;
325 hdd_list_node_t *anchor = NULL;
326
c_hpothu77731d42014-01-23 13:59:03 +0530327 if (NULL == pAdapter)
328 {
329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
330 FL("pAdapter is NULL"));
331 VOS_ASSERT(0);
332 return NULL;
333 }
334
Jeff Johnson295189b2012-06-20 16:38:30 -0700335 // do we have any packets pending in this AC?
336 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
337 if( size == 0 )
338 {
c_hpothu32490782014-03-14 19:14:34 +0530339 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700340 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700341 return NULL;
342 }
343
344 //Remove the packet from the queue
345 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
346 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
347 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
348
349 if(VOS_STATUS_SUCCESS == status)
350 {
351 //If success then we got a valid packet from some AC
352 pktNode = list_entry(anchor, skb_list_node_t, anchor);
353 skb = pktNode->skb;
354 }
355 else
356 {
c_hpothu32490782014-03-14 19:14:34 +0530357 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700358 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700359 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700360
361 return NULL;
362 }
363
364 // if we are in a backpressure situation see if we can turn the hose back on
365 if ( (pAdapter->isTxSuspended[ac]) &&
366 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
367 {
c_hpothu32490782014-03-14 19:14:34 +0530368 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700369 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700370 pAdapter->isTxSuspended[ac] = VOS_FALSE;
371 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530372 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700373 netif_tx_start_all_queues( pAdapter->dev );
374 }
375
376 return skb;
377}
378
379void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
380{
381 hdd_cfg80211_state_t *cfgState;
382 struct sk_buff* skb;
383 hdd_adapter_t* pMonAdapter = NULL;
384 struct ieee80211_hdr *hdr;
385
Mukul Sharma23a92232014-04-07 18:04:00 +0530386 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700387 {
c_hpothu32490782014-03-14 19:14:34 +0530388 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530389 FL("pAdapter is NULL"));
390 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700391 return;
392 }
393
394 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530395 if (pMonAdapter == NULL)
396 {
397 hddLog(VOS_TRACE_LEVEL_ERROR,
398 "%s: pMonAdapter is NULL", __func__);
399 return;
400 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700401 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
402
403 if( NULL != cfgState->buf )
404 {
c_hpothu32490782014-03-14 19:14:34 +0530405 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700406 "%s: Already one MGMT packet Tx going on", __func__);
407 return;
408 }
409
410 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
411
412 if (NULL == skb)
413 {
c_hpothu32490782014-03-14 19:14:34 +0530414 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700415 "%s: No Packet Pending", __func__);
416 return;
417 }
418
419 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
420 if( cfgState->buf == NULL )
421 {
c_hpothu32490782014-03-14 19:14:34 +0530422 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700423 "%s: Failed to Allocate memory", __func__);
424 goto fail;
425 }
426
427 cfgState->len = skb->len;
428
429 vos_mem_copy( cfgState->buf, skb->data, skb->len);
430
431 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800432 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700433
434 hdr = (struct ieee80211_hdr *)skb->data;
435 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
436 == HDD_FRAME_TYPE_MGMT )
437 {
438 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
439 == HDD_FRAME_SUBTYPE_DEAUTH )
440 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530441 struct tagCsrDelStaParams delStaParams;
442
Sushant Kaushik4cd28f62014-12-26 14:23:50 +0530443 WLANSAP_PopulateDelStaParams(hdr->addr1,
444 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530445 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
446
447 hdd_softap_sta_deauth(pAdapter, &delStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 goto mgmt_handled;
449 }
450 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
451 == HDD_FRAME_SUBTYPE_DISASSOC )
452 {
453 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
454 goto mgmt_handled;
455 }
456 }
c_hpothu32490782014-03-14 19:14:34 +0530457 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700458 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
459
Jeff Johnson43971f52012-07-17 12:26:56 -0700460 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700461 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700462 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700463 {
c_hpothu32490782014-03-14 19:14:34 +0530464 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700465 "%s: WLANSAP_SendAction returned fail", __func__);
466 hdd_sendActionCnf( pAdapter, FALSE );
467 }
468 return;
469
470mgmt_handled:
471 hdd_sendActionCnf( pAdapter, TRUE );
472 return;
473fail:
474 kfree_skb(pAdapter->skb_to_tx);
475 pAdapter->skb_to_tx = NULL;
476 return;
477}
478
479void hdd_mon_tx_work_queue(struct work_struct *work)
480{
481 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
482 hdd_mon_tx_mgmt_pkt(pAdapter);
483}
484
485int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
486{
487 v_U16_t rt_hdr_len;
488 struct ieee80211_hdr *hdr;
489 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
490 struct ieee80211_radiotap_header *rtap_hdr =
491 (struct ieee80211_radiotap_header *)skb->data;
492
493 /*Supplicant sends the EAPOL packet on monitor interface*/
494 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
495 if(pPgBkAdapter == NULL)
496 {
c_hpothu32490782014-03-14 19:14:34 +0530497 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700498 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
499 __func__);
500 goto fail; /* too short to be possibly valid */
501 }
502
503 /* check if toal skb length is greater then radio tab header length of not */
504 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
505 goto fail; /* too short to be possibly valid */
506
507 /* check if radio tap header version is correct or not */
508 if (unlikely(rtap_hdr->it_version))
509 goto fail; /* only version 0 is supported */
510
511 /*Strip off the radio tap header*/
512 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
513
514 /* check if skb length if greator then total radio tap header length ot not*/
515 if (unlikely(skb->len < rt_hdr_len))
516 goto fail;
517
518 /* Update the trans_start for this netdev */
519 dev->trans_start = jiffies;
520 /*
521 * fix up the pointers accounting for the radiotap
522 * header still being in there.
523 */
524 skb_set_mac_header(skb, rt_hdr_len);
525 skb_set_network_header(skb, rt_hdr_len);
526 skb_set_transport_header(skb, rt_hdr_len);
527
528 /* Pull rtap header out of the skb */
529 skb_pull(skb, rt_hdr_len);
530
531 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
532 * radio tap header and 802.11 header starts
533 */
534 hdr = (struct ieee80211_hdr *)skb->data;
535
536 /* Send data frames through the normal Data path. In this path we will
537 * conver rcvd 802.11 packet to 802.3 packet */
538 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
539 {
540 v_U8_t da[6];
541 v_U8_t sa[6];
542
543 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
544 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
545
546 /* Pull 802.11 MAC header */
547 skb_pull(skb, HDD_80211_HEADER_LEN);
548
549 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
550 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
551 {
552 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
553 }
554
555 /* Pull LLC header */
556 skb_pull(skb, HDD_LLC_HDR_LEN);
557
558 /* Create space for Ethernet header */
559 skb_push(skb, HDD_MAC_HDR_SIZE*2);
560 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
561 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
562
563 /* Only EAPOL Data packets are allowed through monitor interface */
564 if (vos_be16_to_cpu(
565 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
566 != HDD_ETHERTYPE_802_1_X)
567 {
c_hpothu32490782014-03-14 19:14:34 +0530568 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700569 "%s: Not a Eapol packet. Drop this frame", __func__);
570 //If not EAPOL frames, drop them.
571 kfree_skb(skb);
572 return NETDEV_TX_OK;
573 }
574
575 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
576
577 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
578 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
579 }
580 else
581 {
582 VOS_STATUS status;
583 WLANTL_ACEnumType ac = 0;
584 skb_list_node_t *pktNode = NULL;
585 v_SIZE_t pktListSize = 0;
586
587 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
588 //If we have already reached the max queue size, disable the TX queue
589 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
590 {
591 /* We want to process one packet at a time, so lets disable all TX queues
592 * and re-enable the queues once we get TX feedback for this packet */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530593 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700594 netif_tx_stop_all_queues(pAdapter->dev);
595 pAdapter->isTxSuspended[ac] = VOS_TRUE;
596 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
597 return NETDEV_TX_BUSY;
598 }
599 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
600
601 //Use the skb->cb field to hold the list node information
602 pktNode = (skb_list_node_t *)&skb->cb;
603
604 //Stick the OS packet inside this node.
605 pktNode->skb = skb;
606
607 INIT_LIST_HEAD(&pktNode->anchor);
608
609 //Insert the OS packet into the appropriate AC queue
610 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
611 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
612 &pktNode->anchor, &pktListSize );
613 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
614
615 if ( !VOS_IS_STATUS_SUCCESS( status ) )
616 {
c_hpothu32490782014-03-14 19:14:34 +0530617 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700618 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 kfree_skb(skb);
620 return NETDEV_TX_OK;
621 }
622
623 if ( pktListSize == 1 )
624 {
625 /* In this context we cannot acquire any mutex etc. And to transmit
626 * this packet we need to call SME API. So to take care of this we will
627 * schedule a workqueue
628 */
629 schedule_work(&pPgBkAdapter->monTxWorkQueue);
630 }
631 return NETDEV_TX_OK;
632 }
633
634fail:
c_hpothu32490782014-03-14 19:14:34 +0530635 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700636 "%s: Packet Rcvd at Monitor interface is not proper,"
637 " Dropping the packet",
638 __func__);
639 kfree_skb(skb);
640 return NETDEV_TX_OK;
641}
Dino Mycled9b7cc12014-09-04 18:43:07 +0530642
643/**============================================================================
644 @brief hdd_dhcp_pkt_info() -
645 Function to log DHCP pkt info
646
647 @param skb : [in] pointer to OS packet (sk_buff)
648 @return : None
649 ===========================================================================*/
650
651void hdd_dhcp_pkt_info(struct sk_buff *skb)
652{
653 /* port no 67 (0x43) or 68 (0x44) */
654
655 if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_REQUEST_MSG)
656 hddLog(VOS_TRACE_LEVEL_INFO, FL("Request"));
657 else if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_RESPONSE_MSG)
658 hddLog(VOS_TRACE_LEVEL_INFO, FL("Response"));
659 else
660 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP invalid"));
661
662 hddLog(VOS_TRACE_LEVEL_INFO,
663 FL("DHCP Dest Addr: %pM Src Addr %pM "
664 " source port : %d, dest port : %d"),
665 skb->data, (skb->data + 6),
666 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))),
667 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))));
668
669 if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
670 (skb->data[DHCP_OPTION53_LENGTH_OFFSET] == DHCP_OPTION53_LENGTH)) {
671
672 switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
673 case DHCPDISCOVER:
674 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP DISCOVER"));
675 break;
676 case DHCPREQUEST:
677 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP REQUEST"));
678 break;
679 case DHCPOFFER:
680 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP OFFER"));
681 break;
682 case DHCPACK:
683 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP ACK"));
684 break;
685 case DHCPNAK:
686 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP NACK"));
687 break;
688 case DHCPRELEASE:
689 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP RELEASE"));
690 break;
691 case DHCPINFORM:
692 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP INFORM"));
693 break;
694
695 default:
696 hddLog(VOS_TRACE_LEVEL_INFO,
697 "%s: DHCP Not Defined OPTION53 : %d", __func__,
698 skb->data[DHCP_OPTION53_STATUS_OFFSET]);
699 }
700 }
701}
702
703/**============================================================================
704 @brief hdd_dump_dhcp_pkt() -
705 Function to dump DHCP packets in TX and RX path.
706
707 @param skb : [in] pointer to OS packet (sk_buff)
708 @param path : [in] bool indicating TX/RX path
709 @return : None
710 ===========================================================================*/
711void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path)
712{
713
714 if ((ntohs(*((u16*)((u8*)skb->data + ETH_TYPE_OFFSET)))
715 == ETH_TYPE_IP_PKT) ||
716 (ntohs(*((u8*)skb->data + PROTOCOL_OFFSET)) == UDP_PROTOCOL)) {
717
718 /* IP protocol 12 bytes of mac addresses in 802.3 header */
719 if ( ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
720 BOOTP_SERVER_PORT ||
721 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
722 BOOTP_CLIENT_PORT ||
723 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
724 BOOTP_SERVER_PORT ||
725 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
726 BOOTP_CLIENT_PORT ) {
727
728 if (path == TX_PATH) {
729 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP TX PATH"));
730 } else {
731 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP RX PATH"));
732 }
733
734 hdd_dhcp_pkt_info(skb);
735 }
736 }
737}
738
Jeff Johnson295189b2012-06-20 16:38:30 -0700739/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530740 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 transmitting packets. There are 2 versions of this function. One that uses
742 locked queue and other that uses lockless queues. Both have been retained to
743 do some performance testing
744
745 @param skb : [in] pointer to OS packet (sk_buff)
746 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530747
Jeff Johnson295189b2012-06-20 16:38:30 -0700748 @return : NET_XMIT_DROP if packets are dropped
749 : NET_XMIT_SUCCESS if packet is enqueued succesfully
750 ===========================================================================*/
751int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
752{
753 VOS_STATUS status;
754 WLANTL_ACEnumType ac;
755 sme_QosWmmUpType up;
756 skb_list_node_t *pktNode = NULL;
757 hdd_list_node_t *anchor = NULL;
758 v_SIZE_t pktListSize = 0;
759 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
760 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700761 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700762 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Dino Mycled9b7cc12014-09-04 18:43:07 +0530763 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700764 v_BOOL_t txSuspended = VOS_FALSE;
Mihir Shetef8f74532014-12-04 11:53:34 +0530765 struct sk_buff *skb1;
Jeff Johnson295189b2012-06-20 16:38:30 -0700766
767 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
768
Ravi Joshif9520d62013-10-18 04:11:46 -0700769 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530770 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700771 "%s is called when netif TX %d is disabled",
772 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530773 return NETDEV_TX_BUSY;
774 }
775
Ravi Joshicc57ed42013-10-12 16:31:25 -0700776 //Get TL AC corresponding to Qdisc queue index/AC.
777 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
778
779 if (WLAN_HDD_IBSS == pAdapter->device_mode)
Shailender Karmuchia734f332013-04-19 14:02:48 -0700780 {
781 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
782
Ravi Joshif9520d62013-10-18 04:11:46 -0700783 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
Ravi Joshicc57ed42013-10-12 16:31:25 -0700784 {
c_hpothu32490782014-03-14 19:14:34 +0530785 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700786 "%s: Tx frame in disconnected state in IBSS mode", __func__);
787 ++pAdapter->stats.tx_dropped;
788 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
789 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
790 kfree_skb(skb);
791 return NETDEV_TX_OK;
792 }
793
Shailender Karmuchia734f332013-04-19 14:02:48 -0700794 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
795
796 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
797 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
798 vos_is_macaddr_group(pDestMacAddress)))
799 {
800 STAId = IBSS_BROADCAST_STAID;
c_hpothu32490782014-03-14 19:14:34 +0530801 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Ravi Joshif9520d62013-10-18 04:11:46 -0700802 "%s: BC/MC packet", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700803 }
804 else if (STAId == HDD_WLAN_INVALID_STA_ID)
805 {
c_hpothu32490782014-03-14 19:14:34 +0530806 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshif9520d62013-10-18 04:11:46 -0700807 "%s: Received Unicast frame with invalid staID", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700808 ++pAdapter->stats.tx_dropped;
809 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700810 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Shailender Karmuchia734f332013-04-19 14:02:48 -0700811 kfree_skb(skb);
812 return NETDEV_TX_OK;
813 }
814 }
815 else
816 {
817 STAId = pHddStaCtx->conn_info.staId[0];
818 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700819
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530820 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700821 //select_queue call back function
822 up = skb->priority;
823
824 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
825
826#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530827 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700828 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700829#endif // HDD_WMM_DEBUG
830
Mukul Sharma84f27252014-07-14 18:11:42 +0530831#ifdef DEBUG_ROAM_DELAY
832 vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
833 //Should we check below global to avoid function call each time ??
834/*
835 if(gRoamDelayMetaInfo.hdd_monitor_tx)
836 {
837 }
838 */
839#endif
840
Jeff Johnson295189b2012-06-20 16:38:30 -0700841 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700842 /*CR 463598,384996*/
843 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
844 *We check for +1 in the logic,to take care of Zero count which
845 *occurs very frequently in low traffic cases */
846 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
847 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700848 /* 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 -0700849 * if it is in the mainline code and if the log level is enabled by someone for debugging
c_hpothu32490782014-03-14 19:14:34 +0530850 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"%s:Queue is Filling up.Inform TL again about pending packets", __func__);*/
Shailender Karmuchia734f332013-04-19 14:02:48 -0700851
Ravi Joshi8a934352013-09-25 16:46:58 -0700852 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
853 STAId, ac
854 );
855 if ( !VOS_IS_STATUS_SUCCESS( status ) )
856 {
c_hpothu32490782014-03-14 19:14:34 +0530857 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700858 "%s: WLANTL_STAPktPending() returned error code %d",
859 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700860 ++pAdapter->stats.tx_dropped;
861 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
862 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Ravi Joshi8a934352013-09-25 16:46:58 -0700863 kfree_skb(skb);
864 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
865 return NETDEV_TX_OK;
866 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700867 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700868 //If we have already reached the max queue size, disable the TX queue
869 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
870 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700871 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
872 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530873 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for ac %d"),ac);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700874 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
875 pAdapter->isTxSuspended[ac] = VOS_TRUE;
876 txSuspended = VOS_TRUE;
Mihir Shete5d148f12014-12-16 17:54:49 +0530877 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_NETDEV,
878 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700879 }
880
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530881 /* If 3/4th of the max queue size is used then enable the flag.
882 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
883 if (WLANTL_AC_BE == ac)
884 {
885 if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
886 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530887 pAdapter->isVosLowResource = VOS_TRUE;
888 }
889 else
890 {
891 pAdapter->isVosLowResource = VOS_FALSE;
892 }
893 }
894
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530895 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530896
Sachin Ahuja8c65f382014-12-12 15:34:21 +0530897 if (( NULL != pHddCtx ) &&
898 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +0530899 {
900 hdd_dump_dhcp_pkt(skb, TX_PATH);
901 }
902
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 if (VOS_TRUE == txSuspended)
904 {
c_hpothu32490782014-03-14 19:14:34 +0530905 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530906 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700907 __func__, ac );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530908 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700909 }
910
911 //Use the skb->cb field to hold the list node information
912 pktNode = (skb_list_node_t *)&skb->cb;
913
914 //Stick the OS packet inside this node.
915 pktNode->skb = skb;
916
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530917 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700918 pktNode->userPriority = up;
919
920
921 INIT_LIST_HEAD(&pktNode->anchor);
922
923 //Insert the OS packet into the appropriate AC queue
924 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
925 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
926 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
927
928 if ( !VOS_IS_STATUS_SUCCESS( status ) )
929 {
c_hpothu32490782014-03-14 19:14:34 +0530930 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700931 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
932 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
933 ++pAdapter->stats.tx_dropped;
934 kfree_skb(skb);
935 return NETDEV_TX_OK;
936 }
937
938 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
939 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700940 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700941
Kiet Lamf040f472013-11-20 21:15:23 +0530942 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
943 {
944 /* Function which will determine acquire admittance for a
945 * WMM AC is required or not based on psb configuration done
946 * in the framework
947 */
948 hdd_wmm_acquire_access_required(pAdapter, ac);
949 }
950
Jeff Johnson295189b2012-06-20 16:38:30 -0700951 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530952 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
953 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700954 {
955 granted = VOS_TRUE;
956 }
957 else
958 {
959 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530960 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700961 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700962 if ( granted && ( pktListSize == 1 ))
963 {
964 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +0530965 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700966 status = WLANTL_STAPktPending(
967 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
968 STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 if ( !VOS_IS_STATUS_SUCCESS( status ) )
970 {
c_hpothu32490782014-03-14 19:14:34 +0530971 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d", __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700972
973 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
974 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
975 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
976 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
977 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Mihir Shetef8f74532014-12-04 11:53:34 +0530978 /* Free the skb only if we are able to remove it from the list.
979 * If we are not able to retrieve it from the list it means that
980 * the skb was pulled by TX Thread and is use so we should not free
981 * it here
982 */
983 if (VOS_IS_STATUS_SUCCESS(status))
984 {
985 pktNode = list_entry(anchor, skb_list_node_t, anchor);
986 skb1 = pktNode->skb;
987 kfree_skb(skb1);
988 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700989 ++pAdapter->stats.tx_dropped;
990 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
991 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Jeff Johnson295189b2012-06-20 16:38:30 -0700992 return NETDEV_TX_OK;
993 }
994 }
995
996 dev->trans_start = jiffies;
997
998 return NETDEV_TX_OK;
999}
1000
1001/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -07001002 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
1003
1004 @param pHddStaCtx : [in] pointer to HDD Station Context
1005 pMacAddress [in] pointer to Peer Mac address
1006 staID [out] pointer to Station Index
1007 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
1008 ===========================================================================*/
1009
1010VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1011{
1012 v_U8_t idx;
1013
1014 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
1015 {
1016 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
1017 pMacAddress, sizeof(v_MACADDR_t)))
1018 {
1019 *staId = pHddStaCtx->conn_info.staId[idx];
1020 return VOS_STATUS_SUCCESS;
1021 }
1022 }
1023
1024 return VOS_STATUS_E_FAILURE;
1025}
1026
1027/**============================================================================
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301028 @brief __hdd_tx_timeout() - Function handles timeout during transmission.
Jeff Johnson295189b2012-06-20 16:38:30 -07001029
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301030 @param dev : [in] pointer to network device
Jeff Johnson295189b2012-06-20 16:38:30 -07001031 @return : None
1032 ===========================================================================*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301033void __hdd_tx_timeout(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001034{
Ravi Joshicc57ed42013-10-12 16:31:25 -07001035 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1036 struct netdev_queue *txq;
1037 int i = 0;
Mukul Sharma42b3d432014-10-16 16:13:40 +05301038 v_ULONG_t diff_in_jiffies = 0;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001039
Mihir Shetef3473692014-06-27 15:13:20 +05301040 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301041 "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu",
1042 __func__,jiffies,dev->trans_start);
Mihir Shetef3473692014-06-27 15:13:20 +05301043
c_hpothub8245442013-11-20 23:41:09 +05301044 if ( NULL == pAdapter )
1045 {
c_hpothu32490782014-03-14 19:14:34 +05301046 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301047 FL("pAdapter is NULL"));
1048 VOS_ASSERT(0);
1049 return;
1050 }
1051
Mihir Shetef3473692014-06-27 15:13:20 +05301052 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
1053
Jeff Johnson295189b2012-06-20 16:38:30 -07001054 //Getting here implies we disabled the TX queues for too long. Queues are
1055 //disabled either because of disassociation or low resource scenarios. In
1056 //case of disassociation it is ok to ignore this. But if associated, we have
1057 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -07001058
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301059 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001060 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
1061 pAdapter->wmm_tx_queue[0].count,
1062 pAdapter->wmm_tx_queue[1].count,
1063 pAdapter->wmm_tx_queue[2].count,
1064 pAdapter->wmm_tx_queue[3].count);
1065
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301066 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001067 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
1068 pAdapter->isTxSuspended[0],
1069 pAdapter->isTxSuspended[1],
1070 pAdapter->isTxSuspended[2],
1071 pAdapter->isTxSuspended[3]);
1072
1073 for (i = 0; i < 8; i++)
1074 {
1075 txq = netdev_get_tx_queue(dev, i);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301076 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301077 "Queue%d status: %d txq->trans_start %lu",
1078 i, netif_tx_queue_stopped(txq),txq->trans_start);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001079 }
1080
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301081 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001082 "carrier state: %d", netif_carrier_ok(dev));
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301083
Mihir Shetef3473692014-06-27 15:13:20 +05301084 /* continuousTxTimeoutCount will be reset whenever TL fetches packet
1085 * from HDD
1086 */
1087 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
1088
Mukul Sharma42b3d432014-10-16 16:13:40 +05301089 diff_in_jiffies = jiffies - pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut;
1090 if((pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount > 1)&&
1091 ((diff_in_jiffies) > (HDD_TX_TIMEOUT * 2 ))
1092 )
1093 {
1094 /*
1095 * In Open security case when there is no traffic is running, it may possible
1096 * tx time-out may once happen and later we recovered then we need to
1097 * reset the continuousTxTimeoutCount because it is only getting modified
1098 * when traffic is running. So if over a period of time if this count reaches
1099 * to HDD_TX_STALL_SSR_THRESHOLD then host is triggering false subsystem restart.
1100 * so in genuine Tx Time out case kernel will call the tx time-out back to back at
1101 * interval of HDD_TX_TIMEOUT.So now we are checking if previous TX TIME out was
1102 * occurred more then twice of HDD_TX_TIMEOUT back then we may recovered here.
1103 */
1104 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1105 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1106 FL("This is false alarm so resetting the continuousTxTimeoutCount"));
1107 }
1108
1109 //update last jiffies after the check
1110 pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut = jiffies;
1111
Mihir Shete327c2ab2014-11-13 15:17:02 +05301112 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
1113 HDD_TX_STALL_RECOVERY_THRESHOLD)
1114 {
1115 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1116 "%s: Request firmware for recovery",__func__);
1117 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
1118 }
1119
Mihir Shetef3473692014-06-27 15:13:20 +05301120 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1121 HDD_TX_STALL_SSR_THRESHOLD)
1122 {
1123 // Driver could not recover, issue SSR
1124 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1125 "%s: Cannot recover from Data stall Issue SSR",
1126 __func__);
Mihir Shetefd62d9d2014-08-06 15:08:21 +05301127 WLANTL_FatalError();
Mihir Shetef3473692014-06-27 15:13:20 +05301128 return;
1129 }
1130
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301131 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
1132 * every 5sec. The TL debug spits out a lot of information on the
1133 * serial console, if it is called every time *hdd_tx_timeout* is
1134 * called then we may get a watchdog bite on the Application
1135 * processor, so ratelimit the TL debug logs.
1136 */
1137 if (__ratelimit(&hdd_tx_timeout_rs))
1138 {
1139 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +05301140 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301141 }
Mihir Shetef3473692014-06-27 15:13:20 +05301142
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301143}
Jeff Johnson295189b2012-06-20 16:38:30 -07001144
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301145/**============================================================================
1146 @brief hdd_tx_timeout() - Function called by OS if there is any
1147 timeout during transmission. Since HDD simply enqueues packet
1148 and returns control to OS right away, this would never be invoked
1149
1150 @param dev : [in] pointer to network device
1151 @return : None
1152 ===========================================================================*/
1153void hdd_tx_timeout(struct net_device *dev)
1154{
1155 vos_ssr_protect(__func__);
1156 __hdd_tx_timeout(dev);
1157 vos_ssr_unprotect(__func__);
1158}
Jeff Johnson295189b2012-06-20 16:38:30 -07001159
1160/**============================================================================
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301161 @brief __hdd_stats() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -07001162 device TX/RX statistic
1163
1164 @param dev : [in] pointer to Libra network device
1165
1166 @return : pointer to net_device_stats structure
1167 ===========================================================================*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301168struct net_device_stats* __hdd_stats(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001169{
1170 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +05301171
1172 if ( NULL == pAdapter )
1173 {
c_hpothu32490782014-03-14 19:14:34 +05301174 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301175 FL("pAdapter is NULL"));
1176 VOS_ASSERT(0);
1177 return NULL;
1178 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001179
1180 return &pAdapter->stats;
1181}
1182
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301183struct net_device_stats* hdd_stats(struct net_device *dev)
1184{
1185 struct net_device_stats* dev_stats;
1186
1187 vos_ssr_protect(__func__);
1188 dev_stats = __hdd_stats(dev);
1189 vos_ssr_unprotect(__func__);
1190
1191 return dev_stats;
1192}
Jeff Johnson295189b2012-06-20 16:38:30 -07001193
1194/**============================================================================
1195 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
1196 modules in HDD
1197
1198 @param pAdapter : [in] pointer to adapter context
1199 @return : VOS_STATUS_E_FAILURE if any errors encountered
1200 : VOS_STATUS_SUCCESS otherwise
1201 ===========================================================================*/
1202VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
1203{
1204 VOS_STATUS status = VOS_STATUS_SUCCESS;
1205 v_SINT_t i = -1;
1206
c_hpothub8245442013-11-20 23:41:09 +05301207 if ( NULL == pAdapter )
1208 {
c_hpothu32490782014-03-14 19:14:34 +05301209 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301210 FL("pAdapter is NULL"));
1211 VOS_ASSERT(0);
1212 return VOS_STATUS_E_FAILURE;
1213 }
1214
Jeff Johnson295189b2012-06-20 16:38:30 -07001215 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301216 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001217
1218 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
1219 //Will be zeroed out during alloc
1220
1221 while (++i != NUM_TX_QUEUES)
1222 {
1223 pAdapter->isTxSuspended[i] = VOS_FALSE;
1224 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1225 }
1226
1227 return status;
1228}
1229
1230
1231/**============================================================================
1232 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
1233 modules in HDD
1234
1235 @param pAdapter : [in] pointer to adapter context
1236 @return : VOS_STATUS_E_FAILURE if any errors encountered
1237 : VOS_STATUS_SUCCESS otherwise
1238 ===========================================================================*/
1239VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
1240{
1241 VOS_STATUS status = VOS_STATUS_SUCCESS;
1242 v_SINT_t i = -1;
1243
c_hpothub8245442013-11-20 23:41:09 +05301244 if ( NULL == pAdapter )
1245 {
c_hpothu32490782014-03-14 19:14:34 +05301246 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301247 FL("pAdapter is NULL"));
1248 VOS_ASSERT(0);
1249 return VOS_STATUS_E_FAILURE;
1250 }
1251
Jeff Johnson295189b2012-06-20 16:38:30 -07001252 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301253 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301254 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301255 FL("failed to flush tx queues"));
1256
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 while (++i != NUM_TX_QUEUES)
1258 {
1259 //Free up actual list elements in the Tx queue
1260 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1261 }
1262
1263 return status;
1264}
1265
1266
1267/**============================================================================
1268 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1269 modules in HDD
1270
1271 @param pAdapter : [in] pointer to adapter context
1272 @return : VOS_STATUS_E_FAILURE if any errors encountered
1273 : VOS_STATUS_SUCCESS otherwise
1274 ===========================================================================*/
1275VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1276{
1277 return hdd_flush_tx_queues(pAdapter);
1278}
1279
1280
1281/**============================================================================
1282 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1283
1284 @param pVosPacket : [in] pointer to vos packet
1285 @return : VOS_TRUE if the packet is EAPOL
1286 : VOS_FALSE otherwise
1287 ===========================================================================*/
1288
1289v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1290{
1291 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1292 v_BOOL_t fEAPOL = VOS_FALSE;
1293 void *pBuffer = NULL;
1294
1295
1296 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1297 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
Abhishek Singhfa011222014-04-14 10:57:08 +05301298 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001299 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301300 if ( pBuffer && *(unsigned short*)pBuffer ==
1301 vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001302 {
1303 fEAPOL = VOS_TRUE;
1304 }
1305 }
1306
1307 return fEAPOL;
1308}
1309
Abhishek Singhfa011222014-04-14 10:57:08 +05301310/**============================================================================
1311 @brief hdd_IsARP() - Checks the packet is ARP or not.
1312
1313 @param pVosPacket : [in] pointer to vos packet
1314 @return : VOS_TRUE if the packet is ARP
1315 : VOS_FALSE otherwise
1316 ===========================================================================*/
1317
1318v_BOOL_t hdd_IsARP( vos_pkt_t *pVosPacket )
1319{
1320 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1321 v_BOOL_t fIsARP = VOS_FALSE;
1322 void *pBuffer = NULL;
1323
1324
1325 vosStatus = vos_pkt_peek_data( pVosPacket,
1326 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1327 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1328 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1329 {
1330 if ( pBuffer && *(unsigned short*)pBuffer ==
1331 vos_cpu_to_be16(HDD_ETHERTYPE_ARP) )
1332 {
1333 fIsARP = VOS_TRUE;
1334 }
1335 }
1336
1337 return fIsARP;
1338}
Jeff Johnson295189b2012-06-20 16:38:30 -07001339
1340#ifdef FEATURE_WLAN_WAPI // Need to update this function
1341/**============================================================================
1342 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1343
1344 @param pVosPacket : [in] pointer to vos packet
1345 @return : VOS_TRUE if the packet is WAI
1346 : VOS_FALSE otherwise
1347 ===========================================================================*/
1348
1349v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1350{
1351 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1352 v_BOOL_t fIsWAI = VOS_FALSE;
1353 void *pBuffer = NULL;
1354
1355 // Need to update this function
1356 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1357 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1358
1359 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1360 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301361 if ( pBuffer && *(unsigned short*)pBuffer ==
1362 vos_cpu_to_be16(HDD_ETHERTYPE_WAI) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001363 {
1364 fIsWAI = VOS_TRUE;
1365 }
1366 }
1367
1368 return fIsWAI;
1369}
1370#endif /* FEATURE_WLAN_WAPI */
1371
1372/**============================================================================
1373 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1374 to indicate that a packet has been transmitted across the SDIO bus
1375 succesfully. OS packet resources can be released after this cbk.
1376
1377 @param vosContext : [in] pointer to VOS context
1378 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1379 @param vosStatusIn : [in] status of the transmission
1380
1381 @return : VOS_STATUS_E_FAILURE if any errors encountered
1382 : VOS_STATUS_SUCCESS otherwise
1383 ===========================================================================*/
1384VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1385 vos_pkt_t *pVosPacket,
1386 VOS_STATUS vosStatusIn )
1387{
1388 VOS_STATUS status = VOS_STATUS_SUCCESS;
1389 hdd_adapter_t *pAdapter = NULL;
1390 hdd_context_t *pHddCtx = NULL;
1391 void* pOsPkt = NULL;
1392
1393 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1394 {
c_hpothu32490782014-03-14 19:14:34 +05301395 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301396 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001397 return VOS_STATUS_E_FAILURE;
1398 }
1399
1400 //Return the skb to the OS
1401 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301402 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001403 {
1404 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301405 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301406 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 vos_pkt_return_packet( pVosPacket );
1408 return VOS_STATUS_E_FAILURE;
1409 }
1410
1411 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001412 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001413 //Get the Adapter context.
1414 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Agarwal Ashish971c2882013-10-30 20:11:12 +05301415 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07001416 {
c_hpothu32490782014-03-14 19:14:34 +05301417 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301418 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001419 }
1420 else
1421 {
1422 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1423 }
1424
1425 kfree_skb((struct sk_buff *)pOsPkt);
1426
1427 //Return the VOS packet resources.
1428 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301429 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001430 {
c_hpothu32490782014-03-14 19:14:34 +05301431 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301432 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001433 }
1434
1435 return status;
1436}
1437
1438
1439/**============================================================================
1440 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1441 fetch a packet for transmission.
1442
1443 @param vosContext : [in] pointer to VOS context
1444 @param staId : [in] Station for which TL is requesting a pkt
1445 @param ac : [in] access category requested by TL
1446 @param pVosPacket : [out] pointer to VOS packet packet pointer
1447 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1448
1449 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1450 : VOS_STATUS_E_FAILURE if any errors encountered
1451 : VOS_STATUS_SUCCESS otherwise
1452 ===========================================================================*/
1453VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1454 v_U8_t *pStaId,
1455 WLANTL_ACEnumType ac,
1456 vos_pkt_t **ppVosPacket,
1457 WLANTL_MetaInfoType *pPktMetaInfo )
1458{
1459 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1460 hdd_adapter_t *pAdapter = NULL;
1461 hdd_context_t *pHddCtx = NULL;
1462 hdd_list_node_t *anchor = NULL;
1463 skb_list_node_t *pktNode = NULL;
1464 struct sk_buff *skb = NULL;
1465 vos_pkt_t *pVosPacket = NULL;
1466 v_MACADDR_t* pDestMacAddress = NULL;
1467 v_TIME_t timestamp;
1468 WLANTL_ACEnumType newAc;
1469 v_SIZE_t size = 0;
Abhishek Singhfa011222014-04-14 10:57:08 +05301470 v_U16_t packet_size;
Jeff Johnson295189b2012-06-20 16:38:30 -07001471 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001472 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001473
1474 //Sanity check on inputs
1475 if ( ( NULL == vosContext ) ||
1476 ( NULL == pStaId ) ||
1477 ( NULL == ppVosPacket ) ||
1478 ( NULL == pPktMetaInfo ) )
1479 {
c_hpothu32490782014-03-14 19:14:34 +05301480 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301481 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001482 return VOS_STATUS_E_FAILURE;
1483 }
1484
1485 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001486 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001487 if(pHddCtx == NULL)
1488 {
c_hpothu32490782014-03-14 19:14:34 +05301489 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301490 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001491 return VOS_STATUS_E_FAILURE;
1492 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001493 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001494 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001495 {
c_hpothu32490782014-03-14 19:14:34 +05301496 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301497 FL("pAdapter is NULL %u"), *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001498 VOS_ASSERT(0);
1499 return VOS_STATUS_E_FAILURE;
1500 }
1501
1502 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1503
1504 *ppVosPacket = NULL;
1505
1506 //Make sure the AC being asked for is sane
1507 if( ac >= WLANTL_MAX_AC || ac < 0)
1508 {
c_hpothu32490782014-03-14 19:14:34 +05301509 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301510 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001511 return VOS_STATUS_E_FAILURE;
1512 }
1513
1514 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1515
1516#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301517 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301518 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001519#endif // HDD_WMM_DEBUG
1520
1521 // We find an AC with packets
1522 // or we determine we have no more packets to send
1523 // HDD is not allowed to change AC.
1524
1525 // has this AC been admitted? or
1526 // To allow EAPOL packets when not authenticated
1527 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1528 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1529 {
1530 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1531#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301532 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001533 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001534#endif // HDD_WMM_DEBUG
1535 return VOS_STATUS_E_FAILURE;
1536 }
1537
1538 // do we have any packets pending in this AC?
1539 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1540 if( size > 0 )
1541 {
1542 // yes, so process it
1543#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301544 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001545 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001546#endif // HDD_WMM_DEBUG
1547 }
1548 else
1549 {
1550 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1551#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301552 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001553 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001554#endif // HDD_WMM_DEBUG
1555 return VOS_STATUS_E_FAILURE;
1556 }
1557
1558 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1559 //This simplifies the locking and unlocking of Tx queue
1560 status = vos_pkt_wrap_data_packet( &pVosPacket,
1561 VOS_PKT_TYPE_TX_802_3_DATA,
1562 NULL, //OS Pkt is not being passed
1563 hdd_tx_low_resource_cbk,
1564 pAdapter );
1565
1566 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1567 {
1568 //Remember VOS is in a low resource situation
1569 pAdapter->isVosOutOfResource = VOS_TRUE;
1570 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05301571 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOSS in Low Resource scenario", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001572 //TL will now think we have no more packets in this AC
1573 return VOS_STATUS_E_FAILURE;
1574 }
1575
1576 //Remove the packet from the queue
1577 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1578 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1579 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1580
1581 if(VOS_STATUS_SUCCESS == status)
1582 {
1583 //If success then we got a valid packet from some AC
1584 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1585 skb = pktNode->skb;
1586 }
1587 else
1588 {
1589 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05301590 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001591 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 vos_pkt_return_packet(pVosPacket);
1593 return VOS_STATUS_E_FAILURE;
1594 }
Abhishek Singh45e68fe2014-12-11 12:55:59 +05301595 /* In IBSS the staID can change and hdd uses the same queue for all staid.
1596 * Due to this the fetch may be called for staID x, but data might be of
1597 * staID y. So better get the staId again from SKB and use this to process
1598 * the packet further.
1599 */
1600 if (WLAN_HDD_IBSS == pAdapter->device_mode)
1601 {
1602 *pStaId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
Jeff Johnson295189b2012-06-20 16:38:30 -07001603
Abhishek Singh45e68fe2014-12-11 12:55:59 +05301604 /* If HDD_WLAN_INVALID_STA_ID no need to check the destination,
1605 * just make the staID 0. As if HDD_WLAN_INVALID_STA_ID and
1606 * destination is not BC of MC, the packet is already dropped in
1607 * hdd_hard_start_xmit.
1608 */
1609 if (*pStaId == HDD_WLAN_INVALID_STA_ID)
1610 *pStaId = IBSS_BROADCAST_STAID;
1611 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001612 //Attach skb to VOS packet.
1613 status = vos_pkt_set_os_packet( pVosPacket, skb );
1614 if (status != VOS_STATUS_SUCCESS)
1615 {
c_hpothu32490782014-03-14 19:14:34 +05301616 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 vos_pkt_return_packet(pVosPacket);
1618 ++pAdapter->stats.tx_dropped;
1619 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1620 kfree_skb(skb);
1621 return VOS_STATUS_E_FAILURE;
1622 }
1623
1624 //Just being paranoid. To be removed later
1625 if(pVosPacket == NULL)
1626 {
c_hpothu32490782014-03-14 19:14:34 +05301627 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOS packet returned by VOSS is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001628 ++pAdapter->stats.tx_dropped;
1629 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1630 kfree_skb(skb);
1631 return VOS_STATUS_E_FAILURE;
1632 }
1633
Dino Mycle3b9536d2014-07-09 22:05:24 +05301634#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1635 {
1636 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
1637 /* vos_is_macaddr_group expects data in v_MACADDR_t format
1638 */
1639 if (vos_is_macaddr_group(pDestMacAddress))
1640 {
1641 pAdapter->hdd_stats.hddTxRxStats.txMcast[ac]++;
1642 }
1643
1644 }
1645
1646#endif
1647
Chilam NG571c65a2013-01-19 12:27:36 +05301648#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001649 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05301650 {
1651 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301652 u8 mac[6];
1653
Hoonki Lee387663d2013-02-05 18:08:43 -08001654 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301655
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001656 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05301657 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301658 "broadcast packet, not adding to peer list");
1659 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1660 mac, 6) != 0) {
c_hpothu32490782014-03-14 19:14:34 +05301661 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001662 "extract mac: " MAC_ADDRESS_STR,
1663 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05301664
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001665 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301666 } else {
c_hpothu32490782014-03-14 19:14:34 +05301667 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301668 "packet da is bssid, not adding to peer list");
1669 }
1670 }
1671#endif
1672
Jeff Johnson295189b2012-06-20 16:38:30 -07001673 //Return VOS packet to TL;
1674 *ppVosPacket = pVosPacket;
1675
1676 //Fill out the meta information needed by TL
1677 //FIXME This timestamp is really the time stamp of wrap_data_packet
1678 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1679 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1680
1681 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1682 pPktMetaInfo->ucIsEapol = 0;
1683 else
1684 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1685
Sachin Ahuja8c65f382014-12-12 15:34:21 +05301686 if ((NULL != pHddCtx) &&
1687 (pHddCtx->cfg_ini->gEnableDebugLog))
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001688 {
1689 proto_type = vos_pkt_get_proto_type(skb,
1690 pHddCtx->cfg_ini->gEnableDebugLog);
1691 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1692 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05301693 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001694 "STA TX EAPOL");
1695 }
1696 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1697 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05301698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001699 "STA TX DHCP");
1700 }
1701 }
1702
Abhishek Singhfa011222014-04-14 10:57:08 +05301703 vos_pkt_get_packet_length( pVosPacket,&packet_size );
1704 if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
1705 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
1706
Jeff Johnson295189b2012-06-20 16:38:30 -07001707#ifdef FEATURE_WLAN_WAPI
1708 // Override usIsEapol value when its zero for WAPI case
1709 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
1710#endif /* FEATURE_WLAN_WAPI */
1711
1712 if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) ||
1713 (!pAdapter->hddWmmStatus.wmmQap))
1714 {
1715 // either we don't want QoS or the AP doesn't support QoS
1716 pPktMetaInfo->ucUP = 0;
1717 pPktMetaInfo->ucTID = 0;
1718 }
1719 else
1720 {
1721 /* 1. Check if ACM is set for this AC
1722 * 2. If set, check if this AC had already admitted
Mukul Sharma95f79cb2014-11-24 12:50:24 +05301723 * 3. If not already admitted, downgrade the UP to next best UP
1724 * 4. Allow only when medium time is non zero when Addts accepted else downgrade traffic.
1725 we opted downgrading over Delts when medium time is zero because while doing downgradig
1726 driver is not clearing the wmm context so consider in subsequent roaming if AP (new or
1727 same AP) accept the Addts with valid medium time no application support is required
1728 where if we have opted delts Applications have to again do Addts or STA will never
1729 go for Addts.*/
1730
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
Mukul Sharma95f79cb2014-11-24 12:50:24 +05301732 (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid &&
1733 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07001734 {
1735 pPktMetaInfo->ucUP = pktNode->userPriority;
1736 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1737 }
1738 else
1739 {
1740 //Downgrade the UP
1741 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1742 newAc = WLANTL_AC_BK;
1743 for (i=ac-1; i>0; i--)
1744 {
1745 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1746 {
1747 newAc = i;
1748 break;
1749 }
1750 }
1751 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1752 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
c_hpothu32490782014-03-14 19:14:34 +05301753 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07001754 }
1755 }
1756
Mukul Sharma84f27252014-07-14 18:11:42 +05301757#ifdef DEBUG_ROAM_DELAY
1758 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
1759#endif
1760
Jeff Johnson295189b2012-06-20 16:38:30 -07001761 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1762 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1763 if ( 1 < size )
1764 {
1765 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1766 }
1767 else
1768 {
1769 pPktMetaInfo->bMorePackets = 0;
1770 }
1771
1772 //Extract the destination address from ethernet frame
1773 pDestMacAddress = (v_MACADDR_t*)skb->data;
1774 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1775 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1776
1777
1778
1779 // if we are in a backpressure situation see if we can turn the hose back on
1780 if ( (pAdapter->isTxSuspended[ac]) &&
1781 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1782 {
1783 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1784 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05301785 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001786 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001787 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1788 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1789 skb_get_queue_mapping(skb) ));
Mihir Shete5d148f12014-12-16 17:54:49 +05301790 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_WAKE_NETDEV,
1791 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001792 }
1793
1794
1795 // We're giving the packet to TL so consider it transmitted from
1796 // a statistics perspective. We account for it here instead of
1797 // when the packet is returned for two reasons. First, TL will
1798 // manipulate the skb to the point where the len field is not
1799 // accurate, leading to inaccurate byte counts if we account for
1800 // it later. Second, TL does not provide any feedback as to
1801 // whether or not the packet was successfully sent over the air,
1802 // so the packet counts will be the same regardless of where we
1803 // account for them
1804 pAdapter->stats.tx_bytes += skb->len;
1805 ++pAdapter->stats.tx_packets;
1806 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1807 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301808 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001809
Leo Chang50bbd252013-04-25 14:58:01 -07001810 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1811 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001812 {
1813 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1814 {
c_hpothu32490782014-03-14 19:14:34 +05301815 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001816 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001817 return VOS_STATUS_E_FAILURE;
1818 }
1819 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1820 {
1821 if(0 == pHddCtx->tmInfo.txFrameCount)
1822 {
1823 /* Just recovered from sleep timeout */
1824 pHddCtx->tmInfo.lastOpenTs = timestamp;
1825 }
1826
Leo Chang50bbd252013-04-25 14:58:01 -07001827 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1828 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001829 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1830 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001831 /* During TX open duration, TX frame count is larger than threshold
1832 * Block TX during Sleep time */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05301833 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001834 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001835 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001836 pHddCtx->tmInfo.lastblockTs = timestamp;
1837 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1838 {
1839 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1840 }
1841 }
1842 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1843 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1844 {
1845 /* During TX open duration, TX frame count is less than threshold
1846 * Reset count and timestamp to prepare next cycle */
1847 pHddCtx->tmInfo.lastOpenTs = timestamp;
1848 pHddCtx->tmInfo.txFrameCount = 0;
1849 }
1850 else
1851 {
1852 /* Do Nothing */
1853 }
1854 pHddCtx->tmInfo.txFrameCount++;
1855 }
1856 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1857 }
1858
1859
1860#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301861 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,"%s: Valid VOS PKT returned to TL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001862#endif // HDD_WMM_DEBUG
1863
1864 return status;
1865}
1866
1867
1868/**============================================================================
1869 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1870 case where VOS packets are not available at the time of the call to get
1871 packets. This callback function is invoked by VOS when packets are
1872 available.
1873
1874 @param pVosPacket : [in] pointer to VOS packet
1875 @param userData : [in] opaque user data that was passed initially
1876
1877 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1878 : VOS_STATUS_SUCCESS otherwise
1879 =============================================================================*/
1880VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1881 v_VOID_t *userData )
1882{
1883 VOS_STATUS status;
1884 v_SINT_t i = 0;
1885 v_SIZE_t size = 0;
1886 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1887
Agarwal Ashish971c2882013-10-30 20:11:12 +05301888 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001889 {
c_hpothu32490782014-03-14 19:14:34 +05301890 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301891 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001892 return VOS_STATUS_E_FAILURE;
1893 }
1894
1895 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1896 //situation. Here we will only signal TL that there is a pending data for a STA.
1897 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1898 vos_pkt_return_packet( pVosPacket );
1899
1900 pAdapter->isVosOutOfResource = VOS_FALSE;
1901
1902 //Indicate to TL that there is pending data if a queue is non empty
1903 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1904 {
1905 size = 0;
1906 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1907 if ( size > 0 )
1908 {
1909 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1910 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1911 (WLANTL_ACEnumType)i );
1912 if( !VOS_IS_STATUS_SUCCESS( status ) )
1913 {
c_hpothu32490782014-03-14 19:14:34 +05301914 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301915 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001916 }
1917 }
1918 }
1919
1920 return VOS_STATUS_SUCCESS;
1921}
1922
1923
1924/**============================================================================
1925 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1926 TL will call this to notify the HDD when one or more packets were
1927 received for a registered STA.
1928
1929 @param vosContext : [in] pointer to VOS context
1930 @param pVosPacketChain : [in] pointer to VOS packet chain
1931 @param staId : [in] Station Id
1932 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1933
1934 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1935 : VOS_STATUS_SUCCESS otherwise
1936 ===========================================================================*/
1937VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1938 vos_pkt_t *pVosPacketChain,
1939 v_U8_t staId,
1940 WLANTL_RxMetaInfoType* pRxMetaInfo )
1941{
1942 hdd_adapter_t *pAdapter = NULL;
1943 hdd_context_t *pHddCtx = NULL;
1944 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1945 int rxstat;
1946 struct sk_buff *skb = NULL;
1947 vos_pkt_t* pVosPacket;
1948 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001949 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001950
1951 //Sanity check on inputs
1952 if ( ( NULL == vosContext ) ||
1953 ( NULL == pVosPacketChain ) ||
1954 ( NULL == pRxMetaInfo ) )
1955 {
c_hpothu32490782014-03-14 19:14:34 +05301956 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301957 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001958 return VOS_STATUS_E_FAILURE;
1959 }
1960
Kiet Lam3c2ee302014-03-23 23:23:22 -07001961 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001962 if ( NULL == pHddCtx )
1963 {
c_hpothu32490782014-03-14 19:14:34 +05301964 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301965 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001966 return VOS_STATUS_E_FAILURE;
1967 }
1968
1969 pAdapter = pHddCtx->sta_to_adapter[staId];
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301970 if( (NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 {
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301972 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1973 "%s: pAdapter is Null or adapter has invalid magic for staId %u",
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05301974 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 return VOS_STATUS_E_FAILURE;
1976 }
1977
1978 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1979
1980 // walk the chain until all are processed
1981 pVosPacket = pVosPacketChain;
1982 do
1983 {
1984 // get the pointer to the next packet in the chain
1985 // (but don't unlink the packet since we free the entire chain later)
1986 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1987
1988 // both "success" and "empty" are acceptable results
1989 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1990 {
1991 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301992 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301993 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001994 return VOS_STATUS_E_FAILURE;
1995 }
1996
1997 // Extract the OS packet (skb).
1998 // Tell VOS to detach the OS packet from the VOS packet
1999 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
2000 if(!VOS_IS_STATUS_SUCCESS( status ))
2001 {
2002 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302003 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302004 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002005 return VOS_STATUS_E_FAILURE;
2006 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002007
2008 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2009 {
c_hpothu32490782014-03-14 19:14:34 +05302010 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07002011 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
2012 return eHAL_STATUS_FAILURE;
2013 }
2014
Chilam Ng1279e232013-01-25 15:06:52 -08002015#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002016 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
2017 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08002018 {
2019 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08002020 u8 mac[6];
2021
Hoonki Lee387663d2013-02-05 18:08:43 -08002022 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08002023
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002024 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302025 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002026 "rx broadcast packet, not adding to peer list");
2027 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2028 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002029 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05302030 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002031 "rx extract mac:" MAC_ADDRESS_STR,
2032 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302033 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05302034 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
2035 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002036 {
2037 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05302038 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002039 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
2040 }
Chilam Ng1279e232013-01-25 15:06:52 -08002041 } else {
c_hpothu32490782014-03-14 19:14:34 +05302042 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002043 "rx packet sa is bssid, not adding to peer list");
2044 }
2045 }
2046#endif
2047
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002048 if (pHddCtx->cfg_ini->gEnableDebugLog)
2049 {
2050 proto_type = vos_pkt_get_proto_type(skb,
2051 pHddCtx->cfg_ini->gEnableDebugLog);
2052 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2053 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002055 "STA RX EAPOL");
2056 }
2057 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2058 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302059 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002060 "STA RX DHCP");
2061 }
2062 }
2063
Mukul Sharma84f27252014-07-14 18:11:42 +05302064#ifdef DEBUG_ROAM_DELAY
2065 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2066 //Should we check below global to avoid function call each time ??
2067 /*
2068 if(gRoamDelayMetaInfo.hdd_monitor_rx)
2069 {
2070 }
2071 */
2072#endif
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302073 if (( NULL != pHddCtx ) &&
2074 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05302075 {
2076 hdd_dump_dhcp_pkt(skb, RX_PATH);
2077 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302078
Jeff Johnson295189b2012-06-20 16:38:30 -07002079 skb->dev = pAdapter->dev;
2080 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002081 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002082 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2083 ++pAdapter->stats.rx_packets;
2084 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002085#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002086#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002087 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002088#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002089#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002090 rxstat = netif_rx_ni(skb);
2091 if (NET_RX_SUCCESS == rxstat)
2092 {
2093 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002094 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002095 }
2096 else
2097 {
2098 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2099 }
2100 // now process the next packet in the chain
2101 pVosPacket = pNextVosPacket;
2102
2103 } while (pVosPacket);
2104
2105 //Return the entire VOS packet chain to the resource pool
2106 status = vos_pkt_return_packet( pVosPacketChain );
2107 if(!VOS_IS_STATUS_SUCCESS( status ))
2108 {
c_hpothu32490782014-03-14 19:14:34 +05302109 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 }
2111
2112 pAdapter->dev->last_rx = jiffies;
2113
2114 return status;
2115}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002116/**============================================================================
2117 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2118 Enable/Disable split scan based on TX and RX traffic.
2119 @param HddContext : [in] pointer to Hdd context
2120 @return : None
2121 ===========================================================================*/
2122void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2123{
2124 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2125 hdd_adapter_t *pAdapter = NULL;
2126 hdd_station_ctx_t *pHddStaCtx = NULL;
2127 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2128 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2129 VOS_STATUS status;
2130 v_U8_t staId = 0;
2131 v_U8_t fconnected = 0;
2132
c_hpothub8245442013-11-20 23:41:09 +05302133 if (NULL == phddctx)
2134 {
c_hpothu32490782014-03-14 19:14:34 +05302135 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05302136 FL("phddctx is NULL"));
2137 VOS_ASSERT(0);
2138 return;
2139 }
2140
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002141 if (!cfg_param->dynSplitscan)
2142 {
c_hpothu32490782014-03-14 19:14:34 +05302143 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002144 "%s: Error : Dynamic split scan is not Enabled : %d",
2145 __func__, pHddCtx->cfg_ini->dynSplitscan);
2146 return;
2147 }
2148
2149 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2150 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2151 {
2152 pAdapter = pAdapterNode->pAdapter;
2153
2154 if ( pAdapter )
2155 {
c_hpothu32490782014-03-14 19:14:34 +05302156 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002157 "%s: Adapter with device mode %d exists",
2158 __func__, pAdapter->device_mode);
2159
2160 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2161 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2162 {
2163 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2164 if ((eConnectionState_Associated ==
2165 pHddStaCtx->conn_info.connState) &&
2166 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2167 {
2168 fconnected = TRUE;
2169 }
2170 }
2171 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2172 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2173 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302174 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2175 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2176 if(pSapCtx == NULL){
2177 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2178 FL("psapCtx is NULL"));
2179 return;
2180 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002181 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2182 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302183 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002184 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302185 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002186 {
2187 fconnected = TRUE;
2188 }
2189 }
2190 }
2191 if ( fconnected )
2192 {
c_hpothu32490782014-03-14 19:14:34 +05302193 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002194 "%s: One of the interface is connected check for scan",
2195 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302196 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302197 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
2198 "miracast = %d", __func__,
2199 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
2200 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
2201 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002202
2203 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
2204 cfg_param->trafficMntrTmrForSplitScan);
2205 //Check for the previous statistics count
2206 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
2207 cfg_param->txRxThresholdForSplitScan) ||
2208 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
2209 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05302210 pHddCtx->drvr_miracast ||
2211 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002212 {
2213 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2214 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2215
2216 if (!pHddCtx->issplitscan_enabled)
2217 {
2218 pHddCtx->issplitscan_enabled = TRUE;
2219 sme_enable_disable_split_scan(
2220 WLAN_HDD_GET_HAL_CTX(pAdapter),
2221 cfg_param->nNumStaChanCombinedConc,
2222 cfg_param->nNumP2PChanCombinedConc);
2223 }
2224 return;
2225 }
2226 else
2227 {
2228 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2229 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2230 }
2231 fconnected = FALSE;
2232 }
2233 }
2234 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
2235 pAdapterNode = pNext;
2236 }
2237
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05302238 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
2239 * of disabling the split scan and thus do not disable the same when the
2240 * low TXRX condition is met.
2241 */
2242 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002243 {
c_hpothu32490782014-03-14 19:14:34 +05302244 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002245 "%s: Disable split scan", __func__);
2246 pHddCtx->issplitscan_enabled = FALSE;
2247 sme_enable_disable_split_scan(
2248 pHddCtx->hHal,
2249 SME_DISABLE_SPLIT_SCAN,
2250 SME_DISABLE_SPLIT_SCAN);
2251 }
2252 return;
2253}
Jeff Johnson295189b2012-06-20 16:38:30 -07002254