blob: 5b056ba1c51da1bdf7db375094da2acba96a7dc6 [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
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301709 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001710#endif /* FEATURE_WLAN_WAPI */
1711
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301712 /* 1. Check if ACM is set for this AC
1713 * 2. If set, check if this AC had already admitted
1714 * 3. If not already admitted, downgrade the UP to next best UP
1715 * 4. Allow only when medium time is non zero when Addts accepted
1716 * else downgrade traffic. we opted downgrading over Delts when
1717 * medium time is zero because while doing downgradig driver is not
1718 * clearing the wmm context so consider in subsequent roaming
1719 * if AP (new or same AP) accept the Addts with valid medium time
1720 * no application support is required where if we have opted
1721 * delts Applications have to again do Addts or STA will never
1722 * go for Addts.
1723 */
1724
1725 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
1726 (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid &&
1727 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07001728 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301729 pPktMetaInfo->ucUP = pktNode->userPriority;
1730 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 }
1732 else
1733 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301734 //Downgrade the UP
1735 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1736 newAc = WLANTL_AC_BK;
1737 for (i=ac-1; i>0; i--)
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301739 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1740 {
1741 newAc = i;
1742 break;
1743 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001744 }
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301745 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1746 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1747 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
1748 "Downgrading UP %d to UP %d ",
1749 pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07001750 }
1751
Mukul Sharma84f27252014-07-14 18:11:42 +05301752#ifdef DEBUG_ROAM_DELAY
1753 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
1754#endif
1755
Jeff Johnson295189b2012-06-20 16:38:30 -07001756 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1757 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1758 if ( 1 < size )
1759 {
1760 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1761 }
1762 else
1763 {
1764 pPktMetaInfo->bMorePackets = 0;
1765 }
1766
1767 //Extract the destination address from ethernet frame
1768 pDestMacAddress = (v_MACADDR_t*)skb->data;
1769 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1770 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1771
1772
1773
1774 // if we are in a backpressure situation see if we can turn the hose back on
1775 if ( (pAdapter->isTxSuspended[ac]) &&
1776 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1777 {
1778 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1779 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05301780 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001781 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001782 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1783 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1784 skb_get_queue_mapping(skb) ));
Mihir Shete5d148f12014-12-16 17:54:49 +05301785 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_WAKE_NETDEV,
1786 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001787 }
1788
1789
1790 // We're giving the packet to TL so consider it transmitted from
1791 // a statistics perspective. We account for it here instead of
1792 // when the packet is returned for two reasons. First, TL will
1793 // manipulate the skb to the point where the len field is not
1794 // accurate, leading to inaccurate byte counts if we account for
1795 // it later. Second, TL does not provide any feedback as to
1796 // whether or not the packet was successfully sent over the air,
1797 // so the packet counts will be the same regardless of where we
1798 // account for them
1799 pAdapter->stats.tx_bytes += skb->len;
1800 ++pAdapter->stats.tx_packets;
1801 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1802 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301803 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001804
Leo Chang50bbd252013-04-25 14:58:01 -07001805 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1806 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001807 {
1808 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1809 {
c_hpothu32490782014-03-14 19:14:34 +05301810 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001811 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001812 return VOS_STATUS_E_FAILURE;
1813 }
1814 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1815 {
1816 if(0 == pHddCtx->tmInfo.txFrameCount)
1817 {
1818 /* Just recovered from sleep timeout */
1819 pHddCtx->tmInfo.lastOpenTs = timestamp;
1820 }
1821
Leo Chang50bbd252013-04-25 14:58:01 -07001822 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1823 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001824 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1825 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001826 /* During TX open duration, TX frame count is larger than threshold
1827 * Block TX during Sleep time */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05301828 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001829 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001830 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001831 pHddCtx->tmInfo.lastblockTs = timestamp;
1832 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1833 {
1834 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1835 }
1836 }
1837 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1838 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1839 {
1840 /* During TX open duration, TX frame count is less than threshold
1841 * Reset count and timestamp to prepare next cycle */
1842 pHddCtx->tmInfo.lastOpenTs = timestamp;
1843 pHddCtx->tmInfo.txFrameCount = 0;
1844 }
1845 else
1846 {
1847 /* Do Nothing */
1848 }
1849 pHddCtx->tmInfo.txFrameCount++;
1850 }
1851 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1852 }
1853
1854
1855#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301856 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 -07001857#endif // HDD_WMM_DEBUG
1858
1859 return status;
1860}
1861
1862
1863/**============================================================================
1864 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1865 case where VOS packets are not available at the time of the call to get
1866 packets. This callback function is invoked by VOS when packets are
1867 available.
1868
1869 @param pVosPacket : [in] pointer to VOS packet
1870 @param userData : [in] opaque user data that was passed initially
1871
1872 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1873 : VOS_STATUS_SUCCESS otherwise
1874 =============================================================================*/
1875VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1876 v_VOID_t *userData )
1877{
1878 VOS_STATUS status;
1879 v_SINT_t i = 0;
1880 v_SIZE_t size = 0;
1881 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1882
Agarwal Ashish971c2882013-10-30 20:11:12 +05301883 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001884 {
c_hpothu32490782014-03-14 19:14:34 +05301885 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301886 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001887 return VOS_STATUS_E_FAILURE;
1888 }
1889
1890 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1891 //situation. Here we will only signal TL that there is a pending data for a STA.
1892 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1893 vos_pkt_return_packet( pVosPacket );
1894
1895 pAdapter->isVosOutOfResource = VOS_FALSE;
1896
1897 //Indicate to TL that there is pending data if a queue is non empty
1898 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1899 {
1900 size = 0;
1901 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1902 if ( size > 0 )
1903 {
1904 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1905 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1906 (WLANTL_ACEnumType)i );
1907 if( !VOS_IS_STATUS_SUCCESS( status ) )
1908 {
c_hpothu32490782014-03-14 19:14:34 +05301909 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301910 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001911 }
1912 }
1913 }
1914
1915 return VOS_STATUS_SUCCESS;
1916}
1917
1918
1919/**============================================================================
1920 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1921 TL will call this to notify the HDD when one or more packets were
1922 received for a registered STA.
1923
1924 @param vosContext : [in] pointer to VOS context
1925 @param pVosPacketChain : [in] pointer to VOS packet chain
1926 @param staId : [in] Station Id
1927 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1928
1929 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1930 : VOS_STATUS_SUCCESS otherwise
1931 ===========================================================================*/
1932VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1933 vos_pkt_t *pVosPacketChain,
1934 v_U8_t staId,
1935 WLANTL_RxMetaInfoType* pRxMetaInfo )
1936{
1937 hdd_adapter_t *pAdapter = NULL;
1938 hdd_context_t *pHddCtx = NULL;
1939 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1940 int rxstat;
1941 struct sk_buff *skb = NULL;
1942 vos_pkt_t* pVosPacket;
1943 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001944 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001945
1946 //Sanity check on inputs
1947 if ( ( NULL == vosContext ) ||
1948 ( NULL == pVosPacketChain ) ||
1949 ( NULL == pRxMetaInfo ) )
1950 {
c_hpothu32490782014-03-14 19:14:34 +05301951 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301952 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001953 return VOS_STATUS_E_FAILURE;
1954 }
1955
Kiet Lam3c2ee302014-03-23 23:23:22 -07001956 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001957 if ( NULL == pHddCtx )
1958 {
c_hpothu32490782014-03-14 19:14:34 +05301959 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301960 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 return VOS_STATUS_E_FAILURE;
1962 }
1963
1964 pAdapter = pHddCtx->sta_to_adapter[staId];
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301965 if( (NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001966 {
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301967 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1968 "%s: pAdapter is Null or adapter has invalid magic for staId %u",
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05301969 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001970 return VOS_STATUS_E_FAILURE;
1971 }
1972
1973 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1974
1975 // walk the chain until all are processed
1976 pVosPacket = pVosPacketChain;
1977 do
1978 {
1979 // get the pointer to the next packet in the chain
1980 // (but don't unlink the packet since we free the entire chain later)
1981 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1982
1983 // both "success" and "empty" are acceptable results
1984 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1985 {
1986 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301987 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301988 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001989 return VOS_STATUS_E_FAILURE;
1990 }
1991
1992 // Extract the OS packet (skb).
1993 // Tell VOS to detach the OS packet from the VOS packet
1994 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1995 if(!VOS_IS_STATUS_SUCCESS( status ))
1996 {
1997 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301998 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301999 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002000 return VOS_STATUS_E_FAILURE;
2001 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002002
2003 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2004 {
c_hpothu32490782014-03-14 19:14:34 +05302005 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07002006 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
2007 return eHAL_STATUS_FAILURE;
2008 }
2009
Chilam Ng1279e232013-01-25 15:06:52 -08002010#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002011 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
2012 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08002013 {
2014 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08002015 u8 mac[6];
2016
Hoonki Lee387663d2013-02-05 18:08:43 -08002017 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08002018
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002019 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302020 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002021 "rx broadcast packet, not adding to peer list");
2022 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2023 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002024 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05302025 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002026 "rx extract mac:" MAC_ADDRESS_STR,
2027 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302028 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05302029 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
2030 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002031 {
2032 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05302033 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002034 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
2035 }
Chilam Ng1279e232013-01-25 15:06:52 -08002036 } else {
c_hpothu32490782014-03-14 19:14:34 +05302037 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002038 "rx packet sa is bssid, not adding to peer list");
2039 }
2040 }
2041#endif
2042
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002043 if (pHddCtx->cfg_ini->gEnableDebugLog)
2044 {
2045 proto_type = vos_pkt_get_proto_type(skb,
2046 pHddCtx->cfg_ini->gEnableDebugLog);
2047 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2048 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302049 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002050 "STA RX EAPOL");
2051 }
2052 else if (VOS_PKT_PROTO_TYPE_DHCP & 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 DHCP");
2056 }
2057 }
2058
Mukul Sharma84f27252014-07-14 18:11:42 +05302059#ifdef DEBUG_ROAM_DELAY
2060 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2061 //Should we check below global to avoid function call each time ??
2062 /*
2063 if(gRoamDelayMetaInfo.hdd_monitor_rx)
2064 {
2065 }
2066 */
2067#endif
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302068 if (( NULL != pHddCtx ) &&
2069 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05302070 {
2071 hdd_dump_dhcp_pkt(skb, RX_PATH);
2072 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302073
Jeff Johnson295189b2012-06-20 16:38:30 -07002074 skb->dev = pAdapter->dev;
2075 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002076 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002077 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2078 ++pAdapter->stats.rx_packets;
2079 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002080#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002081#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002082 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002083#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002084#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002085 rxstat = netif_rx_ni(skb);
2086 if (NET_RX_SUCCESS == rxstat)
2087 {
2088 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002089 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002090 }
2091 else
2092 {
2093 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2094 }
2095 // now process the next packet in the chain
2096 pVosPacket = pNextVosPacket;
2097
2098 } while (pVosPacket);
2099
2100 //Return the entire VOS packet chain to the resource pool
2101 status = vos_pkt_return_packet( pVosPacketChain );
2102 if(!VOS_IS_STATUS_SUCCESS( status ))
2103 {
c_hpothu32490782014-03-14 19:14:34 +05302104 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002105 }
2106
2107 pAdapter->dev->last_rx = jiffies;
2108
2109 return status;
2110}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002111/**============================================================================
2112 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2113 Enable/Disable split scan based on TX and RX traffic.
2114 @param HddContext : [in] pointer to Hdd context
2115 @return : None
2116 ===========================================================================*/
2117void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2118{
2119 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2120 hdd_adapter_t *pAdapter = NULL;
2121 hdd_station_ctx_t *pHddStaCtx = NULL;
2122 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2123 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2124 VOS_STATUS status;
2125 v_U8_t staId = 0;
2126 v_U8_t fconnected = 0;
2127
c_hpothub8245442013-11-20 23:41:09 +05302128 if (NULL == phddctx)
2129 {
c_hpothu32490782014-03-14 19:14:34 +05302130 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05302131 FL("phddctx is NULL"));
2132 VOS_ASSERT(0);
2133 return;
2134 }
2135
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002136 if (!cfg_param->dynSplitscan)
2137 {
c_hpothu32490782014-03-14 19:14:34 +05302138 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002139 "%s: Error : Dynamic split scan is not Enabled : %d",
2140 __func__, pHddCtx->cfg_ini->dynSplitscan);
2141 return;
2142 }
2143
2144 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2145 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2146 {
2147 pAdapter = pAdapterNode->pAdapter;
2148
2149 if ( pAdapter )
2150 {
c_hpothu32490782014-03-14 19:14:34 +05302151 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002152 "%s: Adapter with device mode %d exists",
2153 __func__, pAdapter->device_mode);
2154
2155 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2156 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2157 {
2158 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2159 if ((eConnectionState_Associated ==
2160 pHddStaCtx->conn_info.connState) &&
2161 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2162 {
2163 fconnected = TRUE;
2164 }
2165 }
2166 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2167 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2168 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302169 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2170 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2171 if(pSapCtx == NULL){
2172 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2173 FL("psapCtx is NULL"));
2174 return;
2175 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002176 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2177 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302178 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002179 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302180 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002181 {
2182 fconnected = TRUE;
2183 }
2184 }
2185 }
2186 if ( fconnected )
2187 {
c_hpothu32490782014-03-14 19:14:34 +05302188 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002189 "%s: One of the interface is connected check for scan",
2190 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302191 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302192 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
2193 "miracast = %d", __func__,
2194 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
2195 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
2196 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002197
2198 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
2199 cfg_param->trafficMntrTmrForSplitScan);
2200 //Check for the previous statistics count
2201 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
2202 cfg_param->txRxThresholdForSplitScan) ||
2203 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
2204 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05302205 pHddCtx->drvr_miracast ||
2206 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002207 {
2208 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2209 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2210
2211 if (!pHddCtx->issplitscan_enabled)
2212 {
2213 pHddCtx->issplitscan_enabled = TRUE;
2214 sme_enable_disable_split_scan(
2215 WLAN_HDD_GET_HAL_CTX(pAdapter),
2216 cfg_param->nNumStaChanCombinedConc,
2217 cfg_param->nNumP2PChanCombinedConc);
2218 }
2219 return;
2220 }
2221 else
2222 {
2223 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2224 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2225 }
2226 fconnected = FALSE;
2227 }
2228 }
2229 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
2230 pAdapterNode = pNext;
2231 }
2232
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05302233 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
2234 * of disabling the split scan and thus do not disable the same when the
2235 * low TXRX condition is met.
2236 */
2237 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002238 {
c_hpothu32490782014-03-14 19:14:34 +05302239 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002240 "%s: Disable split scan", __func__);
2241 pHddCtx->issplitscan_enabled = FALSE;
2242 sme_enable_disable_split_scan(
2243 pHddCtx->hHal,
2244 SME_DISABLE_SPLIT_SCAN,
2245 SME_DISABLE_SPLIT_SCAN);
2246 }
2247 return;
2248}
Jeff Johnson295189b2012-06-20 16:38:30 -07002249