blob: 370fd71412a7da101a0bd4885867cc58cebb9864 [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
Jeff Johnson295189b2012-06-20 16:38:30 -070033
34 ==========================================================================*/
35
36/*---------------------------------------------------------------------------
37 Include files
38 -------------------------------------------------------------------------*/
39#include <wlan_hdd_tx_rx.h>
40#include <wlan_hdd_softap_tx_rx.h>
41#include <wlan_hdd_dp_utils.h>
42#include <wlan_qct_tl.h>
43#include <linux/netdevice.h>
44#include <linux/skbuff.h>
45#include <linux/etherdevice.h>
Mihir Shetec8fe71b2014-06-16 15:32:59 +053046#include <linux/ratelimit.h>
Mihir Shetef3473692014-06-27 15:13:20 +053047#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
48#include <soc/qcom/subsystem_restart.h>
49#else
50#include <mach/subsystem_restart.h>
51#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070052
Jeff Johnson295189b2012-06-20 16:38:30 -070053#include <wlan_hdd_p2p.h>
54#include <linux/wireless.h>
55#include <net/cfg80211.h>
56#include <net/ieee80211_radiotap.h>
57#include "sapApi.h"
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053058#include <vos_sched.h>
Chilam NG571c65a2013-01-19 12:27:36 +053059#ifdef FEATURE_WLAN_TDLS
60#include "wlan_hdd_tdls.h"
61#endif
62
Mukul Sharma84f27252014-07-14 18:11:42 +053063#ifdef DEBUG_ROAM_DELAY
64#include "vos_utils.h"
65#endif
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053066#include "sapInternal.h"
Mihir Shete5d148f12014-12-16 17:54:49 +053067#include "wlan_hdd_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070068/*---------------------------------------------------------------------------
69 Preprocessor definitions and constants
70 -------------------------------------------------------------------------*/
71
72const v_U8_t hddWmmAcToHighestUp[] = {
73 SME_QOS_WMM_UP_RESV,
74 SME_QOS_WMM_UP_EE,
75 SME_QOS_WMM_UP_VI,
76 SME_QOS_WMM_UP_NC
77};
78
79//Mapping Linux AC interpretation to TL AC.
80const v_U8_t hdd_QdiscAcToTlAC[] = {
81 WLANTL_AC_VO,
82 WLANTL_AC_VI,
83 WLANTL_AC_BE,
84 WLANTL_AC_BK,
85};
86
Mihir Shetec8fe71b2014-06-16 15:32:59 +053087#define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
88#define HDD_TX_TIMEOUT_RATELIMIT_BURST 1
Mihir Shetef3473692014-06-27 15:13:20 +053089#define HDD_TX_STALL_SSR_THRESHOLD 5
Mihir Shete327c2ab2014-11-13 15:17:02 +053090#define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
Mihir Shetec8fe71b2014-06-16 15:32:59 +053091
92static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs, \
93 HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
94 HDD_TX_TIMEOUT_RATELIMIT_BURST);
95
Jeff Johnson295189b2012-06-20 16:38:30 -070096static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070097
98/*---------------------------------------------------------------------------
99 Type declarations
100 -------------------------------------------------------------------------*/
101
102/*---------------------------------------------------------------------------
103 Function definitions and documenation
104 -------------------------------------------------------------------------*/
105
106#ifdef DATA_PATH_UNIT_TEST
107//Utility function to dump an sk_buff
108static void dump_sk_buff(struct sk_buff * skb)
109{
c_hpothu32490782014-03-14 19:14:34 +0530110 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
111 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
112 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
113 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
114 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
115 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
116 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 -0700117
c_hpothu32490782014-03-14 19:14:34 +0530118 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 -0700119 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
120 skb->data[5], skb->data[6], skb->data[7]);
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[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
123 skb->data[13], skb->data[14], skb->data[15]);
124}
125
126//Function for Unit Test only
127static void transport_thread(hdd_adapter_t *pAdapter)
128{
129 v_U8_t staId;
130 WLANTL_ACEnumType ac = WLANTL_AC_BE;
131 vos_pkt_t *pVosPacket = NULL ;
132 vos_pkt_t dummyPacket;
133 WLANTL_MetaInfoType pktMetaInfo;
134 WLANTL_RxMetaInfoType pktRxMetaInfo;
135 VOS_STATUS status = VOS_STATUS_E_FAILURE;
136
c_hpothub8245442013-11-20 23:41:09 +0530137 if (NULL == pAdapter)
138 {
c_hpothu32490782014-03-14 19:14:34 +0530139 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530140 FL("pAdapter is NULL"));
141 VOS_ASSERT(0);
142 return;
143 }
144
Jeff Johnson295189b2012-06-20 16:38:30 -0700145 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
146 &staId,
147 &ac,
148 &pVosPacket,
149 &pktMetaInfo );
150 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530151 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
152 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700153 else
c_hpothu32490782014-03-14 19:14:34 +0530154 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
155 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700156
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700157 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700158 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530159 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
160 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700161 else
c_hpothu32490782014-03-14 19:14:34 +0530162 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
163 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
165 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
166 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530167 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
168 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700169 else
c_hpothu32490782014-03-14 19:14:34 +0530170 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
171 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700172
173 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
174 &dummyPacket,
175 staId,
176 &pktRxMetaInfo);
177 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530178 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
179 "%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700180 else
c_hpothu32490782014-03-14 19:14:34 +0530181 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
182 "%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700183
184}
185#endif
186
187
188/**============================================================================
189 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
190
191 @param pAdapter : [in] pointer to adapter context
192 @return : VOS_STATUS_E_FAILURE if any errors encountered
193 : VOS_STATUS_SUCCESS otherwise
194 ===========================================================================*/
195static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
196{
197 VOS_STATUS status = VOS_STATUS_SUCCESS;
198 v_SINT_t i = -1;
199 hdd_list_node_t *anchor = NULL;
200 skb_list_node_t *pktNode = NULL;
201 struct sk_buff *skb = NULL;
202
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530203 pAdapter->isVosLowResource = VOS_FALSE;
204
Mihir Shete5d148f12014-12-16 17:54:49 +0530205 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_FLUSH_TX_QUEUES,
206 pAdapter->sessionId, 0));
207
Jeff Johnson295189b2012-06-20 16:38:30 -0700208 while (++i != NUM_TX_QUEUES)
209 {
210 //Free up any packets in the Tx queue
211 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
212 while (true)
213 {
214 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
215 if(VOS_STATUS_E_EMPTY != status)
216 {
217 pktNode = list_entry(anchor, skb_list_node_t, anchor);
218 skb = pktNode->skb;
219 //TODO
220 //++pAdapter->stats.tx_dropped;
221 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
222 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
223 kfree_skb(skb);
224 continue;
225 }
226 break;
227 }
228 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
229 // backpressure is no longer in effect
230 pAdapter->isTxSuspended[i] = VOS_FALSE;
231 }
232
233 return status;
234}
235
Ravi Joshif9520d62013-10-18 04:11:46 -0700236/**============================================================================
237 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
238 in IBSS mode
239
240 @param pAdapter : [in] pointer to adapter context
241 : [in] Staion Id
242 @return : VOS_STATUS_E_FAILURE if any errors encountered
243 : VOS_STATUS_SUCCESS otherwise
244 ===========================================================================*/
245void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
246{
247 v_U8_t i;
Ravi Joshi41914632013-10-21 23:02:21 -0700248 v_SIZE_t size = 0;
Ravi Joshif9520d62013-10-18 04:11:46 -0700249 v_U8_t skbStaIdx;
Ravi Joshi41914632013-10-21 23:02:21 -0700250 skb_list_node_t *pktNode = NULL;
251 hdd_list_node_t *tmp = NULL, *next = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700252 struct netdev_queue *txq;
Ravi Joshi41914632013-10-21 23:02:21 -0700253 struct sk_buff *skb = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700254
c_hpothub8245442013-11-20 23:41:09 +0530255 if (NULL == pAdapter)
256 {
c_hpothu32490782014-03-14 19:14:34 +0530257 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530258 FL("pAdapter is NULL %u"), STAId);
259 VOS_ASSERT(0);
260 return;
261 }
262
Ravi Joshif9520d62013-10-18 04:11:46 -0700263 for (i = 0; i < NUM_TX_QUEUES; i++)
264 {
265 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
266
267 if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) )
268 {
269 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
270 continue;
271 }
272
273 /* Iterate through the queue and identify the data for STAId */
Ravi Joshi41914632013-10-21 23:02:21 -0700274 list_for_each_safe(tmp, next, &pAdapter->wmm_tx_queue[i].anchor)
Ravi Joshif9520d62013-10-18 04:11:46 -0700275 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700276 pktNode = list_entry(tmp, skb_list_node_t, anchor);
277 if (pktNode != NULL)
278 {
279 skb = pktNode->skb;
280
281 /* Get the STAId from data */
282 skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
283 if (skbStaIdx == STAId)
284 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700285 /* Data for STAId is freed along with the queue node */
Ravi Joshif9520d62013-10-18 04:11:46 -0700286 list_del(tmp);
Mihir Shete31e1e392014-03-24 17:09:09 +0530287 kfree_skb(skb);
Ravi Joshif9520d62013-10-18 04:11:46 -0700288
289 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
290 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
291 pAdapter->wmm_tx_queue[i].count--;
292 }
293 }
294 }
295
296 /* Restart the queue only-if suspend and the queue was flushed */
Ravi Joshi41914632013-10-21 23:02:21 -0700297 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
Ravi Joshif9520d62013-10-18 04:11:46 -0700298 txq = netdev_get_tx_queue(pAdapter->dev, i);
Ravi Joshi41914632013-10-21 23:02:21 -0700299
300 if (VOS_TRUE == pAdapter->isTxSuspended[i] &&
301 size <= HDD_TX_QUEUE_LOW_WATER_MARK &&
302 netif_tx_queue_stopped(txq) )
Ravi Joshif9520d62013-10-18 04:11:46 -0700303 {
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530304 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queue for queue %d"),i);
Ravi Joshif9520d62013-10-18 04:11:46 -0700305 netif_tx_start_queue(txq);
Ravi Joshi41914632013-10-21 23:02:21 -0700306 pAdapter->isTxSuspended[i] = VOS_FALSE;
307 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressured;
308 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressuredAC[i];
Ravi Joshif9520d62013-10-18 04:11:46 -0700309 }
310
311 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
312 }
313}
314
Jeff Johnson295189b2012-06-20 16:38:30 -0700315static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
316{
317 skb_list_node_t *pktNode = NULL;
318 struct sk_buff *skb = NULL;
319 v_SIZE_t size = 0;
320 WLANTL_ACEnumType ac = 0;
321 VOS_STATUS status = VOS_STATUS_E_FAILURE;
322 hdd_list_node_t *anchor = NULL;
323
c_hpothu77731d42014-01-23 13:59:03 +0530324 if (NULL == pAdapter)
325 {
326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
327 FL("pAdapter is NULL"));
328 VOS_ASSERT(0);
329 return NULL;
330 }
331
Jeff Johnson295189b2012-06-20 16:38:30 -0700332 // do we have any packets pending in this AC?
333 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
334 if( size == 0 )
335 {
c_hpothu32490782014-03-14 19:14:34 +0530336 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700337 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 return NULL;
339 }
340
341 //Remove the packet from the queue
342 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
343 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
344 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
345
346 if(VOS_STATUS_SUCCESS == status)
347 {
348 //If success then we got a valid packet from some AC
349 pktNode = list_entry(anchor, skb_list_node_t, anchor);
350 skb = pktNode->skb;
351 }
352 else
353 {
c_hpothu32490782014-03-14 19:14:34 +0530354 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700355 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700356 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700357
358 return NULL;
359 }
360
361 // if we are in a backpressure situation see if we can turn the hose back on
362 if ( (pAdapter->isTxSuspended[ac]) &&
363 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
364 {
c_hpothu32490782014-03-14 19:14:34 +0530365 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700366 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700367 pAdapter->isTxSuspended[ac] = VOS_FALSE;
368 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530369 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700370 netif_tx_start_all_queues( pAdapter->dev );
371 }
372
373 return skb;
374}
375
376void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
377{
378 hdd_cfg80211_state_t *cfgState;
379 struct sk_buff* skb;
380 hdd_adapter_t* pMonAdapter = NULL;
381 struct ieee80211_hdr *hdr;
382
Mukul Sharma23a92232014-04-07 18:04:00 +0530383 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700384 {
c_hpothu32490782014-03-14 19:14:34 +0530385 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530386 FL("pAdapter is NULL"));
387 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700388 return;
389 }
390
391 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530392 if (pMonAdapter == NULL)
393 {
394 hddLog(VOS_TRACE_LEVEL_ERROR,
395 "%s: pMonAdapter is NULL", __func__);
396 return;
397 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700398 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
399
400 if( NULL != cfgState->buf )
401 {
c_hpothu32490782014-03-14 19:14:34 +0530402 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700403 "%s: Already one MGMT packet Tx going on", __func__);
404 return;
405 }
406
407 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
408
409 if (NULL == skb)
410 {
c_hpothu32490782014-03-14 19:14:34 +0530411 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700412 "%s: No Packet Pending", __func__);
413 return;
414 }
415
416 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
417 if( cfgState->buf == NULL )
418 {
c_hpothu32490782014-03-14 19:14:34 +0530419 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700420 "%s: Failed to Allocate memory", __func__);
421 goto fail;
422 }
423
424 cfgState->len = skb->len;
425
426 vos_mem_copy( cfgState->buf, skb->data, skb->len);
427
428 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800429 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700430
431 hdr = (struct ieee80211_hdr *)skb->data;
432 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
433 == HDD_FRAME_TYPE_MGMT )
434 {
435 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
436 == HDD_FRAME_SUBTYPE_DEAUTH )
437 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530438 struct tagCsrDelStaParams delStaParams;
439
Sushant Kaushik4cd28f62014-12-26 14:23:50 +0530440 WLANSAP_PopulateDelStaParams(hdr->addr1,
441 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530442 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
443
444 hdd_softap_sta_deauth(pAdapter, &delStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -0700445 goto mgmt_handled;
446 }
447 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
448 == HDD_FRAME_SUBTYPE_DISASSOC )
449 {
450 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
451 goto mgmt_handled;
452 }
453 }
c_hpothu32490782014-03-14 19:14:34 +0530454 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
456
Jeff Johnson43971f52012-07-17 12:26:56 -0700457 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700458 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700459 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700460 {
c_hpothu32490782014-03-14 19:14:34 +0530461 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700462 "%s: WLANSAP_SendAction returned fail", __func__);
463 hdd_sendActionCnf( pAdapter, FALSE );
464 }
465 return;
466
467mgmt_handled:
468 hdd_sendActionCnf( pAdapter, TRUE );
469 return;
470fail:
471 kfree_skb(pAdapter->skb_to_tx);
472 pAdapter->skb_to_tx = NULL;
473 return;
474}
475
476void hdd_mon_tx_work_queue(struct work_struct *work)
477{
478 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
479 hdd_mon_tx_mgmt_pkt(pAdapter);
480}
481
482int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
483{
484 v_U16_t rt_hdr_len;
485 struct ieee80211_hdr *hdr;
486 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
487 struct ieee80211_radiotap_header *rtap_hdr =
488 (struct ieee80211_radiotap_header *)skb->data;
489
490 /*Supplicant sends the EAPOL packet on monitor interface*/
491 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
492 if(pPgBkAdapter == NULL)
493 {
c_hpothu32490782014-03-14 19:14:34 +0530494 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700495 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
496 __func__);
497 goto fail; /* too short to be possibly valid */
498 }
499
500 /* check if toal skb length is greater then radio tab header length of not */
501 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
502 goto fail; /* too short to be possibly valid */
503
504 /* check if radio tap header version is correct or not */
505 if (unlikely(rtap_hdr->it_version))
506 goto fail; /* only version 0 is supported */
507
508 /*Strip off the radio tap header*/
509 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
510
511 /* check if skb length if greator then total radio tap header length ot not*/
512 if (unlikely(skb->len < rt_hdr_len))
513 goto fail;
514
515 /* Update the trans_start for this netdev */
516 dev->trans_start = jiffies;
517 /*
518 * fix up the pointers accounting for the radiotap
519 * header still being in there.
520 */
521 skb_set_mac_header(skb, rt_hdr_len);
522 skb_set_network_header(skb, rt_hdr_len);
523 skb_set_transport_header(skb, rt_hdr_len);
524
525 /* Pull rtap header out of the skb */
526 skb_pull(skb, rt_hdr_len);
527
528 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
529 * radio tap header and 802.11 header starts
530 */
531 hdr = (struct ieee80211_hdr *)skb->data;
532
533 /* Send data frames through the normal Data path. In this path we will
534 * conver rcvd 802.11 packet to 802.3 packet */
535 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
536 {
537 v_U8_t da[6];
538 v_U8_t sa[6];
539
540 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
541 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
542
543 /* Pull 802.11 MAC header */
544 skb_pull(skb, HDD_80211_HEADER_LEN);
545
546 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
547 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
548 {
549 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
550 }
551
552 /* Pull LLC header */
553 skb_pull(skb, HDD_LLC_HDR_LEN);
554
555 /* Create space for Ethernet header */
556 skb_push(skb, HDD_MAC_HDR_SIZE*2);
557 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
558 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
559
560 /* Only EAPOL Data packets are allowed through monitor interface */
561 if (vos_be16_to_cpu(
562 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
563 != HDD_ETHERTYPE_802_1_X)
564 {
c_hpothu32490782014-03-14 19:14:34 +0530565 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700566 "%s: Not a Eapol packet. Drop this frame", __func__);
567 //If not EAPOL frames, drop them.
568 kfree_skb(skb);
569 return NETDEV_TX_OK;
570 }
571
572 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
573
574 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
575 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
576 }
577 else
578 {
579 VOS_STATUS status;
580 WLANTL_ACEnumType ac = 0;
581 skb_list_node_t *pktNode = NULL;
582 v_SIZE_t pktListSize = 0;
583
584 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
585 //If we have already reached the max queue size, disable the TX queue
586 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
587 {
588 /* We want to process one packet at a time, so lets disable all TX queues
589 * and re-enable the queues once we get TX feedback for this packet */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530590 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700591 netif_tx_stop_all_queues(pAdapter->dev);
592 pAdapter->isTxSuspended[ac] = VOS_TRUE;
593 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
594 return NETDEV_TX_BUSY;
595 }
596 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
597
598 //Use the skb->cb field to hold the list node information
599 pktNode = (skb_list_node_t *)&skb->cb;
600
601 //Stick the OS packet inside this node.
602 pktNode->skb = skb;
603
604 INIT_LIST_HEAD(&pktNode->anchor);
605
606 //Insert the OS packet into the appropriate AC queue
607 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
608 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
609 &pktNode->anchor, &pktListSize );
610 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
611
612 if ( !VOS_IS_STATUS_SUCCESS( status ) )
613 {
c_hpothu32490782014-03-14 19:14:34 +0530614 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700615 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 kfree_skb(skb);
617 return NETDEV_TX_OK;
618 }
619
620 if ( pktListSize == 1 )
621 {
622 /* In this context we cannot acquire any mutex etc. And to transmit
623 * this packet we need to call SME API. So to take care of this we will
624 * schedule a workqueue
625 */
626 schedule_work(&pPgBkAdapter->monTxWorkQueue);
627 }
628 return NETDEV_TX_OK;
629 }
630
631fail:
c_hpothu32490782014-03-14 19:14:34 +0530632 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700633 "%s: Packet Rcvd at Monitor interface is not proper,"
634 " Dropping the packet",
635 __func__);
636 kfree_skb(skb);
637 return NETDEV_TX_OK;
638}
Dino Mycled9b7cc12014-09-04 18:43:07 +0530639
640/**============================================================================
641 @brief hdd_dhcp_pkt_info() -
642 Function to log DHCP pkt info
643
644 @param skb : [in] pointer to OS packet (sk_buff)
645 @return : None
646 ===========================================================================*/
647
648void hdd_dhcp_pkt_info(struct sk_buff *skb)
649{
650 /* port no 67 (0x43) or 68 (0x44) */
651
652 if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_REQUEST_MSG)
653 hddLog(VOS_TRACE_LEVEL_INFO, FL("Request"));
654 else if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_RESPONSE_MSG)
655 hddLog(VOS_TRACE_LEVEL_INFO, FL("Response"));
656 else
657 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP invalid"));
658
659 hddLog(VOS_TRACE_LEVEL_INFO,
660 FL("DHCP Dest Addr: %pM Src Addr %pM "
661 " source port : %d, dest port : %d"),
662 skb->data, (skb->data + 6),
663 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))),
664 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))));
665
666 if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
667 (skb->data[DHCP_OPTION53_LENGTH_OFFSET] == DHCP_OPTION53_LENGTH)) {
668
669 switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
670 case DHCPDISCOVER:
671 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP DISCOVER"));
672 break;
673 case DHCPREQUEST:
674 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP REQUEST"));
675 break;
676 case DHCPOFFER:
677 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP OFFER"));
678 break;
679 case DHCPACK:
680 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP ACK"));
681 break;
682 case DHCPNAK:
683 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP NACK"));
684 break;
685 case DHCPRELEASE:
686 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP RELEASE"));
687 break;
688 case DHCPINFORM:
689 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP INFORM"));
690 break;
691
692 default:
693 hddLog(VOS_TRACE_LEVEL_INFO,
694 "%s: DHCP Not Defined OPTION53 : %d", __func__,
695 skb->data[DHCP_OPTION53_STATUS_OFFSET]);
696 }
697 }
698}
699
700/**============================================================================
701 @brief hdd_dump_dhcp_pkt() -
702 Function to dump DHCP packets in TX and RX path.
703
704 @param skb : [in] pointer to OS packet (sk_buff)
705 @param path : [in] bool indicating TX/RX path
706 @return : None
707 ===========================================================================*/
708void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path)
709{
710
711 if ((ntohs(*((u16*)((u8*)skb->data + ETH_TYPE_OFFSET)))
712 == ETH_TYPE_IP_PKT) ||
713 (ntohs(*((u8*)skb->data + PROTOCOL_OFFSET)) == UDP_PROTOCOL)) {
714
715 /* IP protocol 12 bytes of mac addresses in 802.3 header */
716 if ( ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
717 BOOTP_SERVER_PORT ||
718 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
719 BOOTP_CLIENT_PORT ||
720 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
721 BOOTP_SERVER_PORT ||
722 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
723 BOOTP_CLIENT_PORT ) {
724
725 if (path == TX_PATH) {
726 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP TX PATH"));
727 } else {
728 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP RX PATH"));
729 }
730
731 hdd_dhcp_pkt_info(skb);
732 }
733 }
734}
735
Jeff Johnson295189b2012-06-20 16:38:30 -0700736/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530737 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700738 transmitting packets. There are 2 versions of this function. One that uses
739 locked queue and other that uses lockless queues. Both have been retained to
740 do some performance testing
741
742 @param skb : [in] pointer to OS packet (sk_buff)
743 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530744
Jeff Johnson295189b2012-06-20 16:38:30 -0700745 @return : NET_XMIT_DROP if packets are dropped
746 : NET_XMIT_SUCCESS if packet is enqueued succesfully
747 ===========================================================================*/
748int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
749{
750 VOS_STATUS status;
751 WLANTL_ACEnumType ac;
752 sme_QosWmmUpType up;
753 skb_list_node_t *pktNode = NULL;
754 hdd_list_node_t *anchor = NULL;
755 v_SIZE_t pktListSize = 0;
756 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
757 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700758 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700759 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Dino Mycled9b7cc12014-09-04 18:43:07 +0530760 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700761 v_BOOL_t txSuspended = VOS_FALSE;
Mihir Shetef8f74532014-12-04 11:53:34 +0530762 struct sk_buff *skb1;
Jeff Johnson295189b2012-06-20 16:38:30 -0700763
764 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
765
Ravi Joshif9520d62013-10-18 04:11:46 -0700766 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530767 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700768 "%s is called when netif TX %d is disabled",
769 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530770 return NETDEV_TX_BUSY;
771 }
772
Ravi Joshicc57ed42013-10-12 16:31:25 -0700773 //Get TL AC corresponding to Qdisc queue index/AC.
774 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
775
776 if (WLAN_HDD_IBSS == pAdapter->device_mode)
Shailender Karmuchia734f332013-04-19 14:02:48 -0700777 {
778 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
779
Ravi Joshif9520d62013-10-18 04:11:46 -0700780 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
Ravi Joshicc57ed42013-10-12 16:31:25 -0700781 {
c_hpothu32490782014-03-14 19:14:34 +0530782 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700783 "%s: Tx frame in disconnected state in IBSS mode", __func__);
784 ++pAdapter->stats.tx_dropped;
785 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
786 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
787 kfree_skb(skb);
788 return NETDEV_TX_OK;
789 }
790
Shailender Karmuchia734f332013-04-19 14:02:48 -0700791 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
792
793 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
794 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
795 vos_is_macaddr_group(pDestMacAddress)))
796 {
797 STAId = IBSS_BROADCAST_STAID;
c_hpothu32490782014-03-14 19:14:34 +0530798 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Ravi Joshif9520d62013-10-18 04:11:46 -0700799 "%s: BC/MC packet", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700800 }
801 else if (STAId == HDD_WLAN_INVALID_STA_ID)
802 {
c_hpothu32490782014-03-14 19:14:34 +0530803 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshif9520d62013-10-18 04:11:46 -0700804 "%s: Received Unicast frame with invalid staID", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700805 ++pAdapter->stats.tx_dropped;
806 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700807 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Shailender Karmuchia734f332013-04-19 14:02:48 -0700808 kfree_skb(skb);
809 return NETDEV_TX_OK;
810 }
811 }
812 else
813 {
c_hpothu851d9862015-01-19 18:39:06 +0530814 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
815 {
816 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
817 FL("Tx frame in not associated state in %d context"),
818 pAdapter->device_mode);
819 ++pAdapter->stats.tx_dropped;
820 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
821 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
822 kfree_skb(skb);
823 return NETDEV_TX_OK;
824 }
Shailender Karmuchia734f332013-04-19 14:02:48 -0700825 STAId = pHddStaCtx->conn_info.staId[0];
826 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700827
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530828 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 //select_queue call back function
830 up = skb->priority;
831
832 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
833
834#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530835 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700836 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700837#endif // HDD_WMM_DEBUG
838
Mukul Sharma84f27252014-07-14 18:11:42 +0530839#ifdef DEBUG_ROAM_DELAY
840 vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
841 //Should we check below global to avoid function call each time ??
842/*
843 if(gRoamDelayMetaInfo.hdd_monitor_tx)
844 {
845 }
846 */
847#endif
848
Jeff Johnson295189b2012-06-20 16:38:30 -0700849 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700850 /*CR 463598,384996*/
851 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
852 *We check for +1 in the logic,to take care of Zero count which
853 *occurs very frequently in low traffic cases */
854 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
855 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700856 /* 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 -0700857 * 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 +0530858 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 -0700859
Ravi Joshi8a934352013-09-25 16:46:58 -0700860 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
861 STAId, ac
862 );
863 if ( !VOS_IS_STATUS_SUCCESS( status ) )
864 {
c_hpothu32490782014-03-14 19:14:34 +0530865 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700866 "%s: WLANTL_STAPktPending() returned error code %d",
867 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700868 ++pAdapter->stats.tx_dropped;
869 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
870 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Ravi Joshi8a934352013-09-25 16:46:58 -0700871 kfree_skb(skb);
872 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
873 return NETDEV_TX_OK;
874 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700875 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700876 //If we have already reached the max queue size, disable the TX queue
877 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
878 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700879 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
880 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530881 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for ac %d"),ac);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700882 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
883 pAdapter->isTxSuspended[ac] = VOS_TRUE;
884 txSuspended = VOS_TRUE;
Mihir Shete5d148f12014-12-16 17:54:49 +0530885 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_NETDEV,
886 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700887 }
888
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530889 /* If 3/4th of the max queue size is used then enable the flag.
890 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
891 if (WLANTL_AC_BE == ac)
892 {
893 if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
894 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530895 pAdapter->isVosLowResource = VOS_TRUE;
896 }
897 else
898 {
899 pAdapter->isVosLowResource = VOS_FALSE;
900 }
901 }
902
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530903 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530904
Sachin Ahuja8c65f382014-12-12 15:34:21 +0530905 if (( NULL != pHddCtx ) &&
906 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +0530907 {
908 hdd_dump_dhcp_pkt(skb, TX_PATH);
909 }
910
Jeff Johnson295189b2012-06-20 16:38:30 -0700911 if (VOS_TRUE == txSuspended)
912 {
c_hpothu32490782014-03-14 19:14:34 +0530913 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530914 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700915 __func__, ac );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530916 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700917 }
918
919 //Use the skb->cb field to hold the list node information
920 pktNode = (skb_list_node_t *)&skb->cb;
921
922 //Stick the OS packet inside this node.
923 pktNode->skb = skb;
924
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530925 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700926 pktNode->userPriority = up;
927
928
929 INIT_LIST_HEAD(&pktNode->anchor);
930
931 //Insert the OS packet into the appropriate AC queue
932 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
933 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
934 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
935
936 if ( !VOS_IS_STATUS_SUCCESS( status ) )
937 {
c_hpothu32490782014-03-14 19:14:34 +0530938 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 -0700939 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
940 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
941 ++pAdapter->stats.tx_dropped;
942 kfree_skb(skb);
943 return NETDEV_TX_OK;
944 }
945
946 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
947 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700948 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700949
Kiet Lamf040f472013-11-20 21:15:23 +0530950 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
951 {
952 /* Function which will determine acquire admittance for a
953 * WMM AC is required or not based on psb configuration done
954 * in the framework
955 */
956 hdd_wmm_acquire_access_required(pAdapter, ac);
957 }
958
Jeff Johnson295189b2012-06-20 16:38:30 -0700959 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530960 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
961 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700962 {
963 granted = VOS_TRUE;
964 }
965 else
966 {
967 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530968 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700970 if ( granted && ( pktListSize == 1 ))
971 {
972 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +0530973 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700974 status = WLANTL_STAPktPending(
975 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
976 STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700977 if ( !VOS_IS_STATUS_SUCCESS( status ) )
978 {
c_hpothu32490782014-03-14 19:14:34 +0530979 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 -0700980
981 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
982 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
983 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
984 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
985 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Mihir Shetef8f74532014-12-04 11:53:34 +0530986 /* Free the skb only if we are able to remove it from the list.
987 * If we are not able to retrieve it from the list it means that
988 * the skb was pulled by TX Thread and is use so we should not free
989 * it here
990 */
991 if (VOS_IS_STATUS_SUCCESS(status))
992 {
993 pktNode = list_entry(anchor, skb_list_node_t, anchor);
994 skb1 = pktNode->skb;
995 kfree_skb(skb1);
996 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700997 ++pAdapter->stats.tx_dropped;
998 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
999 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Jeff Johnson295189b2012-06-20 16:38:30 -07001000 return NETDEV_TX_OK;
1001 }
1002 }
1003
1004 dev->trans_start = jiffies;
1005
1006 return NETDEV_TX_OK;
1007}
1008
1009/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -07001010 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
1011
1012 @param pHddStaCtx : [in] pointer to HDD Station Context
1013 pMacAddress [in] pointer to Peer Mac address
1014 staID [out] pointer to Station Index
1015 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
1016 ===========================================================================*/
1017
1018VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1019{
1020 v_U8_t idx;
1021
1022 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
1023 {
1024 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
1025 pMacAddress, sizeof(v_MACADDR_t)))
1026 {
1027 *staId = pHddStaCtx->conn_info.staId[idx];
1028 return VOS_STATUS_SUCCESS;
1029 }
1030 }
1031
1032 return VOS_STATUS_E_FAILURE;
1033}
1034
1035/**============================================================================
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301036 @brief __hdd_tx_timeout() - Function handles timeout during transmission.
Jeff Johnson295189b2012-06-20 16:38:30 -07001037
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301038 @param dev : [in] pointer to network device
Jeff Johnson295189b2012-06-20 16:38:30 -07001039 @return : None
1040 ===========================================================================*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301041void __hdd_tx_timeout(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001042{
Ravi Joshicc57ed42013-10-12 16:31:25 -07001043 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1044 struct netdev_queue *txq;
1045 int i = 0;
Mukul Sharma42b3d432014-10-16 16:13:40 +05301046 v_ULONG_t diff_in_jiffies = 0;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001047
Mihir Shetef3473692014-06-27 15:13:20 +05301048 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301049 "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu",
1050 __func__,jiffies,dev->trans_start);
Mihir Shetef3473692014-06-27 15:13:20 +05301051
c_hpothub8245442013-11-20 23:41:09 +05301052 if ( NULL == pAdapter )
1053 {
c_hpothu32490782014-03-14 19:14:34 +05301054 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301055 FL("pAdapter is NULL"));
1056 VOS_ASSERT(0);
1057 return;
1058 }
1059
Mihir Shetef3473692014-06-27 15:13:20 +05301060 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
1061
Jeff Johnson295189b2012-06-20 16:38:30 -07001062 //Getting here implies we disabled the TX queues for too long. Queues are
1063 //disabled either because of disassociation or low resource scenarios. In
1064 //case of disassociation it is ok to ignore this. But if associated, we have
1065 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -07001066
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301067 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001068 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
1069 pAdapter->wmm_tx_queue[0].count,
1070 pAdapter->wmm_tx_queue[1].count,
1071 pAdapter->wmm_tx_queue[2].count,
1072 pAdapter->wmm_tx_queue[3].count);
1073
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301074 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001075 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
1076 pAdapter->isTxSuspended[0],
1077 pAdapter->isTxSuspended[1],
1078 pAdapter->isTxSuspended[2],
1079 pAdapter->isTxSuspended[3]);
1080
1081 for (i = 0; i < 8; i++)
1082 {
1083 txq = netdev_get_tx_queue(dev, i);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301084 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301085 "Queue%d status: %d txq->trans_start %lu",
1086 i, netif_tx_queue_stopped(txq),txq->trans_start);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001087 }
1088
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301089 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001090 "carrier state: %d", netif_carrier_ok(dev));
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301091
Mihir Shetef3473692014-06-27 15:13:20 +05301092 /* continuousTxTimeoutCount will be reset whenever TL fetches packet
1093 * from HDD
1094 */
1095 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
1096
Mukul Sharma42b3d432014-10-16 16:13:40 +05301097 diff_in_jiffies = jiffies - pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut;
1098 if((pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount > 1)&&
1099 ((diff_in_jiffies) > (HDD_TX_TIMEOUT * 2 ))
1100 )
1101 {
1102 /*
1103 * In Open security case when there is no traffic is running, it may possible
1104 * tx time-out may once happen and later we recovered then we need to
1105 * reset the continuousTxTimeoutCount because it is only getting modified
1106 * when traffic is running. So if over a period of time if this count reaches
1107 * to HDD_TX_STALL_SSR_THRESHOLD then host is triggering false subsystem restart.
1108 * so in genuine Tx Time out case kernel will call the tx time-out back to back at
1109 * interval of HDD_TX_TIMEOUT.So now we are checking if previous TX TIME out was
1110 * occurred more then twice of HDD_TX_TIMEOUT back then we may recovered here.
1111 */
1112 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1113 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1114 FL("This is false alarm so resetting the continuousTxTimeoutCount"));
1115 }
1116
1117 //update last jiffies after the check
1118 pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut = jiffies;
1119
Mihir Shete327c2ab2014-11-13 15:17:02 +05301120 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
1121 HDD_TX_STALL_RECOVERY_THRESHOLD)
1122 {
1123 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1124 "%s: Request firmware for recovery",__func__);
1125 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
1126 }
1127
Mihir Shetef3473692014-06-27 15:13:20 +05301128 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1129 HDD_TX_STALL_SSR_THRESHOLD)
1130 {
1131 // Driver could not recover, issue SSR
1132 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1133 "%s: Cannot recover from Data stall Issue SSR",
1134 __func__);
Mihir Shetefd62d9d2014-08-06 15:08:21 +05301135 WLANTL_FatalError();
Mihir Shetef3473692014-06-27 15:13:20 +05301136 return;
1137 }
1138
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301139 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
1140 * every 5sec. The TL debug spits out a lot of information on the
1141 * serial console, if it is called every time *hdd_tx_timeout* is
1142 * called then we may get a watchdog bite on the Application
1143 * processor, so ratelimit the TL debug logs.
1144 */
1145 if (__ratelimit(&hdd_tx_timeout_rs))
1146 {
1147 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +05301148 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301149 }
Mihir Shetef3473692014-06-27 15:13:20 +05301150
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301151}
Jeff Johnson295189b2012-06-20 16:38:30 -07001152
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301153/**============================================================================
1154 @brief hdd_tx_timeout() - Function called by OS if there is any
1155 timeout during transmission. Since HDD simply enqueues packet
1156 and returns control to OS right away, this would never be invoked
1157
1158 @param dev : [in] pointer to network device
1159 @return : None
1160 ===========================================================================*/
1161void hdd_tx_timeout(struct net_device *dev)
1162{
1163 vos_ssr_protect(__func__);
1164 __hdd_tx_timeout(dev);
1165 vos_ssr_unprotect(__func__);
1166}
Jeff Johnson295189b2012-06-20 16:38:30 -07001167
1168/**============================================================================
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301169 @brief __hdd_stats() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -07001170 device TX/RX statistic
1171
1172 @param dev : [in] pointer to Libra network device
1173
1174 @return : pointer to net_device_stats structure
1175 ===========================================================================*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301176struct net_device_stats* __hdd_stats(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001177{
1178 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +05301179
1180 if ( NULL == pAdapter )
1181 {
c_hpothu32490782014-03-14 19:14:34 +05301182 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301183 FL("pAdapter is NULL"));
1184 VOS_ASSERT(0);
1185 return NULL;
1186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001187
1188 return &pAdapter->stats;
1189}
1190
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301191struct net_device_stats* hdd_stats(struct net_device *dev)
1192{
1193 struct net_device_stats* dev_stats;
1194
1195 vos_ssr_protect(__func__);
1196 dev_stats = __hdd_stats(dev);
1197 vos_ssr_unprotect(__func__);
1198
1199 return dev_stats;
1200}
Jeff Johnson295189b2012-06-20 16:38:30 -07001201
1202/**============================================================================
1203 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
1204 modules in HDD
1205
1206 @param pAdapter : [in] pointer to adapter context
1207 @return : VOS_STATUS_E_FAILURE if any errors encountered
1208 : VOS_STATUS_SUCCESS otherwise
1209 ===========================================================================*/
1210VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
1211{
1212 VOS_STATUS status = VOS_STATUS_SUCCESS;
1213 v_SINT_t i = -1;
1214
c_hpothub8245442013-11-20 23:41:09 +05301215 if ( NULL == pAdapter )
1216 {
c_hpothu32490782014-03-14 19:14:34 +05301217 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301218 FL("pAdapter is NULL"));
1219 VOS_ASSERT(0);
1220 return VOS_STATUS_E_FAILURE;
1221 }
1222
Jeff Johnson295189b2012-06-20 16:38:30 -07001223 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301224 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001225
1226 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
1227 //Will be zeroed out during alloc
1228
1229 while (++i != NUM_TX_QUEUES)
1230 {
1231 pAdapter->isTxSuspended[i] = VOS_FALSE;
1232 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1233 }
1234
1235 return status;
1236}
1237
1238
1239/**============================================================================
1240 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
1241 modules in HDD
1242
1243 @param pAdapter : [in] pointer to adapter context
1244 @return : VOS_STATUS_E_FAILURE if any errors encountered
1245 : VOS_STATUS_SUCCESS otherwise
1246 ===========================================================================*/
1247VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
1248{
1249 VOS_STATUS status = VOS_STATUS_SUCCESS;
1250 v_SINT_t i = -1;
1251
c_hpothub8245442013-11-20 23:41:09 +05301252 if ( NULL == pAdapter )
1253 {
c_hpothu32490782014-03-14 19:14:34 +05301254 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301255 FL("pAdapter is NULL"));
1256 VOS_ASSERT(0);
1257 return VOS_STATUS_E_FAILURE;
1258 }
1259
Jeff Johnson295189b2012-06-20 16:38:30 -07001260 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301261 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301262 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301263 FL("failed to flush tx queues"));
1264
Jeff Johnson295189b2012-06-20 16:38:30 -07001265 while (++i != NUM_TX_QUEUES)
1266 {
1267 //Free up actual list elements in the Tx queue
1268 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1269 }
1270
1271 return status;
1272}
1273
1274
1275/**============================================================================
1276 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1277 modules in HDD
1278
1279 @param pAdapter : [in] pointer to adapter context
1280 @return : VOS_STATUS_E_FAILURE if any errors encountered
1281 : VOS_STATUS_SUCCESS otherwise
1282 ===========================================================================*/
1283VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1284{
1285 return hdd_flush_tx_queues(pAdapter);
1286}
1287
1288
1289/**============================================================================
1290 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1291
1292 @param pVosPacket : [in] pointer to vos packet
1293 @return : VOS_TRUE if the packet is EAPOL
1294 : VOS_FALSE otherwise
1295 ===========================================================================*/
1296
1297v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1298{
1299 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1300 v_BOOL_t fEAPOL = VOS_FALSE;
1301 void *pBuffer = NULL;
1302
1303
1304 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1305 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
Abhishek Singhfa011222014-04-14 10:57:08 +05301306 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001307 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301308 if ( pBuffer && *(unsigned short*)pBuffer ==
1309 vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001310 {
1311 fEAPOL = VOS_TRUE;
1312 }
1313 }
1314
1315 return fEAPOL;
1316}
1317
Abhishek Singhfa011222014-04-14 10:57:08 +05301318/**============================================================================
1319 @brief hdd_IsARP() - Checks the packet is ARP or not.
1320
1321 @param pVosPacket : [in] pointer to vos packet
1322 @return : VOS_TRUE if the packet is ARP
1323 : VOS_FALSE otherwise
1324 ===========================================================================*/
1325
1326v_BOOL_t hdd_IsARP( vos_pkt_t *pVosPacket )
1327{
1328 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1329 v_BOOL_t fIsARP = VOS_FALSE;
1330 void *pBuffer = NULL;
1331
1332
1333 vosStatus = vos_pkt_peek_data( pVosPacket,
1334 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1335 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1336 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1337 {
1338 if ( pBuffer && *(unsigned short*)pBuffer ==
1339 vos_cpu_to_be16(HDD_ETHERTYPE_ARP) )
1340 {
1341 fIsARP = VOS_TRUE;
1342 }
1343 }
1344
1345 return fIsARP;
1346}
Jeff Johnson295189b2012-06-20 16:38:30 -07001347
1348#ifdef FEATURE_WLAN_WAPI // Need to update this function
1349/**============================================================================
1350 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1351
1352 @param pVosPacket : [in] pointer to vos packet
1353 @return : VOS_TRUE if the packet is WAI
1354 : VOS_FALSE otherwise
1355 ===========================================================================*/
1356
1357v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1358{
1359 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1360 v_BOOL_t fIsWAI = VOS_FALSE;
1361 void *pBuffer = NULL;
1362
1363 // Need to update this function
1364 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1365 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1366
1367 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1368 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301369 if ( pBuffer && *(unsigned short*)pBuffer ==
1370 vos_cpu_to_be16(HDD_ETHERTYPE_WAI) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 {
1372 fIsWAI = VOS_TRUE;
1373 }
1374 }
1375
1376 return fIsWAI;
1377}
1378#endif /* FEATURE_WLAN_WAPI */
1379
1380/**============================================================================
1381 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1382 to indicate that a packet has been transmitted across the SDIO bus
1383 succesfully. OS packet resources can be released after this cbk.
1384
1385 @param vosContext : [in] pointer to VOS context
1386 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1387 @param vosStatusIn : [in] status of the transmission
1388
1389 @return : VOS_STATUS_E_FAILURE if any errors encountered
1390 : VOS_STATUS_SUCCESS otherwise
1391 ===========================================================================*/
1392VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1393 vos_pkt_t *pVosPacket,
1394 VOS_STATUS vosStatusIn )
1395{
1396 VOS_STATUS status = VOS_STATUS_SUCCESS;
1397 hdd_adapter_t *pAdapter = NULL;
1398 hdd_context_t *pHddCtx = NULL;
1399 void* pOsPkt = NULL;
1400
1401 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1402 {
c_hpothu32490782014-03-14 19:14:34 +05301403 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301404 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001405 return VOS_STATUS_E_FAILURE;
1406 }
1407
1408 //Return the skb to the OS
1409 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301410 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001411 {
1412 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301413 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301414 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001415 vos_pkt_return_packet( pVosPacket );
1416 return VOS_STATUS_E_FAILURE;
1417 }
1418
1419 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001420 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001421 //Get the Adapter context.
1422 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Agarwal Ashish971c2882013-10-30 20:11:12 +05301423 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07001424 {
c_hpothu32490782014-03-14 19:14:34 +05301425 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301426 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001427 }
1428 else
1429 {
1430 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1431 }
1432
1433 kfree_skb((struct sk_buff *)pOsPkt);
1434
1435 //Return the VOS packet resources.
1436 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301437 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001438 {
c_hpothu32490782014-03-14 19:14:34 +05301439 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301440 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001441 }
1442
1443 return status;
1444}
1445
1446
1447/**============================================================================
1448 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1449 fetch a packet for transmission.
1450
1451 @param vosContext : [in] pointer to VOS context
1452 @param staId : [in] Station for which TL is requesting a pkt
1453 @param ac : [in] access category requested by TL
1454 @param pVosPacket : [out] pointer to VOS packet packet pointer
1455 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1456
1457 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1458 : VOS_STATUS_E_FAILURE if any errors encountered
1459 : VOS_STATUS_SUCCESS otherwise
1460 ===========================================================================*/
1461VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1462 v_U8_t *pStaId,
1463 WLANTL_ACEnumType ac,
1464 vos_pkt_t **ppVosPacket,
1465 WLANTL_MetaInfoType *pPktMetaInfo )
1466{
1467 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1468 hdd_adapter_t *pAdapter = NULL;
1469 hdd_context_t *pHddCtx = NULL;
1470 hdd_list_node_t *anchor = NULL;
1471 skb_list_node_t *pktNode = NULL;
1472 struct sk_buff *skb = NULL;
1473 vos_pkt_t *pVosPacket = NULL;
1474 v_MACADDR_t* pDestMacAddress = NULL;
1475 v_TIME_t timestamp;
1476 WLANTL_ACEnumType newAc;
1477 v_SIZE_t size = 0;
Abhishek Singhfa011222014-04-14 10:57:08 +05301478 v_U16_t packet_size;
Jeff Johnson295189b2012-06-20 16:38:30 -07001479 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001480 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001481
1482 //Sanity check on inputs
1483 if ( ( NULL == vosContext ) ||
1484 ( NULL == pStaId ) ||
1485 ( NULL == ppVosPacket ) ||
1486 ( NULL == pPktMetaInfo ) )
1487 {
c_hpothu32490782014-03-14 19:14:34 +05301488 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301489 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001490 return VOS_STATUS_E_FAILURE;
1491 }
1492
1493 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001494 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001495 if(pHddCtx == NULL)
1496 {
c_hpothu32490782014-03-14 19:14:34 +05301497 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301498 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001499 return VOS_STATUS_E_FAILURE;
1500 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001501 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001502 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001503 {
c_hpothu32490782014-03-14 19:14:34 +05301504 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301505 FL("pAdapter is NULL %u"), *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001506 VOS_ASSERT(0);
1507 return VOS_STATUS_E_FAILURE;
1508 }
1509
1510 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1511
1512 *ppVosPacket = NULL;
1513
1514 //Make sure the AC being asked for is sane
1515 if( ac >= WLANTL_MAX_AC || ac < 0)
1516 {
c_hpothu32490782014-03-14 19:14:34 +05301517 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301518 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001519 return VOS_STATUS_E_FAILURE;
1520 }
1521
1522 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1523
1524#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301525 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301526 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001527#endif // HDD_WMM_DEBUG
1528
1529 // We find an AC with packets
1530 // or we determine we have no more packets to send
1531 // HDD is not allowed to change AC.
1532
1533 // has this AC been admitted? or
1534 // To allow EAPOL packets when not authenticated
1535 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1536 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1537 {
1538 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1539#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301540 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001541 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001542#endif // HDD_WMM_DEBUG
1543 return VOS_STATUS_E_FAILURE;
1544 }
1545
1546 // do we have any packets pending in this AC?
1547 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1548 if( size > 0 )
1549 {
1550 // yes, so process it
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: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001554#endif // HDD_WMM_DEBUG
1555 }
1556 else
1557 {
1558 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1559#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301560 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001561 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001562#endif // HDD_WMM_DEBUG
1563 return VOS_STATUS_E_FAILURE;
1564 }
1565
1566 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1567 //This simplifies the locking and unlocking of Tx queue
1568 status = vos_pkt_wrap_data_packet( &pVosPacket,
1569 VOS_PKT_TYPE_TX_802_3_DATA,
1570 NULL, //OS Pkt is not being passed
1571 hdd_tx_low_resource_cbk,
1572 pAdapter );
1573
1574 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1575 {
1576 //Remember VOS is in a low resource situation
1577 pAdapter->isVosOutOfResource = VOS_TRUE;
1578 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05301579 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 -07001580 //TL will now think we have no more packets in this AC
1581 return VOS_STATUS_E_FAILURE;
1582 }
1583
1584 //Remove the packet from the queue
1585 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1586 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1587 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1588
1589 if(VOS_STATUS_SUCCESS == status)
1590 {
1591 //If success then we got a valid packet from some AC
1592 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1593 skb = pktNode->skb;
1594 }
1595 else
1596 {
1597 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05301598 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001599 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001600 vos_pkt_return_packet(pVosPacket);
1601 return VOS_STATUS_E_FAILURE;
1602 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001603 //Attach skb to VOS packet.
1604 status = vos_pkt_set_os_packet( pVosPacket, skb );
1605 if (status != VOS_STATUS_SUCCESS)
1606 {
c_hpothu32490782014-03-14 19:14:34 +05301607 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001608 vos_pkt_return_packet(pVosPacket);
1609 ++pAdapter->stats.tx_dropped;
1610 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1611 kfree_skb(skb);
1612 return VOS_STATUS_E_FAILURE;
1613 }
1614
1615 //Just being paranoid. To be removed later
1616 if(pVosPacket == NULL)
1617 {
c_hpothu32490782014-03-14 19:14:34 +05301618 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 -07001619 ++pAdapter->stats.tx_dropped;
1620 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1621 kfree_skb(skb);
1622 return VOS_STATUS_E_FAILURE;
1623 }
1624
Dino Mycle3b9536d2014-07-09 22:05:24 +05301625#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1626 {
1627 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
1628 /* vos_is_macaddr_group expects data in v_MACADDR_t format
1629 */
1630 if (vos_is_macaddr_group(pDestMacAddress))
1631 {
1632 pAdapter->hdd_stats.hddTxRxStats.txMcast[ac]++;
1633 }
1634
1635 }
1636
1637#endif
1638
Chilam NG571c65a2013-01-19 12:27:36 +05301639#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001640 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05301641 {
1642 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301643 u8 mac[6];
1644
Hoonki Lee387663d2013-02-05 18:08:43 -08001645 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301646
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001647 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05301648 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301649 "broadcast packet, not adding to peer list");
1650 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1651 mac, 6) != 0) {
c_hpothu32490782014-03-14 19:14:34 +05301652 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001653 "extract mac: " MAC_ADDRESS_STR,
1654 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05301655
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001656 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301657 } else {
c_hpothu32490782014-03-14 19:14:34 +05301658 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301659 "packet da is bssid, not adding to peer list");
1660 }
1661 }
1662#endif
1663
Jeff Johnson295189b2012-06-20 16:38:30 -07001664 //Return VOS packet to TL;
1665 *ppVosPacket = pVosPacket;
1666
1667 //Fill out the meta information needed by TL
1668 //FIXME This timestamp is really the time stamp of wrap_data_packet
1669 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1670 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1671
1672 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1673 pPktMetaInfo->ucIsEapol = 0;
1674 else
1675 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1676
Sachin Ahuja8c65f382014-12-12 15:34:21 +05301677 if ((NULL != pHddCtx) &&
1678 (pHddCtx->cfg_ini->gEnableDebugLog))
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001679 {
1680 proto_type = vos_pkt_get_proto_type(skb,
1681 pHddCtx->cfg_ini->gEnableDebugLog);
1682 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1683 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05301684 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001685 "STA TX EAPOL");
1686 }
1687 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1688 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05301689 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001690 "STA TX DHCP");
1691 }
1692 }
1693
Abhishek Singhfa011222014-04-14 10:57:08 +05301694 vos_pkt_get_packet_length( pVosPacket,&packet_size );
1695 if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
1696 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
1697
Jeff Johnson295189b2012-06-20 16:38:30 -07001698#ifdef FEATURE_WLAN_WAPI
1699 // Override usIsEapol value when its zero for WAPI case
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301700 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001701#endif /* FEATURE_WLAN_WAPI */
1702
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301703 /* 1. Check if ACM is set for this AC
1704 * 2. If set, check if this AC had already admitted
1705 * 3. If not already admitted, downgrade the UP to next best UP
1706 * 4. Allow only when medium time is non zero when Addts accepted
1707 * else downgrade traffic. we opted downgrading over Delts when
1708 * medium time is zero because while doing downgradig driver is not
1709 * clearing the wmm context so consider in subsequent roaming
1710 * if AP (new or same AP) accept the Addts with valid medium time
1711 * no application support is required where if we have opted
1712 * delts Applications have to again do Addts or STA will never
1713 * go for Addts.
1714 */
1715
1716 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
1717 (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid &&
1718 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07001719 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301720 pPktMetaInfo->ucUP = pktNode->userPriority;
1721 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 }
1723 else
1724 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301725 //Downgrade the UP
1726 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1727 newAc = WLANTL_AC_BK;
1728 for (i=ac-1; i>0; i--)
Jeff Johnson295189b2012-06-20 16:38:30 -07001729 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301730 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1731 {
1732 newAc = i;
1733 break;
1734 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001735 }
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301736 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1737 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1738 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
1739 "Downgrading UP %d to UP %d ",
1740 pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07001741 }
1742
Mukul Sharma84f27252014-07-14 18:11:42 +05301743#ifdef DEBUG_ROAM_DELAY
1744 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
1745#endif
1746
Jeff Johnson295189b2012-06-20 16:38:30 -07001747 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1748 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1749 if ( 1 < size )
1750 {
1751 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1752 }
1753 else
1754 {
1755 pPktMetaInfo->bMorePackets = 0;
1756 }
1757
1758 //Extract the destination address from ethernet frame
1759 pDestMacAddress = (v_MACADDR_t*)skb->data;
1760 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1761 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1762
1763
1764
1765 // if we are in a backpressure situation see if we can turn the hose back on
1766 if ( (pAdapter->isTxSuspended[ac]) &&
1767 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1768 {
1769 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1770 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05301771 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001772 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001773 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1774 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1775 skb_get_queue_mapping(skb) ));
Mihir Shete5d148f12014-12-16 17:54:49 +05301776 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_WAKE_NETDEV,
1777 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001778 }
1779
1780
1781 // We're giving the packet to TL so consider it transmitted from
1782 // a statistics perspective. We account for it here instead of
1783 // when the packet is returned for two reasons. First, TL will
1784 // manipulate the skb to the point where the len field is not
1785 // accurate, leading to inaccurate byte counts if we account for
1786 // it later. Second, TL does not provide any feedback as to
1787 // whether or not the packet was successfully sent over the air,
1788 // so the packet counts will be the same regardless of where we
1789 // account for them
1790 pAdapter->stats.tx_bytes += skb->len;
1791 ++pAdapter->stats.tx_packets;
1792 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1793 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301794 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001795
Leo Chang50bbd252013-04-25 14:58:01 -07001796 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1797 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001798 {
1799 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1800 {
c_hpothu32490782014-03-14 19:14:34 +05301801 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001802 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001803 return VOS_STATUS_E_FAILURE;
1804 }
1805 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1806 {
1807 if(0 == pHddCtx->tmInfo.txFrameCount)
1808 {
1809 /* Just recovered from sleep timeout */
1810 pHddCtx->tmInfo.lastOpenTs = timestamp;
1811 }
1812
Leo Chang50bbd252013-04-25 14:58:01 -07001813 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1814 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001815 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1816 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001817 /* During TX open duration, TX frame count is larger than threshold
1818 * Block TX during Sleep time */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05301819 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001820 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001821 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 pHddCtx->tmInfo.lastblockTs = timestamp;
1823 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1824 {
1825 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1826 }
1827 }
1828 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1829 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1830 {
1831 /* During TX open duration, TX frame count is less than threshold
1832 * Reset count and timestamp to prepare next cycle */
1833 pHddCtx->tmInfo.lastOpenTs = timestamp;
1834 pHddCtx->tmInfo.txFrameCount = 0;
1835 }
1836 else
1837 {
1838 /* Do Nothing */
1839 }
1840 pHddCtx->tmInfo.txFrameCount++;
1841 }
1842 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1843 }
1844
1845
1846#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301847 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 -07001848#endif // HDD_WMM_DEBUG
1849
1850 return status;
1851}
1852
1853
1854/**============================================================================
1855 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1856 case where VOS packets are not available at the time of the call to get
1857 packets. This callback function is invoked by VOS when packets are
1858 available.
1859
1860 @param pVosPacket : [in] pointer to VOS packet
1861 @param userData : [in] opaque user data that was passed initially
1862
1863 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1864 : VOS_STATUS_SUCCESS otherwise
1865 =============================================================================*/
1866VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1867 v_VOID_t *userData )
1868{
1869 VOS_STATUS status;
1870 v_SINT_t i = 0;
1871 v_SIZE_t size = 0;
1872 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1873
Agarwal Ashish971c2882013-10-30 20:11:12 +05301874 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001875 {
c_hpothu32490782014-03-14 19:14:34 +05301876 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301877 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001878 return VOS_STATUS_E_FAILURE;
1879 }
1880
1881 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1882 //situation. Here we will only signal TL that there is a pending data for a STA.
1883 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1884 vos_pkt_return_packet( pVosPacket );
1885
1886 pAdapter->isVosOutOfResource = VOS_FALSE;
1887
1888 //Indicate to TL that there is pending data if a queue is non empty
1889 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1890 {
1891 size = 0;
1892 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1893 if ( size > 0 )
1894 {
1895 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1896 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
1897 (WLANTL_ACEnumType)i );
1898 if( !VOS_IS_STATUS_SUCCESS( status ) )
1899 {
c_hpothu32490782014-03-14 19:14:34 +05301900 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301901 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07001902 }
1903 }
1904 }
1905
1906 return VOS_STATUS_SUCCESS;
1907}
1908
1909
1910/**============================================================================
1911 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
1912 TL will call this to notify the HDD when one or more packets were
1913 received for a registered STA.
1914
1915 @param vosContext : [in] pointer to VOS context
1916 @param pVosPacketChain : [in] pointer to VOS packet chain
1917 @param staId : [in] Station Id
1918 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
1919
1920 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1921 : VOS_STATUS_SUCCESS otherwise
1922 ===========================================================================*/
1923VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
1924 vos_pkt_t *pVosPacketChain,
1925 v_U8_t staId,
1926 WLANTL_RxMetaInfoType* pRxMetaInfo )
1927{
1928 hdd_adapter_t *pAdapter = NULL;
1929 hdd_context_t *pHddCtx = NULL;
1930 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1931 int rxstat;
1932 struct sk_buff *skb = NULL;
1933 vos_pkt_t* pVosPacket;
1934 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001935 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07001936
1937 //Sanity check on inputs
1938 if ( ( NULL == vosContext ) ||
1939 ( NULL == pVosPacketChain ) ||
1940 ( NULL == pRxMetaInfo ) )
1941 {
c_hpothu32490782014-03-14 19:14:34 +05301942 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301943 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001944 return VOS_STATUS_E_FAILURE;
1945 }
1946
Kiet Lam3c2ee302014-03-23 23:23:22 -07001947 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 if ( NULL == pHddCtx )
1949 {
c_hpothu32490782014-03-14 19:14:34 +05301950 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301951 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001952 return VOS_STATUS_E_FAILURE;
1953 }
1954
1955 pAdapter = pHddCtx->sta_to_adapter[staId];
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301956 if( (NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001957 {
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05301958 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1959 "%s: pAdapter is Null or adapter has invalid magic for staId %u",
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05301960 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 return VOS_STATUS_E_FAILURE;
1962 }
1963
1964 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
1965
1966 // walk the chain until all are processed
1967 pVosPacket = pVosPacketChain;
1968 do
1969 {
1970 // get the pointer to the next packet in the chain
1971 // (but don't unlink the packet since we free the entire chain later)
1972 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
1973
1974 // both "success" and "empty" are acceptable results
1975 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
1976 {
1977 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301978 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301979 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001980 return VOS_STATUS_E_FAILURE;
1981 }
1982
1983 // Extract the OS packet (skb).
1984 // Tell VOS to detach the OS packet from the VOS packet
1985 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
1986 if(!VOS_IS_STATUS_SUCCESS( status ))
1987 {
1988 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05301989 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301990 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001991 return VOS_STATUS_E_FAILURE;
1992 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001993
1994 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1995 {
c_hpothu32490782014-03-14 19:14:34 +05301996 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07001997 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
1998 return eHAL_STATUS_FAILURE;
1999 }
2000
Chilam Ng1279e232013-01-25 15:06:52 -08002001#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002002 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
2003 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08002004 {
2005 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08002006 u8 mac[6];
2007
Hoonki Lee387663d2013-02-05 18:08:43 -08002008 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08002009
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002010 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302011 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002012 "rx broadcast packet, not adding to peer list");
2013 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2014 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002015 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05302016 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002017 "rx extract mac:" MAC_ADDRESS_STR,
2018 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302019 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05302020 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
2021 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002022 {
2023 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05302024 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002025 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
2026 }
Chilam Ng1279e232013-01-25 15:06:52 -08002027 } else {
c_hpothu32490782014-03-14 19:14:34 +05302028 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002029 "rx packet sa is bssid, not adding to peer list");
2030 }
2031 }
2032#endif
2033
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002034 if (pHddCtx->cfg_ini->gEnableDebugLog)
2035 {
2036 proto_type = vos_pkt_get_proto_type(skb,
2037 pHddCtx->cfg_ini->gEnableDebugLog);
2038 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2039 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002041 "STA RX EAPOL");
2042 }
2043 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2044 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002046 "STA RX DHCP");
2047 }
2048 }
2049
Mukul Sharma84f27252014-07-14 18:11:42 +05302050#ifdef DEBUG_ROAM_DELAY
2051 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2052 //Should we check below global to avoid function call each time ??
2053 /*
2054 if(gRoamDelayMetaInfo.hdd_monitor_rx)
2055 {
2056 }
2057 */
2058#endif
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302059 if (( NULL != pHddCtx ) &&
2060 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05302061 {
2062 hdd_dump_dhcp_pkt(skb, RX_PATH);
2063 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302064
Jeff Johnson295189b2012-06-20 16:38:30 -07002065 skb->dev = pAdapter->dev;
2066 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002067 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002068 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2069 ++pAdapter->stats.rx_packets;
2070 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002071#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002072#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002073 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002074#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 rxstat = netif_rx_ni(skb);
2077 if (NET_RX_SUCCESS == rxstat)
2078 {
2079 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002080 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002081 }
2082 else
2083 {
2084 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2085 }
2086 // now process the next packet in the chain
2087 pVosPacket = pNextVosPacket;
2088
2089 } while (pVosPacket);
2090
2091 //Return the entire VOS packet chain to the resource pool
2092 status = vos_pkt_return_packet( pVosPacketChain );
2093 if(!VOS_IS_STATUS_SUCCESS( status ))
2094 {
c_hpothu32490782014-03-14 19:14:34 +05302095 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002096 }
2097
2098 pAdapter->dev->last_rx = jiffies;
2099
2100 return status;
2101}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002102/**============================================================================
2103 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2104 Enable/Disable split scan based on TX and RX traffic.
2105 @param HddContext : [in] pointer to Hdd context
2106 @return : None
2107 ===========================================================================*/
2108void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2109{
2110 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2111 hdd_adapter_t *pAdapter = NULL;
2112 hdd_station_ctx_t *pHddStaCtx = NULL;
2113 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2114 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2115 VOS_STATUS status;
2116 v_U8_t staId = 0;
2117 v_U8_t fconnected = 0;
2118
c_hpothub8245442013-11-20 23:41:09 +05302119 if (NULL == phddctx)
2120 {
c_hpothu32490782014-03-14 19:14:34 +05302121 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05302122 FL("phddctx is NULL"));
2123 VOS_ASSERT(0);
2124 return;
2125 }
2126
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002127 if (!cfg_param->dynSplitscan)
2128 {
c_hpothu32490782014-03-14 19:14:34 +05302129 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002130 "%s: Error : Dynamic split scan is not Enabled : %d",
2131 __func__, pHddCtx->cfg_ini->dynSplitscan);
2132 return;
2133 }
2134
2135 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2136 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2137 {
2138 pAdapter = pAdapterNode->pAdapter;
2139
2140 if ( pAdapter )
2141 {
c_hpothu32490782014-03-14 19:14:34 +05302142 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002143 "%s: Adapter with device mode %d exists",
2144 __func__, pAdapter->device_mode);
2145
2146 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2147 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2148 {
2149 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2150 if ((eConnectionState_Associated ==
2151 pHddStaCtx->conn_info.connState) &&
2152 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2153 {
2154 fconnected = TRUE;
2155 }
2156 }
2157 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2158 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2159 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302160 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2161 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2162 if(pSapCtx == NULL){
2163 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2164 FL("psapCtx is NULL"));
2165 return;
2166 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002167 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2168 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302169 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002170 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302171 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002172 {
2173 fconnected = TRUE;
2174 }
2175 }
2176 }
2177 if ( fconnected )
2178 {
c_hpothu32490782014-03-14 19:14:34 +05302179 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002180 "%s: One of the interface is connected check for scan",
2181 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302182 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302183 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
2184 "miracast = %d", __func__,
2185 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
2186 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
2187 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002188
2189 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
2190 cfg_param->trafficMntrTmrForSplitScan);
2191 //Check for the previous statistics count
2192 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
2193 cfg_param->txRxThresholdForSplitScan) ||
2194 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
2195 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05302196 pHddCtx->drvr_miracast ||
2197 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002198 {
2199 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2200 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2201
2202 if (!pHddCtx->issplitscan_enabled)
2203 {
2204 pHddCtx->issplitscan_enabled = TRUE;
2205 sme_enable_disable_split_scan(
2206 WLAN_HDD_GET_HAL_CTX(pAdapter),
2207 cfg_param->nNumStaChanCombinedConc,
2208 cfg_param->nNumP2PChanCombinedConc);
2209 }
2210 return;
2211 }
2212 else
2213 {
2214 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2215 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2216 }
2217 fconnected = FALSE;
2218 }
2219 }
2220 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
2221 pAdapterNode = pNext;
2222 }
2223
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05302224 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
2225 * of disabling the split scan and thus do not disable the same when the
2226 * low TXRX condition is met.
2227 */
2228 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002229 {
c_hpothu32490782014-03-14 19:14:34 +05302230 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002231 "%s: Disable split scan", __func__);
2232 pHddCtx->issplitscan_enabled = FALSE;
2233 sme_enable_disable_split_scan(
2234 pHddCtx->hHal,
2235 SME_DISABLE_SPLIT_SCAN,
2236 SME_DISABLE_SPLIT_SCAN);
2237 }
2238 return;
2239}
Jeff Johnson295189b2012-06-20 16:38:30 -07002240