blob: b0a8c4201333ee176b90ca96de03ed5d53ada476 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
c_manjee16126372017-01-16 19:29:30 +05302 * Copyright (c) 2012-2017 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
Sushant Kaushika8073312015-05-04 17:33:52 +053063#include "vos_diag_core_event.h"
Mukul Sharma84f27252014-07-14 18:11:42 +053064#include "vos_utils.h"
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053065#include "sapInternal.h"
Mihir Shete5d148f12014-12-16 17:54:49 +053066#include "wlan_hdd_trace.h"
Katya Nigame7b69a82015-04-28 15:24:06 +053067#include "wlan_qct_wda.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,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +053085 WLANTL_AC_HIGH_PRIO,
Jeff Johnson295189b2012-06-20 16:38:30 -070086};
87
Mihir Shetec8fe71b2014-06-16 15:32:59 +053088#define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
89#define HDD_TX_TIMEOUT_RATELIMIT_BURST 1
Mihir Shetef3473692014-06-27 15:13:20 +053090#define HDD_TX_STALL_SSR_THRESHOLD 5
Mihir Shete0be28772015-02-17 18:42:14 +053091#define HDD_TX_STALL_SSR_THRESHOLD_HIGH 13
Mihir Shete327c2ab2014-11-13 15:17:02 +053092#define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
Sravan Kumar Kairame9d186c2015-11-27 23:37:02 +053093#define HDD_TX_STALL_KICKDXE_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 4
Abhishek Singh837adf22015-10-01 17:37:37 +053094#define HDD_TX_STALL_FATAL_EVENT_THRESHOLD 2
Sushant Kaushik9811d8a2015-10-07 15:56:26 +053095#define EAPOL_MASK 0x8013
96#define EAPOL_M1_BIT_MASK 0x8000
97#define EAPOL_M2_BIT_MASK 0x0001
98#define EAPOL_M3_BIT_MASK 0x8013
99#define EAPOL_M4_BIT_MASK 0x0003
Abhishek Singh837adf22015-10-01 17:37:37 +0530100
Mihir Shetec8fe71b2014-06-16 15:32:59 +0530101
Katya Nigame7b69a82015-04-28 15:24:06 +0530102int gRatefromIdx[] = {
103 10,20,55,100,
104 10,20,55,110,
105 60,90,120,180,240,360,480,540,
106 65,130,195,260,390,520,585,650,
107 72,144,217,289,434,578,650,722,
108 65,130,195,260,390,520,585,650,
109 135,270,405,540,810,1080,1215,1350,
110 150,300,450,600,900,1200,1350,1500,
111 135,270,405,540,810,1080,1215,1350,
112 1350,1350,65,130,195,260,390, 520,
113 585,650,780,1350,1350,1350,1350,1350,
114 1350,1350,1350,1350,655,722,866,1350,
115 1350,1350,135,270,405,540,810,1080,
116 1215,1350,1350,1620,1800,1350,1350,1350,
117 1350,1350,1350,1200,1350,1500,1350,1800,
118 2000,1350, 292,585,877,1170,1755,2340,
119 2632,2925,1350,3510,3900,1350,1350,1350,
120 1350,1350,1350,1350,2925,3250,1350,3900,
121 4333
122 };
Sushant Kaushika8073312015-05-04 17:33:52 +0530123#ifdef FEATURE_WLAN_DIAG_SUPPORT
124#define HDD_EAPOL_PACKET_TYPE_OFFSET (15)
125#define HDD_EAPOL_KEY_INFO_OFFSET (19)
126#define HDD_EAPOL_DEST_MAC_OFFSET (0)
127#define HDD_EAPOL_SRC_MAC_OFFSET (6)
128#endif /* FEATURE_WLAN_DIAG_SUPPORT */
Katya Nigame7b69a82015-04-28 15:24:06 +0530129
130
Mihir Shetec8fe71b2014-06-16 15:32:59 +0530131static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs, \
132 HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
133 HDD_TX_TIMEOUT_RATELIMIT_BURST);
134
Jeff Johnson295189b2012-06-20 16:38:30 -0700135static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700136
137/*---------------------------------------------------------------------------
138 Type declarations
139 -------------------------------------------------------------------------*/
140
141/*---------------------------------------------------------------------------
142 Function definitions and documenation
143 -------------------------------------------------------------------------*/
144
145#ifdef DATA_PATH_UNIT_TEST
146//Utility function to dump an sk_buff
147static void dump_sk_buff(struct sk_buff * skb)
148{
c_hpothu32490782014-03-14 19:14:34 +0530149 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
150 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
151 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
152 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
153 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
154 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
155 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 -0700156
c_hpothu32490782014-03-14 19:14:34 +0530157 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 -0700158 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
159 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu32490782014-03-14 19:14:34 +0530160 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 -0700161 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
162 skb->data[13], skb->data[14], skb->data[15]);
163}
164
165//Function for Unit Test only
166static void transport_thread(hdd_adapter_t *pAdapter)
167{
168 v_U8_t staId;
169 WLANTL_ACEnumType ac = WLANTL_AC_BE;
170 vos_pkt_t *pVosPacket = NULL ;
171 vos_pkt_t dummyPacket;
172 WLANTL_MetaInfoType pktMetaInfo;
173 WLANTL_RxMetaInfoType pktRxMetaInfo;
174 VOS_STATUS status = VOS_STATUS_E_FAILURE;
175
c_hpothub8245442013-11-20 23:41:09 +0530176 if (NULL == pAdapter)
177 {
c_hpothu32490782014-03-14 19:14:34 +0530178 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530179 FL("pAdapter is NULL"));
180 VOS_ASSERT(0);
181 return;
182 }
183
Jeff Johnson295189b2012-06-20 16:38:30 -0700184 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
185 &staId,
186 &ac,
187 &pVosPacket,
188 &pktMetaInfo );
189 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530190 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
191 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192 else
c_hpothu32490782014-03-14 19:14:34 +0530193 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
194 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700195
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700196 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700197 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530198 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
199 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700200 else
c_hpothu32490782014-03-14 19:14:34 +0530201 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
202 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700203
204 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
205 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530206 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
207 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700208 else
c_hpothu32490782014-03-14 19:14:34 +0530209 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
210 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700211
212 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
213 &dummyPacket,
214 staId,
215 &pktRxMetaInfo);
216 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530217 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
218 "%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700219 else
c_hpothu32490782014-03-14 19:14:34 +0530220 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
221 "%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700222
223}
224#endif
225
226
227/**============================================================================
228 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
229
230 @param pAdapter : [in] pointer to adapter context
231 @return : VOS_STATUS_E_FAILURE if any errors encountered
232 : VOS_STATUS_SUCCESS otherwise
233 ===========================================================================*/
234static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
235{
236 VOS_STATUS status = VOS_STATUS_SUCCESS;
237 v_SINT_t i = -1;
238 hdd_list_node_t *anchor = NULL;
239 skb_list_node_t *pktNode = NULL;
240 struct sk_buff *skb = NULL;
241
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530242 pAdapter->isVosLowResource = VOS_FALSE;
243
Mihir Shete5d148f12014-12-16 17:54:49 +0530244 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_FLUSH_TX_QUEUES,
245 pAdapter->sessionId, 0));
246
Jeff Johnson295189b2012-06-20 16:38:30 -0700247 while (++i != NUM_TX_QUEUES)
248 {
249 //Free up any packets in the Tx queue
250 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
251 while (true)
252 {
253 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
254 if(VOS_STATUS_E_EMPTY != status)
255 {
256 pktNode = list_entry(anchor, skb_list_node_t, anchor);
257 skb = pktNode->skb;
258 //TODO
259 //++pAdapter->stats.tx_dropped;
260 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
261 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
262 kfree_skb(skb);
263 continue;
264 }
265 break;
266 }
267 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
268 // backpressure is no longer in effect
269 pAdapter->isTxSuspended[i] = VOS_FALSE;
270 }
271
272 return status;
273}
274
Ravi Joshif9520d62013-10-18 04:11:46 -0700275/**============================================================================
276 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
277 in IBSS mode
278
279 @param pAdapter : [in] pointer to adapter context
280 : [in] Staion Id
281 @return : VOS_STATUS_E_FAILURE if any errors encountered
282 : VOS_STATUS_SUCCESS otherwise
283 ===========================================================================*/
284void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
285{
286 v_U8_t i;
Katya Nigam47528772015-02-11 12:24:49 +0530287 hdd_list_node_t *anchor = NULL;
Ravi Joshi41914632013-10-21 23:02:21 -0700288 skb_list_node_t *pktNode = NULL;
Ravi Joshi41914632013-10-21 23:02:21 -0700289 struct sk_buff *skb = NULL;
Katya Nigam47528772015-02-11 12:24:49 +0530290 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
291 hdd_ibss_peer_info_t *pPeerInfo = &pHddStaCtx->ibss_peer_info;
Ravi Joshif9520d62013-10-18 04:11:46 -0700292
Katya Nigam47528772015-02-11 12:24:49 +0530293 for (i = 0; i < NUM_TX_QUEUES; i ++)
c_hpothub8245442013-11-20 23:41:09 +0530294 {
Katya Nigam47528772015-02-11 12:24:49 +0530295 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
296 while (true)
Ravi Joshif9520d62013-10-18 04:11:46 -0700297 {
Katya Nigam47528772015-02-11 12:24:49 +0530298 if (VOS_STATUS_E_EMPTY !=
299 hdd_list_remove_front(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i],
300 &anchor))
Ravi Joshif9520d62013-10-18 04:11:46 -0700301 {
Katya Nigam47528772015-02-11 12:24:49 +0530302 //If success then we got a valid packet from some AC
303 pktNode = list_entry(anchor, skb_list_node_t, anchor);
Ravi Joshif9520d62013-10-18 04:11:46 -0700304 skb = pktNode->skb;
Katya Nigam47528772015-02-11 12:24:49 +0530305 ++pAdapter->stats.tx_dropped;
306 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
307 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
308 kfree_skb(skb);
309 continue;
Ravi Joshif9520d62013-10-18 04:11:46 -0700310 }
Katya Nigam47528772015-02-11 12:24:49 +0530311 break;
Ravi Joshif9520d62013-10-18 04:11:46 -0700312 }
Katya Nigam47528772015-02-11 12:24:49 +0530313 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
Ravi Joshif9520d62013-10-18 04:11:46 -0700314 }
315}
316
Jeff Johnson295189b2012-06-20 16:38:30 -0700317static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
318{
319 skb_list_node_t *pktNode = NULL;
320 struct sk_buff *skb = NULL;
321 v_SIZE_t size = 0;
322 WLANTL_ACEnumType ac = 0;
323 VOS_STATUS status = VOS_STATUS_E_FAILURE;
324 hdd_list_node_t *anchor = NULL;
325
c_hpothu77731d42014-01-23 13:59:03 +0530326 if (NULL == pAdapter)
327 {
328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
329 FL("pAdapter is NULL"));
330 VOS_ASSERT(0);
331 return NULL;
332 }
333
Jeff Johnson295189b2012-06-20 16:38:30 -0700334 // do we have any packets pending in this AC?
335 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
336 if( size == 0 )
337 {
c_hpothu32490782014-03-14 19:14:34 +0530338 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700339 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700340 return NULL;
341 }
342
343 //Remove the packet from the queue
344 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
345 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
346 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
347
348 if(VOS_STATUS_SUCCESS == status)
349 {
350 //If success then we got a valid packet from some AC
351 pktNode = list_entry(anchor, skb_list_node_t, anchor);
352 skb = pktNode->skb;
353 }
354 else
355 {
c_hpothu32490782014-03-14 19:14:34 +0530356 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700357 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700358 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700359
360 return NULL;
361 }
362
363 // if we are in a backpressure situation see if we can turn the hose back on
364 if ( (pAdapter->isTxSuspended[ac]) &&
365 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
366 {
c_hpothu32490782014-03-14 19:14:34 +0530367 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700368 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700369 pAdapter->isTxSuspended[ac] = VOS_FALSE;
370 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530371 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700372 netif_tx_start_all_queues( pAdapter->dev );
373 }
374
375 return skb;
376}
377
378void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
379{
380 hdd_cfg80211_state_t *cfgState;
381 struct sk_buff* skb;
382 hdd_adapter_t* pMonAdapter = NULL;
383 struct ieee80211_hdr *hdr;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530384 hdd_context_t *pHddCtx;
385 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700386
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530387 ENTER();
Mukul Sharma23a92232014-04-07 18:04:00 +0530388 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700389 {
c_hpothu32490782014-03-14 19:14:34 +0530390 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530391 FL("pAdapter is NULL"));
392 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700393 return;
394 }
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530395 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
396 ret = wlan_hdd_validate_context(pHddCtx);
397 if (0 != ret)
398 {
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530399 return;
400 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700401 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530402 if (pMonAdapter == NULL)
403 {
404 hddLog(VOS_TRACE_LEVEL_ERROR,
405 "%s: pMonAdapter is NULL", __func__);
406 return;
407 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700408 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
409
410 if( NULL != cfgState->buf )
411 {
c_hpothu32490782014-03-14 19:14:34 +0530412 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700413 "%s: Already one MGMT packet Tx going on", __func__);
414 return;
415 }
416
417 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
418
419 if (NULL == skb)
420 {
c_hpothu32490782014-03-14 19:14:34 +0530421 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700422 "%s: No Packet Pending", __func__);
423 return;
424 }
425
426 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
427 if( cfgState->buf == NULL )
428 {
c_hpothu32490782014-03-14 19:14:34 +0530429 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700430 "%s: Failed to Allocate memory", __func__);
431 goto fail;
432 }
433
434 cfgState->len = skb->len;
435
436 vos_mem_copy( cfgState->buf, skb->data, skb->len);
437
438 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800439 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700440
441 hdr = (struct ieee80211_hdr *)skb->data;
442 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
443 == HDD_FRAME_TYPE_MGMT )
444 {
445 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
446 == HDD_FRAME_SUBTYPE_DEAUTH )
447 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530448 struct tagCsrDelStaParams delStaParams;
449
Sushant Kaushik4cd28f62014-12-26 14:23:50 +0530450 WLANSAP_PopulateDelStaParams(hdr->addr1,
451 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530452 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
453
454 hdd_softap_sta_deauth(pAdapter, &delStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 goto mgmt_handled;
456 }
457 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
458 == HDD_FRAME_SUBTYPE_DISASSOC )
459 {
460 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
461 goto mgmt_handled;
462 }
463 }
c_hpothu32490782014-03-14 19:14:34 +0530464 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700465 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
466
Jeff Johnson43971f52012-07-17 12:26:56 -0700467 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700469 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700470 {
c_hpothu32490782014-03-14 19:14:34 +0530471 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 "%s: WLANSAP_SendAction returned fail", __func__);
473 hdd_sendActionCnf( pAdapter, FALSE );
474 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530475 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700476 return;
477
478mgmt_handled:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530479 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700480 hdd_sendActionCnf( pAdapter, TRUE );
481 return;
482fail:
483 kfree_skb(pAdapter->skb_to_tx);
484 pAdapter->skb_to_tx = NULL;
485 return;
486}
487
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530488void __hdd_mon_tx_work_queue(struct work_struct *work)
Jeff Johnson295189b2012-06-20 16:38:30 -0700489{
490 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
491 hdd_mon_tx_mgmt_pkt(pAdapter);
492}
493
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530494void hdd_mon_tx_work_queue(struct work_struct *work)
495{
496 vos_ssr_protect(__func__);
497 __hdd_mon_tx_work_queue(work);
498 vos_ssr_unprotect(__func__);
499}
500
Jeff Johnson295189b2012-06-20 16:38:30 -0700501int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
502{
Katya Nigame7b69a82015-04-28 15:24:06 +0530503 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
504 "%s: Packet Rcvd at Monitor interface,"
505 " Dropping the packet",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700506 kfree_skb(skb);
507 return NETDEV_TX_OK;
508}
Dino Mycled9b7cc12014-09-04 18:43:07 +0530509
510/**============================================================================
511 @brief hdd_dhcp_pkt_info() -
512 Function to log DHCP pkt info
513
514 @param skb : [in] pointer to OS packet (sk_buff)
515 @return : None
516 ===========================================================================*/
517
518void hdd_dhcp_pkt_info(struct sk_buff *skb)
519{
520 /* port no 67 (0x43) or 68 (0x44) */
521
522 if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_REQUEST_MSG)
523 hddLog(VOS_TRACE_LEVEL_INFO, FL("Request"));
524 else if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_RESPONSE_MSG)
525 hddLog(VOS_TRACE_LEVEL_INFO, FL("Response"));
526 else
527 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP invalid"));
528
529 hddLog(VOS_TRACE_LEVEL_INFO,
530 FL("DHCP Dest Addr: %pM Src Addr %pM "
531 " source port : %d, dest port : %d"),
532 skb->data, (skb->data + 6),
533 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))),
534 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))));
535
536 if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
537 (skb->data[DHCP_OPTION53_LENGTH_OFFSET] == DHCP_OPTION53_LENGTH)) {
538
539 switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
540 case DHCPDISCOVER:
541 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP DISCOVER"));
542 break;
543 case DHCPREQUEST:
544 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP REQUEST"));
545 break;
546 case DHCPOFFER:
547 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP OFFER"));
548 break;
549 case DHCPACK:
550 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP ACK"));
551 break;
552 case DHCPNAK:
553 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP NACK"));
554 break;
555 case DHCPRELEASE:
556 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP RELEASE"));
557 break;
558 case DHCPINFORM:
559 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP INFORM"));
560 break;
561
562 default:
563 hddLog(VOS_TRACE_LEVEL_INFO,
564 "%s: DHCP Not Defined OPTION53 : %d", __func__,
565 skb->data[DHCP_OPTION53_STATUS_OFFSET]);
566 }
567 }
568}
569
570/**============================================================================
571 @brief hdd_dump_dhcp_pkt() -
572 Function to dump DHCP packets in TX and RX path.
573
574 @param skb : [in] pointer to OS packet (sk_buff)
575 @param path : [in] bool indicating TX/RX path
576 @return : None
577 ===========================================================================*/
578void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path)
579{
580
581 if ((ntohs(*((u16*)((u8*)skb->data + ETH_TYPE_OFFSET)))
582 == ETH_TYPE_IP_PKT) ||
583 (ntohs(*((u8*)skb->data + PROTOCOL_OFFSET)) == UDP_PROTOCOL)) {
584
585 /* IP protocol 12 bytes of mac addresses in 802.3 header */
586 if ( ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
587 BOOTP_SERVER_PORT ||
588 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
589 BOOTP_CLIENT_PORT ||
590 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
591 BOOTP_SERVER_PORT ||
592 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
593 BOOTP_CLIENT_PORT ) {
594
595 if (path == TX_PATH) {
596 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP TX PATH"));
597 } else {
598 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP RX PATH"));
599 }
600
601 hdd_dhcp_pkt_info(skb);
602 }
603 }
604}
605
Jeff Johnson295189b2012-06-20 16:38:30 -0700606/**============================================================================
Katya Nigam77fcf582015-02-09 16:48:24 +0530607 @brief hdd_ibss_hard_start_xmit() - Function registered with the Linux OS for
608 transmitting packets in case of IBSS. There are 2 versions of this function.
609 One that uses locked queue and other that uses lockless queues. Both have been
610 retained to do some performance testing
611
612 @param skb : [in] pointer to OS packet (sk_buff)
613 @param dev : [in] pointer to network device
614
615 @return : NET_XMIT_DROP if packets are dropped
616 : NET_XMIT_SUCCESS if packet is enqueued succesfully
617 ===========================================================================*/
618 int hdd_ibss_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
619 {
620 VOS_STATUS status;
621 WLANTL_ACEnumType ac;
622 sme_QosWmmUpType up;
623 skb_list_node_t *pktNode = NULL;
624 hdd_list_node_t *anchor = NULL;
625 v_SIZE_t pktListSize = 0;
626 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
627 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
628 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
629 hdd_ibss_peer_info_t * pPeerInfo;
630 v_U8_t STAId = WLAN_MAX_STA_COUNT;
631 v_BOOL_t txSuspended = VOS_FALSE;
632 struct sk_buff *skb1;
633 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
634
635 if (NULL == pHddCtx || NULL == pHddStaCtx) {
636 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
637 "%s HDD context is NULL", __func__);
638 return NETDEV_TX_BUSY;
639 }
640 pPeerInfo = &pHddStaCtx->ibss_peer_info;
641 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
642
643 //Get TL AC corresponding to Qdisc queue index/AC.
644 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
645
646 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
647 {
648 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
649 "%s: Tx frame in disconnected state in IBSS mode", __func__);
650 ++pAdapter->stats.tx_dropped;
651 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
652 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
653 kfree_skb(skb);
654 return NETDEV_TX_OK;
655 }
656
Nirav Shah7e3c8132015-06-22 23:51:42 +0530657 STAId = hdd_sta_id_find_from_mac_addr(pAdapter, pDestMacAddress);
Katya Nigam77fcf582015-02-09 16:48:24 +0530658 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
659 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
660 vos_is_macaddr_group(pDestMacAddress)))
661 {
662 STAId = IBSS_BROADCAST_STAID;
663 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
664 "%s: BC/MC packet", __func__);
665 }
666 else if (STAId >= HDD_MAX_NUM_IBSS_STA)
667 {
668 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
669 "%s: Received Unicast frame with invalid staID", __func__);
670 ++pAdapter->stats.tx_dropped;
671 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
672 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
673 kfree_skb(skb);
674 return NETDEV_TX_OK;
675 }
676
677 //user priority from IP header, which is already extracted and set from
678 //select_queue call back function
679 up = skb->priority;
680 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
681
682 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
683 "%s: Classified as ac %d up %d", __func__, ac, up);
684
685 if ( pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP )
686 {
687 hdd_dump_dhcp_pkt(skb, TX_PATH);
688 }
689
690 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
691 hdd_list_size(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
692 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
693 {
694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
695 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
696 pPeerInfo->ibssStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
697 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
698 txSuspended = VOS_TRUE;
699 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
701 "%s: TX queue full for AC=%d Disable OS TX queue",
702 __func__, ac );
703 return NETDEV_TX_BUSY;
704 }
705
706 /* If 3/4th of the max queue size is used then enable the flag.
707 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
708 if (WLANTL_AC_BE == ac)
709 {
710 if (pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
711 {
712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
713 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
714 pAdapter->isVosLowResource = VOS_TRUE;
715 }
716 else
717 {
718 pAdapter->isVosLowResource = VOS_FALSE;
719 }
720 }
721
722 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
723
724 //Use the skb->cb field to hold the list node information
725 pktNode = (skb_list_node_t *)&skb->cb;
726
727 //Stick the OS packet inside this node.
728 pktNode->skb = skb;
729
730 //Stick the User Priority inside this node
731 pktNode->userPriority = up;
732
733 INIT_LIST_HEAD(&pktNode->anchor);
734
735 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
736 status = hdd_list_insert_back_size( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac],
737 &pktNode->anchor, &pktListSize );
738 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
739 if ( !VOS_IS_STATUS_SUCCESS( status ) )
740 {
741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
742 "%s:Insert Tx queue failed. Pkt dropped", __func__);
743 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
744 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
745 ++pAdapter->stats.tx_dropped;
746 kfree_skb(skb);
747 return NETDEV_TX_OK;
748 }
749
750 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
751 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
752 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
753
754 if (1 == pktListSize)
755 {
756 //Let TL know we have a packet to send for this AC
757 status = WLANTL_STAPktPending( pHddCtx->pvosContext, STAId, ac );
758
759 if ( !VOS_IS_STATUS_SUCCESS( status ) )
760 {
761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
762 "%s: Failed to signal TL for AC=%d STAId =%d",
763 __func__, ac, STAId );
764
765 /* Remove the packet from queue. It must be at the back of the queue, as TX thread
766 * cannot preempt us in the middle as we are in a soft irq context.
767 * Also it must be the same packet that we just allocated.
768 */
769 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
770 status = hdd_list_remove_back( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &anchor);
771 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
772 /* Free the skb only if we are able to remove it from the list.
773 * If we are not able to retrieve it from the list it means that
774 * the skb was pulled by TX Thread and is use so we should not free
775 * it here
776 */
777 if (VOS_IS_STATUS_SUCCESS(status))
778 {
779 pktNode = list_entry(anchor, skb_list_node_t, anchor);
780 skb1 = pktNode->skb;
781 kfree_skb(skb1);
782 }
783 ++pAdapter->stats.tx_dropped;
784 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
785 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
786 return NETDEV_TX_OK;
787 }
788 }
789
790 dev->trans_start = jiffies;
791
792 return NETDEV_TX_OK;
793 }
794
795/**============================================================================
SaidiReddy Yenuga18d77a62016-10-04 20:26:22 +0530796 @brief __hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700797 transmitting packets. There are 2 versions of this function. One that uses
798 locked queue and other that uses lockless queues. Both have been retained to
799 do some performance testing
800
801 @param skb : [in] pointer to OS packet (sk_buff)
802 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530803
Jeff Johnson295189b2012-06-20 16:38:30 -0700804 @return : NET_XMIT_DROP if packets are dropped
805 : NET_XMIT_SUCCESS if packet is enqueued succesfully
806 ===========================================================================*/
SaidiReddy Yenuga18d77a62016-10-04 20:26:22 +0530807int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -0700808{
809 VOS_STATUS status;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530810 WLANTL_ACEnumType qid, ac;
Jeff Johnson295189b2012-06-20 16:38:30 -0700811 sme_QosWmmUpType up;
812 skb_list_node_t *pktNode = NULL;
813 hdd_list_node_t *anchor = NULL;
814 v_SIZE_t pktListSize = 0;
815 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
816 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700817 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700818 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Dino Mycled9b7cc12014-09-04 18:43:07 +0530819 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700820 v_BOOL_t txSuspended = VOS_FALSE;
Mihir Shetef8f74532014-12-04 11:53:34 +0530821 struct sk_buff *skb1;
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +0530822 v_BOOL_t arp_pkt;
Jeff Johnson295189b2012-06-20 16:38:30 -0700823
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530824 if (NULL == pHddCtx) {
825 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
826 "%s HDD context is NULL", __func__);
827 return NETDEV_TX_BUSY;
828 }
829
Jeff Johnson295189b2012-06-20 16:38:30 -0700830 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
831
Ravi Joshif9520d62013-10-18 04:11:46 -0700832 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530833 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700834 "%s is called when netif TX %d is disabled",
835 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530836 return NETDEV_TX_BUSY;
837 }
838
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +0530839 arp_pkt = vos_is_arp_pkt(skb, false);
840
841 if (arp_pkt)
842 {
843 ++pAdapter->hdd_stats.hddArpStats.txCount;
844 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
845 "%s :ARP packet received form net_dev", __func__);
846 }
847
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530848 //Get TL Q index corresponding to Qdisc queue index/AC.
849 qid = hdd_QdiscAcToTlAC[skb->queue_mapping];
850 ac = qid;
851
852 if (qid == WLANTL_AC_HIGH_PRIO)
853 {
854 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
855 "%s It must be a Eapol/Wapi/DHCP packet device_mode:%d",
856 __func__, pAdapter->device_mode);
857 ac = hddWmmUpToAcMap[skb->priority];
858 }
Ravi Joshicc57ed42013-10-12 16:31:25 -0700859
c_hpothu851d9862015-01-19 18:39:06 +0530860 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
861 {
862 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
863 FL("Tx frame in not associated state in %d context"),
864 pAdapter->device_mode);
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +0530865
866 if (arp_pkt)
867 {
868 ++pAdapter->hdd_stats.hddArpStats.txDropped;
869 pAdapter->hdd_stats.hddArpStats.reason = HDD_TX_FRAME_IN_NOT_ASSOCIATED_STATE;
870 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
871 "%s :Tx frame in not associated state, ARP packet Dropped ",
872 __func__);
873 }
c_hpothu851d9862015-01-19 18:39:06 +0530874 ++pAdapter->stats.tx_dropped;
875 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530876 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
c_hpothu851d9862015-01-19 18:39:06 +0530877 kfree_skb(skb);
878 return NETDEV_TX_OK;
879 }
Shailender Karmuchia734f332013-04-19 14:02:48 -0700880 STAId = pHddStaCtx->conn_info.staId[0];
Jeff Johnson295189b2012-06-20 16:38:30 -0700881
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530882 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700883 //select_queue call back function
884 up = skb->priority;
885
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530886 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -0700887
888#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530889 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700890 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700891#endif // HDD_WMM_DEBUG
892
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530893 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
Mukul Sharma84f27252014-07-14 18:11:42 +0530894 {
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530895 vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
Mukul Sharma84f27252014-07-14 18:11:42 +0530896 }
Mukul Sharma84f27252014-07-14 18:11:42 +0530897
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530898 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700899 /*CR 463598,384996*/
900 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
901 *We check for +1 in the logic,to take care of Zero count which
902 *occurs very frequently in low traffic cases */
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530903 if((pAdapter->wmm_tx_queue[qid].count + 1) % 10 == 0)
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700904 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700905 /* 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 -0700906 * 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 +0530907 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 -0700908
Ravi Joshi8a934352013-09-25 16:46:58 -0700909 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530910 STAId, qid
Ravi Joshi8a934352013-09-25 16:46:58 -0700911 );
912 if ( !VOS_IS_STATUS_SUCCESS( status ) )
913 {
c_hpothu32490782014-03-14 19:14:34 +0530914 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700915 "%s: WLANTL_STAPktPending() returned error code %d",
916 __func__, status);
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +0530917
918 if (arp_pkt)
919 {
920 ++pAdapter->hdd_stats.hddArpStats.txDropped;
921 pAdapter->hdd_stats.hddArpStats.reason = HDD_WLANTL_STAPKTPENDING_RETURNED_ERROR_CODE;
922 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
923 "%s:ARP Packet Dropped WLANTL_STAPktPending returned error %d",
924 __func__, status);
925 }
Ravi Joshicc57ed42013-10-12 16:31:25 -0700926 ++pAdapter->stats.tx_dropped;
927 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530928 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Ravi Joshi8a934352013-09-25 16:46:58 -0700929 kfree_skb(skb);
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530930 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Ravi Joshi8a934352013-09-25 16:46:58 -0700931 return NETDEV_TX_OK;
932 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700933 }
Sravan Kumar Kairam7ce69332017-02-15 15:41:43 +0530934
935 if (pHddCtx->bad_sta[STAId]) {
936 hdd_list_node_t *anchor = NULL;
937 skb_list_node_t *pktNode = NULL;
938 struct sk_buff *fskb = NULL;
939
940 if (pAdapter->wmm_tx_queue[qid].count >=
941 pAdapter->wmm_tx_queue[qid].max_size / 2) {
942 hdd_list_remove_front(&pAdapter->wmm_tx_queue[qid],
943 &anchor);
944 pktNode = list_entry(anchor, skb_list_node_t, anchor);
945 fskb = pktNode->skb;
946 kfree_skb(fskb);
947 ++pAdapter->stats.tx_dropped;
948 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
949 }
950 }
951
Jeff Johnson295189b2012-06-20 16:38:30 -0700952 //If we have already reached the max queue size, disable the TX queue
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530953 if ( pAdapter->wmm_tx_queue[qid].count == pAdapter->wmm_tx_queue[qid].max_size)
Jeff Johnson295189b2012-06-20 16:38:30 -0700954 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700955 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530956 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[qid];
957 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for QId %d"), qid);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700958 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530959 pAdapter->isTxSuspended[qid] = VOS_TRUE;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700960 txSuspended = VOS_TRUE;
Mihir Shete5d148f12014-12-16 17:54:49 +0530961 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_NETDEV,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530962 pAdapter->sessionId, qid));
Jeff Johnson295189b2012-06-20 16:38:30 -0700963 }
964
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530965 /* If 3/4th of the max queue size is used then enable the flag.
966 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530967 if (WLANTL_AC_BE == qid)
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530968 {
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530969 if (pAdapter->wmm_tx_queue[qid].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530970 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530971 pAdapter->isVosLowResource = VOS_TRUE;
972 }
973 else
974 {
975 pAdapter->isVosLowResource = VOS_FALSE;
976 }
977 }
978
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530979 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530980
Sachin Ahuja8c65f382014-12-12 15:34:21 +0530981 if (( NULL != pHddCtx ) &&
982 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +0530983 {
984 hdd_dump_dhcp_pkt(skb, TX_PATH);
985 }
986
Jeff Johnson295189b2012-06-20 16:38:30 -0700987 if (VOS_TRUE == txSuspended)
988 {
c_hpothu32490782014-03-14 19:14:34 +0530989 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530990 "%s: TX queue full for QId=%d Disable OS TX queue",
991 __func__, qid );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530992 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 }
994
995 //Use the skb->cb field to hold the list node information
996 pktNode = (skb_list_node_t *)&skb->cb;
997
998 //Stick the OS packet inside this node.
999 pktNode->skb = skb;
1000
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +05301001 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 pktNode->userPriority = up;
1003
1004
1005 INIT_LIST_HEAD(&pktNode->anchor);
1006
1007 //Insert the OS packet into the appropriate AC queue
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301008 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
1009 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[qid], &pktNode->anchor, &pktListSize );
1010 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001011
1012 if ( !VOS_IS_STATUS_SUCCESS( status ) )
1013 {
c_hpothu32490782014-03-14 19:14:34 +05301014 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05301015
1016 if (arp_pkt)
1017 {
1018 ++pAdapter->hdd_stats.hddArpStats.txDropped;
1019 pAdapter->hdd_stats.hddArpStats.reason = HDD_INSERT_TX_QUEUE_FAILED;
1020 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1021 "%s:Insert Tx queue failed. ARP packet dropped", __func__);
1022 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001023 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301024 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -07001025 ++pAdapter->stats.tx_dropped;
1026 kfree_skb(skb);
1027 return NETDEV_TX_OK;
1028 }
1029
1030 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301031 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[qid];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001032 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001033
Kiet Lamf040f472013-11-20 21:15:23 +05301034 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
1035 {
1036 /* Function which will determine acquire admittance for a
1037 * WMM AC is required or not based on psb configuration done
1038 * in the framework
1039 */
1040 hdd_wmm_acquire_access_required(pAdapter, ac);
1041 }
1042
Jeff Johnson295189b2012-06-20 16:38:30 -07001043 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +05301044 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
1045 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001046 {
1047 granted = VOS_TRUE;
1048 }
1049 else
1050 {
1051 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +05301052 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001053 }
Nirav Shah4f765af2015-01-21 19:51:30 +05301054
1055 if ( (granted && ( pktListSize == 1 )) ||
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301056 (qid == WLANTL_AC_HIGH_PRIO))
Jeff Johnson295189b2012-06-20 16:38:30 -07001057 {
1058 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +05301059 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -07001060 status = WLANTL_STAPktPending(
1061 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301062 STAId, qid );
Jeff Johnson295189b2012-06-20 16:38:30 -07001063 if ( !VOS_IS_STATUS_SUCCESS( status ) )
1064 {
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301065 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
1066 "%s: Failed to signal TL for QId=%d", __func__, qid );
Jeff Johnson295189b2012-06-20 16:38:30 -07001067
1068 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
1069 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301070 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
1071 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[qid], &anchor );
1072 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Mihir Shetef8f74532014-12-04 11:53:34 +05301073 /* Free the skb only if we are able to remove it from the list.
1074 * If we are not able to retrieve it from the list it means that
1075 * the skb was pulled by TX Thread and is use so we should not free
1076 * it here
1077 */
1078 if (VOS_IS_STATUS_SUCCESS(status))
1079 {
1080 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1081 skb1 = pktNode->skb;
1082 kfree_skb(skb1);
1083 }
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05301084
1085 if (arp_pkt)
1086 {
1087 ++pAdapter->hdd_stats.hddArpStats.txDropped;
1088 pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILED_TO_SIGNAL_TL;
1089 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1090 "%s: ARP packet Dropped : Failed to signal TL for QId=%d",
1091 __func__, qid );
1092 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001093 ++pAdapter->stats.tx_dropped;
1094 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301095 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -07001096 return NETDEV_TX_OK;
1097 }
1098 }
1099
1100 dev->trans_start = jiffies;
1101
1102 return NETDEV_TX_OK;
1103}
1104
SaidiReddy Yenuga18d77a62016-10-04 20:26:22 +05301105int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
1106{
1107 int ret;
1108 vos_ssr_protect(__func__);
1109 ret = __hdd_hard_start_xmit(skb, dev);
1110 vos_ssr_unprotect(__func__);
1111 return ret;
1112}
1113
Jeff Johnson295189b2012-06-20 16:38:30 -07001114/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -07001115 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
1116
1117 @param pHddStaCtx : [in] pointer to HDD Station Context
1118 pMacAddress [in] pointer to Peer Mac address
1119 staID [out] pointer to Station Index
1120 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
1121 ===========================================================================*/
1122
1123VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1124{
1125 v_U8_t idx;
1126
1127 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
1128 {
1129 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
1130 pMacAddress, sizeof(v_MACADDR_t)))
1131 {
1132 *staId = pHddStaCtx->conn_info.staId[idx];
1133 return VOS_STATUS_SUCCESS;
1134 }
1135 }
1136
1137 return VOS_STATUS_E_FAILURE;
1138}
1139
1140/**============================================================================
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301141 @brief __hdd_tx_timeout() - Function handles timeout during transmission.
Jeff Johnson295189b2012-06-20 16:38:30 -07001142
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301143 @param dev : [in] pointer to network device
Jeff Johnson295189b2012-06-20 16:38:30 -07001144 @return : None
1145 ===========================================================================*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301146void __hdd_tx_timeout(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001147{
Ravi Joshicc57ed42013-10-12 16:31:25 -07001148 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mihir Shete0be28772015-02-17 18:42:14 +05301149 hdd_context_t *pHddCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001150 struct netdev_queue *txq;
Mihir Shete0be28772015-02-17 18:42:14 +05301151 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001152 int i = 0;
Mukul Sharma4b322632015-02-28 20:21:43 +05301153 int status = 0;
Mukul Sharma42b3d432014-10-16 16:13:40 +05301154 v_ULONG_t diff_in_jiffies = 0;
mukul sharma4cbba382015-08-14 17:18:49 +05301155 hdd_station_ctx_t *pHddStaCtx = NULL;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001156
Mihir Shetef3473692014-06-27 15:13:20 +05301157 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301158 "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu",
1159 __func__,jiffies,dev->trans_start);
Mihir Shetef3473692014-06-27 15:13:20 +05301160
c_hpothub8245442013-11-20 23:41:09 +05301161 if ( NULL == pAdapter )
1162 {
c_hpothu32490782014-03-14 19:14:34 +05301163 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301164 FL("pAdapter is NULL"));
1165 VOS_ASSERT(0);
1166 return;
1167 }
1168
Mihir Shete0be28772015-02-17 18:42:14 +05301169 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Mukul Sharma4b322632015-02-28 20:21:43 +05301170 status = wlan_hdd_validate_context(pHddCtx);
1171 if (status !=0 )
Mihir Shete0be28772015-02-17 18:42:14 +05301172 {
Mukul Sharma4b322632015-02-28 20:21:43 +05301173 return;
Mihir Shete0be28772015-02-17 18:42:14 +05301174 }
1175
mukul sharma4cbba382015-08-14 17:18:49 +05301176 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1177 if ( NULL == pHddStaCtx )
1178 {
1179 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1180 FL("pHddStaCtx is NULL"));
1181 return;
1182 }
1183
Mihir Shetef3473692014-06-27 15:13:20 +05301184 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
1185
Jeff Johnson295189b2012-06-20 16:38:30 -07001186 //Getting here implies we disabled the TX queues for too long. Queues are
1187 //disabled either because of disassociation or low resource scenarios. In
1188 //case of disassociation it is ok to ignore this. But if associated, we have
1189 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -07001190
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301191 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001192 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
1193 pAdapter->wmm_tx_queue[0].count,
1194 pAdapter->wmm_tx_queue[1].count,
1195 pAdapter->wmm_tx_queue[2].count,
1196 pAdapter->wmm_tx_queue[3].count);
1197
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301198 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001199 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
1200 pAdapter->isTxSuspended[0],
1201 pAdapter->isTxSuspended[1],
1202 pAdapter->isTxSuspended[2],
1203 pAdapter->isTxSuspended[3]);
1204
Mihir Shete0be28772015-02-17 18:42:14 +05301205 for (i = 0; i < dev->num_tx_queues; i++)
Ravi Joshicc57ed42013-10-12 16:31:25 -07001206 {
1207 txq = netdev_get_tx_queue(dev, i);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301208 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301209 "Queue%d status: %d txq->trans_start %lu",
1210 i, netif_tx_queue_stopped(txq),txq->trans_start);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001211 }
1212
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301213 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001214 "carrier state: %d", netif_carrier_ok(dev));
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301215
Mihir Shetef3473692014-06-27 15:13:20 +05301216 /* continuousTxTimeoutCount will be reset whenever TL fetches packet
1217 * from HDD
1218 */
1219 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
1220
Mukul Sharma42b3d432014-10-16 16:13:40 +05301221 diff_in_jiffies = jiffies - pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut;
1222 if((pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount > 1)&&
1223 ((diff_in_jiffies) > (HDD_TX_TIMEOUT * 2 ))
1224 )
1225 {
1226 /*
1227 * In Open security case when there is no traffic is running, it may possible
1228 * tx time-out may once happen and later we recovered then we need to
1229 * reset the continuousTxTimeoutCount because it is only getting modified
1230 * when traffic is running. So if over a period of time if this count reaches
1231 * to HDD_TX_STALL_SSR_THRESHOLD then host is triggering false subsystem restart.
1232 * so in genuine Tx Time out case kernel will call the tx time-out back to back at
1233 * interval of HDD_TX_TIMEOUT.So now we are checking if previous TX TIME out was
1234 * occurred more then twice of HDD_TX_TIMEOUT back then we may recovered here.
1235 */
1236 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1237 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1238 FL("This is false alarm so resetting the continuousTxTimeoutCount"));
1239 }
1240
1241 //update last jiffies after the check
1242 pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut = jiffies;
1243
mukul sharma4cbba382015-08-14 17:18:49 +05301244 if (!pHddStaCtx->conn_info.uIsAuthenticated) {
1245 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1246 FL("TL is not in authenticated state so skipping SSR"));
Karthick S79bbe822015-07-14 15:28:08 +05301247 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1248 goto print_log;
1249 }
Mihir Shete327c2ab2014-11-13 15:17:02 +05301250 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
Sravan Kumar Kairame9d186c2015-11-27 23:37:02 +05301251 HDD_TX_STALL_KICKDXE_THRESHOLD)
1252 {
1253 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1254 "%s: Request Kick DXE for recovery",__func__);
1255 WLANTL_TLDebugMessage(WLANTL_DEBUG_KICKDXE);
1256 }
1257 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
Mihir Shete327c2ab2014-11-13 15:17:02 +05301258 HDD_TX_STALL_RECOVERY_THRESHOLD)
1259 {
1260 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1261 "%s: Request firmware for recovery",__func__);
1262 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
1263 }
Ganesh Kondabattinic86625a2015-11-27 15:08:40 +05301264
1265 /*
1266 * This function is getting called in softirq context, So don't hold
1267 * any mutex.
1268 * There is no harm here in not holding the mutex as long as we are
1269 * not accessing the pRemainChanCtx contents.
1270 */
Mihir Shete0be28772015-02-17 18:42:14 +05301271 pRemainChanCtx = hdd_get_remain_on_channel_ctx(pHddCtx);
1272 if (!pRemainChanCtx)
Mihir Shetef3473692014-06-27 15:13:20 +05301273 {
Mihir Shete0be28772015-02-17 18:42:14 +05301274 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1275 HDD_TX_STALL_SSR_THRESHOLD)
1276 {
1277 // Driver could not recover, issue SSR
1278 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1279 "%s: Cannot recover from Data stall Issue SSR",
1280 __func__);
1281 WLANTL_FatalError();
Mukul Sharma987bef02015-11-16 20:04:54 +05301282 // reset count after issuing the SSR
1283 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Mihir Shete0be28772015-02-17 18:42:14 +05301284 return;
1285 }
1286 }
1287 else
1288 {
1289 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1290 "Remain on channel in progress");
1291 /* The supplicant can retry "P2P Invitation Request" for 120 times
1292 * and so there is a possbility that we can remain off channel for
1293 * the entire duration of these retries(which can be max 60sec).
1294 * If we encounter such a case, let us not trigger SSR after 30sec
1295 * but wait for 60sec to let the device go on home channel and start
1296 * tx. If tx does not start within 70sec we will issue SSR.
1297 */
1298 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1299 HDD_TX_STALL_SSR_THRESHOLD_HIGH)
1300 {
1301 // Driver could not recover, issue SSR
1302 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1303 "%s: Cannot recover from Data stall Issue SSR",
1304 __func__);
1305 WLANTL_FatalError();
1306 return;
1307 }
Mihir Shetef3473692014-06-27 15:13:20 +05301308 }
1309
Karthick S79bbe822015-07-14 15:28:08 +05301310print_log:
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301311 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
1312 * every 5sec. The TL debug spits out a lot of information on the
1313 * serial console, if it is called every time *hdd_tx_timeout* is
1314 * called then we may get a watchdog bite on the Application
1315 * processor, so ratelimit the TL debug logs.
1316 */
1317 if (__ratelimit(&hdd_tx_timeout_rs))
1318 {
1319 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +05301320 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301321 }
Abhishek Singh837adf22015-10-01 17:37:37 +05301322 /* Call fatal event if data stall is for
1323 * HDD_TX_STALL_FATAL_EVENT_THRESHOLD times
1324 */
1325 if (HDD_TX_STALL_FATAL_EVENT_THRESHOLD ==
1326 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount)
1327 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
1328 WLAN_LOG_INDICATOR_HOST_DRIVER,
1329 WLAN_LOG_REASON_DATA_STALL,
1330 FALSE, TRUE);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301331}
Jeff Johnson295189b2012-06-20 16:38:30 -07001332
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301333/**============================================================================
1334 @brief hdd_tx_timeout() - Function called by OS if there is any
1335 timeout during transmission. Since HDD simply enqueues packet
1336 and returns control to OS right away, this would never be invoked
1337
1338 @param dev : [in] pointer to network device
1339 @return : None
1340 ===========================================================================*/
1341void hdd_tx_timeout(struct net_device *dev)
1342{
1343 vos_ssr_protect(__func__);
1344 __hdd_tx_timeout(dev);
1345 vos_ssr_unprotect(__func__);
1346}
Jeff Johnson295189b2012-06-20 16:38:30 -07001347
1348/**============================================================================
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301349 @brief __hdd_stats() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -07001350 device TX/RX statistic
1351
1352 @param dev : [in] pointer to Libra network device
1353
1354 @return : pointer to net_device_stats structure
1355 ===========================================================================*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301356struct net_device_stats* __hdd_stats(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001357{
1358 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +05301359
1360 if ( NULL == pAdapter )
1361 {
c_hpothu32490782014-03-14 19:14:34 +05301362 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301363 FL("pAdapter is NULL"));
1364 VOS_ASSERT(0);
1365 return NULL;
1366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001367
1368 return &pAdapter->stats;
1369}
1370
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301371struct net_device_stats* hdd_stats(struct net_device *dev)
1372{
1373 struct net_device_stats* dev_stats;
1374
1375 vos_ssr_protect(__func__);
1376 dev_stats = __hdd_stats(dev);
1377 vos_ssr_unprotect(__func__);
1378
1379 return dev_stats;
1380}
Jeff Johnson295189b2012-06-20 16:38:30 -07001381
1382/**============================================================================
Katya Nigam1fd24402015-02-16 14:52:19 +05301383 @brief hdd_ibss_init_tx_rx() - Init function to initialize Tx/RX
1384 modules in HDD
1385
1386 @param pAdapter : [in] pointer to adapter context
1387 @return : VOS_STATUS_E_FAILURE if any errors encountered
1388 : VOS_STATUS_SUCCESS otherwise
1389 ===========================================================================*/
1390void hdd_ibss_init_tx_rx( hdd_adapter_t *pAdapter )
1391{
1392 v_U8_t i;
1393 v_U8_t STAId = 0;
1394 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1395 hdd_ibss_peer_info_t *pPeerInfo = &pHddStaCtx->ibss_peer_info;
1396 v_U8_t pACWeights[] = {
1397 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
1398 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
1399 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
1400 HDD_SOFTAP_VO_WEIGHT_DEFAULT
1401 };
1402
1403 pAdapter->isVosOutOfResource = VOS_FALSE;
1404 pAdapter->isVosLowResource = VOS_FALSE;
1405
1406 // Since SAP model is used for IBSS also. Using same queue length as in SAP.
1407 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
1408 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
1409 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
1410 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
1411
1412 for (STAId = 0; STAId < HDD_MAX_NUM_IBSS_STA; STAId++)
1413 {
1414 vos_mem_zero(&pPeerInfo->ibssStaInfo[STAId], sizeof(hdd_ibss_station_info_t));
1415 for (i = 0; i < NUM_TX_QUEUES; i ++)
1416 {
1417 hdd_list_init(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1418 }
1419 }
1420
1421 /* Update the AC weights suitable for SoftAP mode of operation */
1422 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
1423}
1424
1425/**============================================================================
1426 @brief hdd_ibss_deinit_tx_rx() - Deinit function to clean up Tx/RX
1427 modules in HDD
1428
1429 @param pAdapter : [in] pointer to adapter context..
1430 @return : VOS_STATUS_E_FAILURE if any errors encountered.
1431 : VOS_STATUS_SUCCESS otherwise
1432 ===========================================================================*/
1433VOS_STATUS hdd_ibss_deinit_tx_rx( hdd_adapter_t *pAdapter )
1434{
1435 VOS_STATUS status = VOS_STATUS_SUCCESS;
1436 v_U8_t STAId = 0;
1437 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1438 hdd_ibss_peer_info_t * pPeerInfo = &pHddStaCtx->ibss_peer_info;
1439 hdd_list_node_t *anchor = NULL;
1440 skb_list_node_t *pktNode = NULL;
1441 struct sk_buff *skb = NULL;
1442 v_SINT_t i = -1;
1443
1444 for (STAId = 0; STAId < HDD_MAX_NUM_IBSS_STA; STAId++)
1445 {
1446 if (VOS_FALSE == pPeerInfo->ibssStaInfo[STAId].isUsed)
1447 {
1448 continue;
1449 }
1450 for (i = 0; i < NUM_TX_QUEUES; i ++)
1451 {
1452 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
1453 while (true)
1454 {
1455 status = hdd_list_remove_front ( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i], &anchor);
1456
1457 if (VOS_STATUS_E_EMPTY != status)
1458 {
1459 //If success then we got a valid packet from some AC
1460 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1461 skb = pktNode->skb;
1462 ++pAdapter->stats.tx_dropped;
1463 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
1464 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
1465 kfree_skb(skb);
1466 continue;
1467 }
1468
1469 //current list is empty
1470 break;
1471 }
1472 pPeerInfo->ibssStaInfo[STAId].txSuspended[i] = VOS_FALSE;
1473 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
1474 }
1475 }
1476 pAdapter->isVosLowResource = VOS_FALSE;
1477
1478 return status;
1479}
1480
1481/**============================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -07001482 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
1483 modules in HDD
1484
1485 @param pAdapter : [in] pointer to adapter context
1486 @return : VOS_STATUS_E_FAILURE if any errors encountered
1487 : VOS_STATUS_SUCCESS otherwise
1488 ===========================================================================*/
1489VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
1490{
1491 VOS_STATUS status = VOS_STATUS_SUCCESS;
1492 v_SINT_t i = -1;
1493
c_hpothub8245442013-11-20 23:41:09 +05301494 if ( NULL == pAdapter )
1495 {
c_hpothu32490782014-03-14 19:14:34 +05301496 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301497 FL("pAdapter is NULL"));
1498 VOS_ASSERT(0);
1499 return VOS_STATUS_E_FAILURE;
1500 }
1501
Jeff Johnson295189b2012-06-20 16:38:30 -07001502 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301503 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001504
1505 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
1506 //Will be zeroed out during alloc
1507
1508 while (++i != NUM_TX_QUEUES)
1509 {
1510 pAdapter->isTxSuspended[i] = VOS_FALSE;
1511 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1512 }
1513
1514 return status;
1515}
1516
1517
1518/**============================================================================
1519 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
1520 modules in HDD
1521
1522 @param pAdapter : [in] pointer to adapter context
1523 @return : VOS_STATUS_E_FAILURE if any errors encountered
1524 : VOS_STATUS_SUCCESS otherwise
1525 ===========================================================================*/
1526VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
1527{
1528 VOS_STATUS status = VOS_STATUS_SUCCESS;
1529 v_SINT_t i = -1;
1530
c_hpothub8245442013-11-20 23:41:09 +05301531 if ( NULL == pAdapter )
1532 {
c_hpothu32490782014-03-14 19:14:34 +05301533 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301534 FL("pAdapter is NULL"));
1535 VOS_ASSERT(0);
1536 return VOS_STATUS_E_FAILURE;
1537 }
1538
Jeff Johnson295189b2012-06-20 16:38:30 -07001539 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301540 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301541 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301542 FL("failed to flush tx queues"));
1543
Jeff Johnson295189b2012-06-20 16:38:30 -07001544 while (++i != NUM_TX_QUEUES)
1545 {
1546 //Free up actual list elements in the Tx queue
1547 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1548 }
1549
1550 return status;
1551}
1552
1553
1554/**============================================================================
1555 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1556 modules in HDD
1557
1558 @param pAdapter : [in] pointer to adapter context
1559 @return : VOS_STATUS_E_FAILURE if any errors encountered
1560 : VOS_STATUS_SUCCESS otherwise
1561 ===========================================================================*/
1562VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1563{
1564 return hdd_flush_tx_queues(pAdapter);
1565}
1566
1567
1568/**============================================================================
1569 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1570
1571 @param pVosPacket : [in] pointer to vos packet
1572 @return : VOS_TRUE if the packet is EAPOL
1573 : VOS_FALSE otherwise
1574 ===========================================================================*/
1575
1576v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1577{
1578 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1579 v_BOOL_t fEAPOL = VOS_FALSE;
1580 void *pBuffer = NULL;
1581
1582
1583 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1584 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
Abhishek Singhfa011222014-04-14 10:57:08 +05301585 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001586 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301587 if ( pBuffer && *(unsigned short*)pBuffer ==
1588 vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 {
1590 fEAPOL = VOS_TRUE;
1591 }
1592 }
1593
1594 return fEAPOL;
1595}
1596
Abhishek Singhfa011222014-04-14 10:57:08 +05301597/**============================================================================
1598 @brief hdd_IsARP() - Checks the packet is ARP or not.
1599
1600 @param pVosPacket : [in] pointer to vos packet
1601 @return : VOS_TRUE if the packet is ARP
1602 : VOS_FALSE otherwise
1603 ===========================================================================*/
1604
1605v_BOOL_t hdd_IsARP( vos_pkt_t *pVosPacket )
1606{
1607 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1608 v_BOOL_t fIsARP = VOS_FALSE;
1609 void *pBuffer = NULL;
1610
1611
1612 vosStatus = vos_pkt_peek_data( pVosPacket,
1613 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1614 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1615 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1616 {
1617 if ( pBuffer && *(unsigned short*)pBuffer ==
1618 vos_cpu_to_be16(HDD_ETHERTYPE_ARP) )
1619 {
1620 fIsARP = VOS_TRUE;
1621 }
1622 }
1623
1624 return fIsARP;
1625}
Jeff Johnson295189b2012-06-20 16:38:30 -07001626
1627#ifdef FEATURE_WLAN_WAPI // Need to update this function
1628/**============================================================================
1629 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1630
1631 @param pVosPacket : [in] pointer to vos packet
1632 @return : VOS_TRUE if the packet is WAI
1633 : VOS_FALSE otherwise
1634 ===========================================================================*/
1635
1636v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1637{
1638 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1639 v_BOOL_t fIsWAI = VOS_FALSE;
1640 void *pBuffer = NULL;
1641
1642 // Need to update this function
1643 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1644 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1645
1646 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1647 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301648 if ( pBuffer && *(unsigned short*)pBuffer ==
1649 vos_cpu_to_be16(HDD_ETHERTYPE_WAI) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001650 {
1651 fIsWAI = VOS_TRUE;
1652 }
1653 }
1654
1655 return fIsWAI;
1656}
1657#endif /* FEATURE_WLAN_WAPI */
1658
1659/**============================================================================
1660 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1661 to indicate that a packet has been transmitted across the SDIO bus
1662 succesfully. OS packet resources can be released after this cbk.
1663
1664 @param vosContext : [in] pointer to VOS context
1665 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1666 @param vosStatusIn : [in] status of the transmission
1667
1668 @return : VOS_STATUS_E_FAILURE if any errors encountered
1669 : VOS_STATUS_SUCCESS otherwise
1670 ===========================================================================*/
1671VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1672 vos_pkt_t *pVosPacket,
1673 VOS_STATUS vosStatusIn )
1674{
1675 VOS_STATUS status = VOS_STATUS_SUCCESS;
1676 hdd_adapter_t *pAdapter = NULL;
1677 hdd_context_t *pHddCtx = NULL;
1678 void* pOsPkt = NULL;
1679
1680 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1681 {
c_hpothu32490782014-03-14 19:14:34 +05301682 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301683 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001684 return VOS_STATUS_E_FAILURE;
1685 }
1686
1687 //Return the skb to the OS
1688 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301689 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 {
1691 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301692 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301693 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001694 vos_pkt_return_packet( pVosPacket );
1695 return VOS_STATUS_E_FAILURE;
1696 }
1697
1698 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001699 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001700 //Get the Adapter context.
1701 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301702 if (pAdapter == NULL || WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301704 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1705 "%s: Invalid adapter %p", __func__, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001706 }
1707 else
1708 {
1709 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1710 }
1711
1712 kfree_skb((struct sk_buff *)pOsPkt);
1713
1714 //Return the VOS packet resources.
1715 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301716 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001717 {
c_hpothu32490782014-03-14 19:14:34 +05301718 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301719 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001720 }
1721
1722 return status;
1723}
1724
Katya Nigamf944e5e2015-02-10 15:05:43 +05301725/**============================================================================
1726 @brief hdd_ibss_tx_fetch_packet_cbk() - Callback function invoked by TL to
1727 fetch a packet for transmission.
1728
1729 @param vosContext : [in] pointer to VOS context
1730 @param staId : [in] Station for which TL is requesting a pkt
1731 @param ac : [in] access category requested by TL
1732 @param pVosPacket : [out] pointer to VOS packet packet pointer
1733 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1734
1735 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1736 : VOS_STATUS_E_FAILURE if any errors encountered
1737 : VOS_STATUS_SUCCESS otherwise
1738 ===========================================================================*/
1739VOS_STATUS hdd_ibss_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1740 v_U8_t *pStaId,
1741 WLANTL_ACEnumType ac,
1742 vos_pkt_t **ppVosPacket,
1743 WLANTL_MetaInfoType *pPktMetaInfo )
1744{
1745 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1746 hdd_adapter_t *pAdapter = NULL;
1747 hdd_list_node_t *anchor = NULL;
1748 skb_list_node_t *pktNode = NULL;
1749 struct sk_buff *skb = NULL;
1750 vos_pkt_t *pVosPacket = NULL;
1751 v_MACADDR_t* pDestMacAddress = NULL;
1752 v_TIME_t timestamp;
1753 v_SIZE_t size = 0;
1754 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1755 hdd_context_t *pHddCtx = NULL;
1756 hdd_station_ctx_t *pHddStaCtx = NULL;
1757 hdd_ibss_peer_info_t *pPeerInfo = NULL;
1758 v_U8_t proto_type = 0;
Abhishek Singh99f725a2015-05-15 17:50:26 +05301759 v_U16_t packet_size;
Katya Nigamf944e5e2015-02-10 15:05:43 +05301760
1761 //Sanity check on inputs
1762 if ( ( NULL == vosContext ) ||
1763 ( NULL == pStaId ) ||
1764 ( NULL == ppVosPacket ) ||
1765 ( NULL == pPktMetaInfo ) )
1766 {
1767 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1768 "%s: Null Params being passed", __func__);
1769 return VOS_STATUS_E_FAILURE;
1770 }
1771
1772 //Get the HDD context.
1773 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1774 if ( NULL == pHddCtx )
1775 {
1776 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1777 "%s: HDD adapter context is Null", __func__);
1778 return VOS_STATUS_E_FAILURE;
1779 }
1780
1781 STAId = *pStaId;
1782 pAdapter = pHddCtx->sta_to_adapter[STAId];
1783 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1784 {
1785 VOS_ASSERT(0);
1786 return VOS_STATUS_E_FAILURE;
1787 }
1788
1789 pHddStaCtx = &pAdapter->sessionCtx.station;
1790 pPeerInfo = &pHddStaCtx->ibss_peer_info;
1791
1792 if (FALSE == pPeerInfo->ibssStaInfo[STAId].isUsed )
1793 {
1794 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1795 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1796 return VOS_STATUS_E_FAILURE;
1797 }
1798
1799 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1800
1801 *ppVosPacket = NULL;
1802
1803 //Make sure the AC being asked for is sane
1804 if( ac > WLANTL_MAX_AC || ac < 0)
1805 {
1806 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1807 "%s: Invalid AC %d passed by TL", __func__, ac);
1808 return VOS_STATUS_E_FAILURE;
1809 }
1810
1811 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1812
Katya Nigamf944e5e2015-02-10 15:05:43 +05301813 //Get the vos packet before so that we are prepare for VOS low reseurce condition
1814 //This simplifies the locking and unlocking of Tx queue
1815 status = vos_pkt_wrap_data_packet( &pVosPacket,
1816 VOS_PKT_TYPE_TX_802_3_DATA,
1817 NULL, //OS Pkt is not being passed
1818 hdd_tx_low_resource_cbk,
1819 pAdapter );
1820
1821 if ((status == VOS_STATUS_E_ALREADY) || (status == VOS_STATUS_E_RESOURCES))
1822 {
1823 //Remember VOS is in a low resource situation
1824 pAdapter->isVosOutOfResource = VOS_TRUE;
1825 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
1826 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
1827 "%s: VOSS in Low Resource scenario", __func__);
1828 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1829 return VOS_STATUS_E_FAILURE;
1830 }
1831
1832 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there.
1833 Do not get next AC as the other branch does.
1834 */
1835 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1836 hdd_list_size(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &size);
1837
1838 if (0 == size)
1839 {
1840 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1841 vos_pkt_return_packet(pVosPacket);
1842 return VOS_STATUS_E_EMPTY;
1843 }
1844
1845 status = hdd_list_remove_front( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1846 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1847
1848 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1849 "%s: AC %d has packets pending", __func__, ac);
1850
1851 if(VOS_STATUS_SUCCESS == status)
1852 {
1853 //If success then we got a valid packet from some AC
1854 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1855 skb = pktNode->skb;
1856 }
1857 else
1858 {
1859 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1860 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1861 "%s: Error in de-queuing skb from Tx queue status = %d",
1862 __func__, status );
1863 vos_pkt_return_packet(pVosPacket);
1864 return VOS_STATUS_E_FAILURE;
1865 }
1866
1867 //Attach skb to VOS packet.
1868 status = vos_pkt_set_os_packet( pVosPacket, skb );
1869 if (status != VOS_STATUS_SUCCESS)
1870 {
1871 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1872 "%s: Error attaching skb", __func__);
1873 vos_pkt_return_packet(pVosPacket);
1874 ++pAdapter->stats.tx_dropped;
1875 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1876 kfree_skb(skb);
1877 return VOS_STATUS_E_FAILURE;
1878 }
1879
1880 //Return VOS packet to TL;
1881 *ppVosPacket = pVosPacket;
1882
1883 //Fill out the meta information needed by TL
1884 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1885 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1886 if ( 1 < size )
1887 {
1888 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1889 }
1890 else
1891 {
1892 pPktMetaInfo->bMorePackets = 0;
1893 }
1894
1895 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1896 pPktMetaInfo->ucIsEapol = 0;
1897 else
1898 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1899
1900 if ((NULL != pHddCtx) &&
1901 (pHddCtx->cfg_ini->gEnableDebugLog))
1902 {
1903 proto_type = vos_pkt_get_proto_type(skb,
1904 pHddCtx->cfg_ini->gEnableDebugLog);
1905 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1906 {
1907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1908 "IBSS STA TX EAPOL");
1909 }
1910 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1911 {
1912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1913 "IBSS STA TX DHCP");
1914 }
Mihir Shete39f7c752015-06-11 15:40:09 +05301915 else if (VOS_PKT_PROTO_TYPE_ARP & proto_type)
1916 {
1917 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1918 "IBSS STA TX ARP");
1919 }
Katya Nigamf944e5e2015-02-10 15:05:43 +05301920 }
1921
Abhishek Singh99f725a2015-05-15 17:50:26 +05301922 vos_pkt_get_packet_length( pVosPacket,&packet_size );
1923 if ( HDD_ETHERTYPE_ARP_SIZE == packet_size )
1924 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
1925
Katya Nigamf944e5e2015-02-10 15:05:43 +05301926 pPktMetaInfo->ucUP = pktNode->userPriority;
1927 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1928 pPktMetaInfo->ucType = 0;
1929
1930 //Extract the destination address from ethernet frame
1931 pDestMacAddress = (v_MACADDR_t*)skb->data;
1932
1933 // we need 802.3 to 802.11 frame translation
1934 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1935 pPktMetaInfo->ucDisableFrmXtl = 0;
1936 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1937 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1938
1939 if ( (pPeerInfo->ibssStaInfo[STAId].txSuspended[ac]) &&
1940 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1941 {
1942 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1943 "%s: TX queue re-enabled", __func__);
1944 pPeerInfo->ibssStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1945 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1946 }
1947
1948 // We're giving the packet to TL so consider it transmitted from
1949 // a statistics perspective. We account for it here instead of
1950 // when the packet is returned for two reasons. First, TL will
1951 // manipulate the skb to the point where the len field is not
1952 // accurate, leading to inaccurate byte counts if we account for
1953 // it later. Second, TL does not provide any feedback as to
1954 // whether or not the packet was successfully sent over the air,
1955 // so the packet counts will be the same regardless of where we
1956 // account for them
1957 pAdapter->stats.tx_bytes += skb->len;
1958 ++pAdapter->stats.tx_packets;
1959 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1960 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1961 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1962
1963 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1964 "%s: Valid VOS PKT returned to TL", __func__);
1965
1966 return status;
1967}
Jeff Johnson295189b2012-06-20 16:38:30 -07001968
1969/**============================================================================
1970 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1971 fetch a packet for transmission.
1972
1973 @param vosContext : [in] pointer to VOS context
1974 @param staId : [in] Station for which TL is requesting a pkt
1975 @param ac : [in] access category requested by TL
1976 @param pVosPacket : [out] pointer to VOS packet packet pointer
1977 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1978
1979 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1980 : VOS_STATUS_E_FAILURE if any errors encountered
1981 : VOS_STATUS_SUCCESS otherwise
1982 ===========================================================================*/
1983VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1984 v_U8_t *pStaId,
1985 WLANTL_ACEnumType ac,
1986 vos_pkt_t **ppVosPacket,
1987 WLANTL_MetaInfoType *pPktMetaInfo )
1988{
1989 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1990 hdd_adapter_t *pAdapter = NULL;
1991 hdd_context_t *pHddCtx = NULL;
1992 hdd_list_node_t *anchor = NULL;
1993 skb_list_node_t *pktNode = NULL;
1994 struct sk_buff *skb = NULL;
1995 vos_pkt_t *pVosPacket = NULL;
1996 v_MACADDR_t* pDestMacAddress = NULL;
1997 v_TIME_t timestamp;
1998 WLANTL_ACEnumType newAc;
1999 v_SIZE_t size = 0;
Abhishek Singhfa011222014-04-14 10:57:08 +05302000 v_U16_t packet_size;
Jeff Johnson295189b2012-06-20 16:38:30 -07002001 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002002 v_U8_t proto_type = 0;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302003 WLANTL_ACEnumType actualAC;
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302004 v_BOOL_t arp_pkt;
Jeff Johnson295189b2012-06-20 16:38:30 -07002005
2006 //Sanity check on inputs
2007 if ( ( NULL == vosContext ) ||
2008 ( NULL == pStaId ) ||
2009 ( NULL == ppVosPacket ) ||
2010 ( NULL == pPktMetaInfo ) )
2011 {
c_hpothu32490782014-03-14 19:14:34 +05302012 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302013 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002014 return VOS_STATUS_E_FAILURE;
2015 }
2016
2017 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07002018 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07002019 if(pHddCtx == NULL)
2020 {
c_hpothu32490782014-03-14 19:14:34 +05302021 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302022 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002023 return VOS_STATUS_E_FAILURE;
2024 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002025 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08002026 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 {
c_hpothu32490782014-03-14 19:14:34 +05302028 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302029 FL("invalid adapter:%p for staId:%u"), pAdapter, *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002030 VOS_ASSERT(0);
2031 return VOS_STATUS_E_FAILURE;
2032 }
2033
2034 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
2035
2036 *ppVosPacket = NULL;
2037
2038 //Make sure the AC being asked for is sane
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302039 if (ac > WLANTL_AC_HIGH_PRIO || ac < 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 {
c_hpothu32490782014-03-14 19:14:34 +05302041 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302042 "%s: Invalid QId %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07002043 return VOS_STATUS_E_FAILURE;
2044 }
2045
2046 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
2047
2048#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05302049 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302050 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07002051#endif // HDD_WMM_DEBUG
2052
Jeff Johnson295189b2012-06-20 16:38:30 -07002053 // do we have any packets pending in this AC?
2054 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
2055 if( size > 0 )
2056 {
2057 // yes, so process it
2058#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05302059 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002060 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07002061#endif // HDD_WMM_DEBUG
2062 }
2063 else
2064 {
2065 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
2066#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05302067 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002068 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002069#endif // HDD_WMM_DEBUG
2070 return VOS_STATUS_E_FAILURE;
2071 }
2072
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302073 // Note here that we are not checking "wmmAcAccessAllowed" for packets
2074 // in new queue since there is no one AC associated to the new queue.
2075 // Since there will be either eapol or dhcp pkts in new queue overlooking
2076 // this should be okay from implicit QoS perspective.
2077 if (ac != WLANTL_AC_HIGH_PRIO)
2078 {
2079 // We find an AC with packets
2080 // or we determine we have no more packets to send
2081 // HDD is not allowed to change AC.
2082
2083 // has this AC been admitted? or
2084 // To allow EAPOL packets when not authenticated
2085 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
2086 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
2087 {
2088 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
2089#ifdef HDD_WMM_DEBUG
2090 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
2091 "%s: no packets pending", __func__);
2092#endif // HDD_WMM_DEBUG
2093 return VOS_STATUS_E_FAILURE;
2094 }
2095 }
2096
Jeff Johnson295189b2012-06-20 16:38:30 -07002097 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
2098 //This simplifies the locking and unlocking of Tx queue
2099 status = vos_pkt_wrap_data_packet( &pVosPacket,
2100 VOS_PKT_TYPE_TX_802_3_DATA,
2101 NULL, //OS Pkt is not being passed
2102 hdd_tx_low_resource_cbk,
2103 pAdapter );
2104
2105 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
2106 {
2107 //Remember VOS is in a low resource situation
2108 pAdapter->isVosOutOfResource = VOS_TRUE;
2109 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05302110 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 -07002111 //TL will now think we have no more packets in this AC
2112 return VOS_STATUS_E_FAILURE;
2113 }
2114
2115 //Remove the packet from the queue
2116 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
2117 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
2118 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
2119
2120 if(VOS_STATUS_SUCCESS == status)
2121 {
2122 //If success then we got a valid packet from some AC
2123 pktNode = list_entry(anchor, skb_list_node_t, anchor);
2124 skb = pktNode->skb;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302125 actualAC = hddWmmUpToAcMap[pktNode->userPriority];
2126 if (actualAC >= WLANTL_MAX_AC)
2127 {
2128 /* To fix klocwork */
2129 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
2130 "%s: Invalid AC for packet:%d", __func__, actualAC);
2131 actualAC = WLANTL_AC_BE;
2132 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002133 }
2134 else
2135 {
2136 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05302137 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002138 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07002139 vos_pkt_return_packet(pVosPacket);
2140 return VOS_STATUS_E_FAILURE;
2141 }
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302142 arp_pkt = vos_is_arp_pkt(skb, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07002143 //Attach skb to VOS packet.
2144 status = vos_pkt_set_os_packet( pVosPacket, skb );
2145 if (status != VOS_STATUS_SUCCESS)
2146 {
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302147
2148 if (arp_pkt)
2149 {
2150 ++pAdapter->hdd_stats.hddArpStats.txDropped;
2151 pAdapter->hdd_stats.hddArpStats.reason = HDD_ERROR_ATTACHING_SKB;
2152 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2153 "%s :Error attaching skb,ARP packet droped", __func__);
2154 }
2155
c_hpothu32490782014-03-14 19:14:34 +05302156 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002157 vos_pkt_return_packet(pVosPacket);
2158 ++pAdapter->stats.tx_dropped;
2159 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
2160 kfree_skb(skb);
2161 return VOS_STATUS_E_FAILURE;
2162 }
2163
2164 //Just being paranoid. To be removed later
2165 if(pVosPacket == NULL)
2166 {
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302167
2168 if (arp_pkt)
2169 {
2170 ++pAdapter->hdd_stats.hddArpStats.txDropped;
2171 pAdapter->hdd_stats.hddArpStats.reason = HDD_VOS_PACKET_RETURNED_BY_VOSS_IS_NULL;
2172 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2173 "%s :VOS packet returned by VOSS is NULL,ARP packet droped",
2174 __func__);
2175 }
2176
c_hpothu32490782014-03-14 19:14:34 +05302177 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 -07002178 ++pAdapter->stats.tx_dropped;
2179 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
2180 kfree_skb(skb);
2181 return VOS_STATUS_E_FAILURE;
2182 }
2183
Dino Mycle3b9536d2014-07-09 22:05:24 +05302184#ifdef WLAN_FEATURE_LINK_LAYER_STATS
Srinivas Dasaridab36fe2015-07-21 12:10:56 +05302185 if (vos_is_macaddr_multicast((v_MACADDR_t*)skb->data))
Dino Mycle3b9536d2014-07-09 22:05:24 +05302186 {
Srinivas Dasaridab36fe2015-07-21 12:10:56 +05302187 pAdapter->hdd_stats.hddTxRxStats.txMcast[actualAC]++;
Dino Mycle3b9536d2014-07-09 22:05:24 +05302188 }
2189
2190#endif
2191
Masti, Narayanraddi63d62352015-10-01 12:52:50 +05302192 wlan_hdd_tdls_notify_packet(pAdapter, skb);
Chilam NG571c65a2013-01-19 12:27:36 +05302193
Jeff Johnson295189b2012-06-20 16:38:30 -07002194 //Return VOS packet to TL;
2195 *ppVosPacket = pVosPacket;
2196
2197 //Fill out the meta information needed by TL
2198 //FIXME This timestamp is really the time stamp of wrap_data_packet
2199 vos_pkt_get_timestamp( pVosPacket, &timestamp );
2200 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
2201
2202 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
2203 pPktMetaInfo->ucIsEapol = 0;
Nirav Shah4f765af2015-01-21 19:51:30 +05302204 else
Jeff Johnson295189b2012-06-20 16:38:30 -07002205 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
2206
Sushant Kaushika8073312015-05-04 17:33:52 +05302207 if (pPktMetaInfo->ucIsEapol)
2208 wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED);
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302209 if ((NULL != pHddCtx) &&
2210 (pHddCtx->cfg_ini->gEnableDebugLog))
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002211 {
2212 proto_type = vos_pkt_get_proto_type(skb,
2213 pHddCtx->cfg_ini->gEnableDebugLog);
2214 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2215 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302216 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4b53d4b2015-05-08 05:35:00 -07002217 "STA TX EAPOL");
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002218 }
2219 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2220 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302221 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002222 "STA TX DHCP");
2223 }
Mihir Shete39f7c752015-06-11 15:40:09 +05302224 else if (VOS_PKT_PROTO_TYPE_ARP & proto_type)
2225 {
2226 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2227 "STA TX ARP");
2228 }
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002229 }
2230
Abhishek Singhfa011222014-04-14 10:57:08 +05302231 vos_pkt_get_packet_length( pVosPacket,&packet_size );
2232 if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
2233 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
2234
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302235 if(pPktMetaInfo->ucIsArp)
2236 {
2237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2238 "%s :STA TX ARP Received in TL ",__func__);
2239 }
2240
Jeff Johnson295189b2012-06-20 16:38:30 -07002241#ifdef FEATURE_WLAN_WAPI
2242 // Override usIsEapol value when its zero for WAPI case
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302243 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002244#endif /* FEATURE_WLAN_WAPI */
2245
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302246 /* 1. Check if ACM is set for this AC
2247 * 2. If set, check if this AC had already admitted
2248 * 3. If not already admitted, downgrade the UP to next best UP
2249 * 4. Allow only when medium time is non zero when Addts accepted
2250 * else downgrade traffic. we opted downgrading over Delts when
2251 * medium time is zero because while doing downgradig driver is not
2252 * clearing the wmm context so consider in subsequent roaming
2253 * if AP (new or same AP) accept the Addts with valid medium time
2254 * no application support is required where if we have opted
2255 * delts Applications have to again do Addts or STA will never
2256 * go for Addts.
2257 */
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302258 pPktMetaInfo->ac = actualAC;
2259 if(!pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcAccessRequired ||
2260 (pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid &&
2261 pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07002262 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302263 pPktMetaInfo->ucUP = pktNode->userPriority;
2264 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07002265 }
2266 else
2267 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302268 //Downgrade the UP
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302269 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid;
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302270 newAc = WLANTL_AC_BK;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302271 for (i=actualAC-1; i>0; i--)
Jeff Johnson295189b2012-06-20 16:38:30 -07002272 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302273 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
2274 {
2275 newAc = i;
2276 break;
2277 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002278 }
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302279 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
2280 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
2281 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
2282 "Downgrading UP %d to UP %d ",
2283 pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002284 }
2285
Girish Gowlibf0e1ab2015-01-19 16:05:16 +05302286 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
2287 {
2288 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
2289 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302290
Jeff Johnson295189b2012-06-20 16:38:30 -07002291 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
2292 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
2293 if ( 1 < size )
2294 {
2295 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
2296 }
2297 else
2298 {
2299 pPktMetaInfo->bMorePackets = 0;
2300 }
2301
2302 //Extract the destination address from ethernet frame
2303 pDestMacAddress = (v_MACADDR_t*)skb->data;
2304 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
2305 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
2306
2307
2308
2309 // if we are in a backpressure situation see if we can turn the hose back on
2310 if ( (pAdapter->isTxSuspended[ac]) &&
2311 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
2312 {
2313 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
2314 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05302315 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002316 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07002317 pAdapter->isTxSuspended[ac] = VOS_FALSE;
2318 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
2319 skb_get_queue_mapping(skb) ));
Mihir Shete5d148f12014-12-16 17:54:49 +05302320 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_WAKE_NETDEV,
2321 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -07002322 }
2323
2324
2325 // We're giving the packet to TL so consider it transmitted from
2326 // a statistics perspective. We account for it here instead of
2327 // when the packet is returned for two reasons. First, TL will
2328 // manipulate the skb to the point where the len field is not
2329 // accurate, leading to inaccurate byte counts if we account for
2330 // it later. Second, TL does not provide any feedback as to
2331 // whether or not the packet was successfully sent over the air,
2332 // so the packet counts will be the same regardless of where we
2333 // account for them
2334 pAdapter->stats.tx_bytes += skb->len;
2335 ++pAdapter->stats.tx_packets;
2336 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
2337 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05302338 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002339
Leo Chang50bbd252013-04-25 14:58:01 -07002340 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
2341 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07002342 {
2343 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
2344 {
c_hpothu32490782014-03-14 19:14:34 +05302345 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002346 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002347 return VOS_STATUS_E_FAILURE;
2348 }
2349 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
2350 {
2351 if(0 == pHddCtx->tmInfo.txFrameCount)
2352 {
2353 /* Just recovered from sleep timeout */
2354 pHddCtx->tmInfo.lastOpenTs = timestamp;
2355 }
2356
Leo Chang50bbd252013-04-25 14:58:01 -07002357 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
2358 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002359 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
2360 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002361 /* During TX open duration, TX frame count is larger than threshold
2362 * Block TX during Sleep time */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302363 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002364 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07002365 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002366 pHddCtx->tmInfo.lastblockTs = timestamp;
2367 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
2368 {
2369 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
2370 }
2371 }
2372 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
2373 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
2374 {
2375 /* During TX open duration, TX frame count is less than threshold
2376 * Reset count and timestamp to prepare next cycle */
2377 pHddCtx->tmInfo.lastOpenTs = timestamp;
2378 pHddCtx->tmInfo.txFrameCount = 0;
2379 }
2380 else
2381 {
2382 /* Do Nothing */
2383 }
2384 pHddCtx->tmInfo.txFrameCount++;
2385 }
2386 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
2387 }
2388
2389
2390#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05302391 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 -07002392#endif // HDD_WMM_DEBUG
2393
2394 return status;
2395}
2396
2397
2398/**============================================================================
2399 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
2400 case where VOS packets are not available at the time of the call to get
2401 packets. This callback function is invoked by VOS when packets are
2402 available.
2403
2404 @param pVosPacket : [in] pointer to VOS packet
2405 @param userData : [in] opaque user data that was passed initially
2406
2407 @return : VOS_STATUS_E_FAILURE if any errors encountered,
2408 : VOS_STATUS_SUCCESS otherwise
2409 =============================================================================*/
2410VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
2411 v_VOID_t *userData )
2412{
2413 VOS_STATUS status;
2414 v_SINT_t i = 0;
2415 v_SIZE_t size = 0;
2416 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
2417
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302418 if (NULL == pAdapter || WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
Jeff Johnson295189b2012-06-20 16:38:30 -07002419 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302420 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2421 FL("Invalid adapter %p"), pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002422 return VOS_STATUS_E_FAILURE;
2423 }
2424
2425 //Return the packet to VOS. We just needed to know that VOS is out of low resource
2426 //situation. Here we will only signal TL that there is a pending data for a STA.
2427 //VOS packet will be requested (if needed) when TL comes back to fetch data.
2428 vos_pkt_return_packet( pVosPacket );
2429
2430 pAdapter->isVosOutOfResource = VOS_FALSE;
2431
2432 //Indicate to TL that there is pending data if a queue is non empty
2433 for( i=NUM_TX_QUEUES-1; i>=0; --i )
2434 {
2435 size = 0;
2436 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
2437 if ( size > 0 )
2438 {
2439 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
2440 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
2441 (WLANTL_ACEnumType)i );
2442 if( !VOS_IS_STATUS_SUCCESS( status ) )
2443 {
c_hpothu32490782014-03-14 19:14:34 +05302444 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302445 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07002446 }
2447 }
2448 }
2449
2450 return VOS_STATUS_SUCCESS;
2451}
2452
Katya Nigame7b69a82015-04-28 15:24:06 +05302453static void hdd_mon_add_rx_radiotap_hdr (struct sk_buff *skb,
2454 int rtap_len, v_PVOID_t pRxPacket, hdd_mon_ctx_t *pMonCtx)
2455{
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302456 u8 rtap_temp[28] = {0};
Katya Nigame7b69a82015-04-28 15:24:06 +05302457 struct ieee80211_radiotap_header *rthdr;
2458 unsigned char *pos;
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302459 u32 mac_time;
Katya Nigame7b69a82015-04-28 15:24:06 +05302460 u16 rx_flags = 0;
2461 u16 rateIdx;
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302462 u16 channel_flags = 0;
2463 u8 rfBand;
2464 s8 currentRSSI, currentRSSI0, currentRSSI1;
2465 s8 noise;
Katya Nigame7b69a82015-04-28 15:24:06 +05302466
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302467 mac_time = WDA_GET_RX_TIMESTAMP(pRxPacket);
Katya Nigame7b69a82015-04-28 15:24:06 +05302468 rateIdx = WDA_GET_RX_MAC_RATE_IDX(pRxPacket);
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302469 if( rateIdx >= 210 && rateIdx <= 217)
2470 rateIdx-=202;
2471 if( rateIdx >= 218 && rateIdx <= 225 )
2472 rateIdx-=210;
Abhishek Singh2b055852015-10-07 14:14:13 +05302473
Gupta, Kapil50d757b2016-03-17 19:45:19 +05302474 if(rateIdx >= (sizeof(gRatefromIdx)/ sizeof(int))) {
Abhishek Singh2b055852015-10-07 14:14:13 +05302475 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2476 "%s: invalid rateIdx %d make it 0", __func__, rateIdx);
2477 rateIdx = 0;
2478 }
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302479 rfBand = WDA_GET_RX_RFBAND(pRxPacket);
2480 if (IS_5G_BAND(rfBand))
2481 channel_flags |= IEEE80211_CHAN_5GHZ;
2482 else
2483 channel_flags |= IEEE80211_CHAN_2GHZ;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302484 currentRSSI0 = WDA_GETRSSI0(pRxPacket) - 100;
2485 currentRSSI1 = WDA_GETRSSI1(pRxPacket) - 100;
2486 currentRSSI = (currentRSSI0 > currentRSSI1) ? currentRSSI0 : currentRSSI1;
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302487 noise = WDA_GET_RX_SNR(pRxPacket);
Katya Nigame7b69a82015-04-28 15:24:06 +05302488
2489 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2490
2491 /* radiotap header, set always present flags */
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302492 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
2493 (1 << IEEE80211_RADIOTAP_FLAGS) |
Katya Nigame7b69a82015-04-28 15:24:06 +05302494 (1 << IEEE80211_RADIOTAP_CHANNEL) |
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302495 (1 << IEEE80211_RADIOTAP_RATE) |
2496 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
2497 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
Katya Nigame7b69a82015-04-28 15:24:06 +05302498 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2499 rthdr->it_len = cpu_to_le16(rtap_len);
2500
2501 pos = (unsigned char *) (rthdr + 1);
2502
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302503 /* IEEE80211_RADIOTAP_TSFT */
2504 put_unaligned_le64(mac_time, pos);
2505 pos += 8;
2506
Katya Nigame7b69a82015-04-28 15:24:06 +05302507 /* IEEE80211_RADIOTAP_FLAGS */
2508 *pos = 0;
2509 pos++;
2510
2511 /* IEEE80211_RADIOTAP_RATE */
Katya Nigame7b69a82015-04-28 15:24:06 +05302512 *pos = gRatefromIdx[rateIdx]/5;
Katya Nigame7b69a82015-04-28 15:24:06 +05302513 pos++;
2514
2515 /* IEEE80211_RADIOTAP_CHANNEL */
2516 put_unaligned_le16(pMonCtx->ChannelNo, pos);
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302517 pos += 2;
2518 put_unaligned_le16(channel_flags, pos);
2519 pos += 2;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302520
2521 /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
2522 *pos = currentRSSI;
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302523 pos++;
2524
2525 /* IEEE80211_RADIOTAP_DBM_ANTNOISE */
2526 *pos = noise;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302527 pos++;
Katya Nigame7b69a82015-04-28 15:24:06 +05302528
2529 if ((pos - (u8 *)rthdr) & 1)
2530 pos++;
2531 put_unaligned_le16(rx_flags, pos);
2532 pos += 2;
2533
2534 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2535}
2536
2537
2538VOS_STATUS hdd_rx_packet_monitor_cbk(v_VOID_t *vosContext,vos_pkt_t *pVosPacket, int conversion)
2539{
2540 struct sk_buff *skb = NULL;
2541 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2542 hdd_adapter_t *pAdapter = NULL;
2543 hdd_context_t *pHddCtx = NULL;
2544 hdd_mon_ctx_t *pMonCtx = NULL;
2545 v_PVOID_t pvBDHeader = NULL;
2546 int rxstat;
2547 int needed_headroom = 0;
2548
2549
2550 //Sanity check on inputs
2551 if ( ( NULL == vosContext ) ||
2552 ( NULL == pVosPacket ) )
2553 {
2554 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2555 "%s: Null params being passed", __func__);
2556 return VOS_STATUS_E_FAILURE;
2557 }
2558
2559 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Abhishek Singh2b055852015-10-07 14:14:13 +05302560
2561 if (NULL == pHddCtx)
2562 {
2563 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2564 FL("Failed to get pHddCtx from vosContext"));
2565 vos_pkt_return_packet( pVosPacket );
2566 return VOS_STATUS_E_FAILURE;
2567 }
2568
Katya Nigame7b69a82015-04-28 15:24:06 +05302569 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
2570 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
2571 {
2572 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2573 FL("Invalid adapter %p for MONITOR MODE"), pAdapter);
2574 vos_pkt_return_packet( pVosPacket );
2575 return VOS_STATUS_E_FAILURE;
2576 }
2577
2578 status = WDA_DS_PeekRxPacketInfo( pVosPacket, (v_PVOID_t)&pvBDHeader, 1/*Swap BD*/ );
2579 if ( NULL == pvBDHeader )
2580 {
2581 VOS_TRACE( VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
2582 "Cannot extract BD header");
2583 /* Drop packet */
2584 vos_pkt_return_packet(pVosPacket);
2585 return VOS_STATUS_E_FAILURE;
2586 }
2587
2588 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
2589 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
2590 if(!VOS_IS_STATUS_SUCCESS( status ))
2591 {
2592 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
2593 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2594 "%s: Failure extracting skb from vos pkt", __func__);
2595 vos_pkt_return_packet( pVosPacket );
2596 return VOS_STATUS_E_FAILURE;
2597 }
2598
2599 if(!conversion)
2600 {
2601 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
Sravan Kumar Kairam937935b2015-12-28 16:23:04 +05302602 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 18;
Katya Nigame7b69a82015-04-28 15:24:06 +05302603 hdd_mon_add_rx_radiotap_hdr( skb, needed_headroom, pvBDHeader, pMonCtx );
2604 }
2605
2606 skb_reset_mac_header( skb );
2607 skb->dev = pAdapter->dev;
2608 skb->pkt_type = PACKET_OTHERHOST;
2609 skb->protocol = htons(ETH_P_802_2);
2610 skb->ip_summed = CHECKSUM_NONE;
2611 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2612 ++pAdapter->stats.rx_packets;
2613 pAdapter->stats.rx_bytes += skb->len;
2614
2615 rxstat = netif_rx_ni(skb);
2616 if (NET_RX_SUCCESS == rxstat)
2617 {
2618 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
2619 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
2620 }
2621 else
2622 {
2623 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2624 }
2625
2626 status = vos_pkt_return_packet( pVosPacket );
2627 if(!VOS_IS_STATUS_SUCCESS( status ))
2628 {
2629 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
2630 }
2631 pAdapter->dev->last_rx = jiffies;
2632
2633return status;
2634}
Jeff Johnson295189b2012-06-20 16:38:30 -07002635
Sravan Kumar Kairamf9f95122017-01-18 20:54:05 +05302636bool hdd_is_duplicate_ip_arp(struct sk_buff *skb)
2637{
2638 struct in_ifaddr **ifap = NULL;
2639 struct in_ifaddr *ifa = NULL;
2640 struct in_device *in_dev;
2641 uint32_t arp_ip,if_ip;
2642
2643 if (NULL == skb)
2644 return false;
2645
2646 arp_ip = hdd_get_arp_src_ip(skb);
2647
2648 if(!skb->dev) return false;
2649
2650 in_dev = __in_dev_get_rtnl(skb->dev);
2651
2652 if (in_dev) {
2653 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
2654 ifap = &ifa->ifa_next) {
2655 if (!strcmp(skb->dev->name, ifa->ifa_label))
2656 break;
2657 }
2658 }
2659 if (ifa && ifa->ifa_local) {
2660
2661 if_ip = ntohl(ifa->ifa_local);
2662 if (if_ip == arp_ip) {
2663 return true;
2664 }
2665 }
2666
2667 return false;
2668}
2669
Jeff Johnson295189b2012-06-20 16:38:30 -07002670/**============================================================================
2671 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
2672 TL will call this to notify the HDD when one or more packets were
2673 received for a registered STA.
2674
2675 @param vosContext : [in] pointer to VOS context
2676 @param pVosPacketChain : [in] pointer to VOS packet chain
2677 @param staId : [in] Station Id
2678 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
2679
2680 @return : VOS_STATUS_E_FAILURE if any errors encountered,
2681 : VOS_STATUS_SUCCESS otherwise
2682 ===========================================================================*/
2683VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
2684 vos_pkt_t *pVosPacketChain,
2685 v_U8_t staId,
2686 WLANTL_RxMetaInfoType* pRxMetaInfo )
2687{
2688 hdd_adapter_t *pAdapter = NULL;
2689 hdd_context_t *pHddCtx = NULL;
2690 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2691 int rxstat;
2692 struct sk_buff *skb = NULL;
2693 vos_pkt_t* pVosPacket;
2694 vos_pkt_t* pNextVosPacket;
c_manjee16126372017-01-16 19:29:30 +05302695 v_U8_t proto_type = 0;
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302696 v_BOOL_t arp_pkt;
Jeff Johnson295189b2012-06-20 16:38:30 -07002697
2698 //Sanity check on inputs
2699 if ( ( NULL == vosContext ) ||
2700 ( NULL == pVosPacketChain ) ||
2701 ( NULL == pRxMetaInfo ) )
2702 {
c_hpothu32490782014-03-14 19:14:34 +05302703 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302704 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002705 return VOS_STATUS_E_FAILURE;
2706 }
2707
Kiet Lam3c2ee302014-03-23 23:23:22 -07002708 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07002709 if ( NULL == pHddCtx )
2710 {
c_hpothu32490782014-03-14 19:14:34 +05302711 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302712 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002713 return VOS_STATUS_E_FAILURE;
2714 }
2715
2716 pAdapter = pHddCtx->sta_to_adapter[staId];
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302717 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002718 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302719 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2720 FL("Invalid adapter %p for staId %u"), pAdapter, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002721 return VOS_STATUS_E_FAILURE;
2722 }
2723
2724 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
2725
2726 // walk the chain until all are processed
2727 pVosPacket = pVosPacketChain;
2728 do
2729 {
2730 // get the pointer to the next packet in the chain
2731 // (but don't unlink the packet since we free the entire chain later)
2732 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
2733
2734 // both "success" and "empty" are acceptable results
2735 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
2736 {
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302737
2738 if(hdd_IsARP(pVosPacket))
2739 {
2740 ++pAdapter->hdd_stats.hddArpStats.rxDropped;
2741 pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILURE_WALKING_PACKET_CHAIN;
2742 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2743 "%s: ARP packet Drop: Failure walking packet chain", __func__);
2744 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002745 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302746 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302747 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002748 return VOS_STATUS_E_FAILURE;
2749 }
2750
2751 // Extract the OS packet (skb).
Sushant Kaushikd43987b2015-06-05 12:18:34 +05302752 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07002753 if(!VOS_IS_STATUS_SUCCESS( status ))
2754 {
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302755
2756 if(hdd_IsARP(pVosPacket))
2757 {
2758 ++pAdapter->hdd_stats.hddArpStats.rxDropped;
2759 pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILURE_EXTRACTING_SKB_FROM_VOS_PKT;
2760 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2761 "%s: ARP packet Dropped: Failure extracting skb from vos pkt",
2762 __func__);
2763 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002764 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302765 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302766 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002767 return VOS_STATUS_E_FAILURE;
2768 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002769
Sushant Kaushikd43987b2015-06-05 12:18:34 +05302770 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
2771 wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
2772
2773 pVosPacket->pSkb = NULL;
2774
Jeff Johnsone7245742012-09-05 17:12:55 -07002775 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2776 {
c_hpothu32490782014-03-14 19:14:34 +05302777 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07002778 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
2779 return eHAL_STATUS_FAILURE;
2780 }
2781
Chilam Ng1279e232013-01-25 15:06:52 -08002782#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002783 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
2784 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08002785 {
2786 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08002787 u8 mac[6];
2788
Ganesh Kondabattinif3ba0972015-08-07 15:58:04 +05302789 memcpy(mac, skb->data+6, 6);
Chilam Ng1279e232013-01-25 15:06:52 -08002790
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002791 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302792 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002793 "rx broadcast packet, not adding to peer list");
Ganesh Kondabattinif3ba0972015-08-07 15:58:04 +05302794 } else if ((memcmp(pHddStaCtx->conn_info.bssId,
2795 mac, 6) != 0) && (pRxMetaInfo->isStaTdls)) {
2796 wlan_hdd_tdls_update_rx_pkt_cnt_n_rssi(pAdapter, mac,
2797 pRxMetaInfo->rssiAvg);
Chilam Ng1279e232013-01-25 15:06:52 -08002798 } else {
c_hpothu32490782014-03-14 19:14:34 +05302799 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002800 "rx packet sa is bssid, not adding to peer list");
2801 }
2802 }
2803#endif
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002804 if (pHddCtx->cfg_ini->gEnableDebugLog)
2805 {
2806 proto_type = vos_pkt_get_proto_type(skb,
2807 pHddCtx->cfg_ini->gEnableDebugLog);
2808 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2809 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302810 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4b53d4b2015-05-08 05:35:00 -07002811 "STA RX EAPOL");
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002812 }
2813 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2814 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302815 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002816 "STA RX DHCP");
2817 }
Mihir Shete39f7c752015-06-11 15:40:09 +05302818 else if (VOS_PKT_PROTO_TYPE_ARP & proto_type)
2819 {
2820 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2821 "STA RX ARP");
2822 }
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002823 }
2824
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302825 arp_pkt = vos_is_arp_pkt(skb, false);
2826
2827 if (arp_pkt)
2828 {
2829 ++pAdapter->hdd_stats.hddArpStats.rxCount;
2830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2831 "%s :STA RX ARP received",__func__);
2832 }
2833
Sravan Kumar Kairamd9ded562016-11-13 15:21:49 +05302834 if (pHddCtx->rx_wow_dump) {
2835 if (!(VOS_PKT_PROTO_TYPE_ARP & proto_type) &&
2836 !(VOS_PKT_PROTO_TYPE_EAPOL & proto_type))
2837 hdd_log_ip_addr(skb);
2838 pHddCtx->rx_wow_dump = false;
2839 }
2840
Girish Gowli8a7bc042015-01-19 16:20:20 +05302841 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
2842 {
2843 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2844 }
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302845 if (( NULL != pHddCtx ) &&
2846 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05302847 {
2848 hdd_dump_dhcp_pkt(skb, RX_PATH);
2849 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302850
Jeff Johnson295189b2012-06-20 16:38:30 -07002851 skb->dev = pAdapter->dev;
2852 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002853 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002854 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2855 ++pAdapter->stats.rx_packets;
2856 pAdapter->stats.rx_bytes += skb->len;
Sravan Kumar Kairamf9f95122017-01-18 20:54:05 +05302857
2858 if (arp_pkt)
2859 {
2860 pAdapter->dad = hdd_is_duplicate_ip_arp(skb);
2861 if(pAdapter->dad)
2862 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2863 "%s :Duplicate IP detected",__func__);
2864 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002865#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302866 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2867 HDD_WAKE_LOCK_DURATION,
2868 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002869#endif
Bhargav Shah15c8bfc2015-08-04 19:36:12 +05302870 if (pNextVosPacket)
2871 {
2872 rxstat = netif_rx(skb);
2873 }
2874 else
2875 {
2876 rxstat = netif_rx_ni(skb);
2877 }
2878
Jeff Johnson295189b2012-06-20 16:38:30 -07002879 if (NET_RX_SUCCESS == rxstat)
2880 {
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302881
2882 if (arp_pkt)
2883 {
2884 ++pAdapter->hdd_stats.hddArpStats.rxDelivered;
2885 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2886 "STA RX ARP packet Delivered to net stack");
2887 }
2888
Jeff Johnson295189b2012-06-20 16:38:30 -07002889 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002890 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002891 }
2892 else
2893 {
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302894
2895 if (arp_pkt)
2896 {
2897 ++pAdapter->hdd_stats.hddArpStats.rxRefused;
2898 pAdapter->hdd_stats.hddArpStats.reason = HDD_STA_RX_ARP_PACKET_REFUSED_IN_NET_STACK;
2899 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2900 "%s :STA RX ARP packet Refused in net stack", __func__);
2901 }
2902
Jeff Johnson295189b2012-06-20 16:38:30 -07002903 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2904 }
2905 // now process the next packet in the chain
2906 pVosPacket = pNextVosPacket;
2907
2908 } while (pVosPacket);
2909
2910 //Return the entire VOS packet chain to the resource pool
2911 status = vos_pkt_return_packet( pVosPacketChain );
2912 if(!VOS_IS_STATUS_SUCCESS( status ))
2913 {
c_hpothu32490782014-03-14 19:14:34 +05302914 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002915 }
2916
2917 pAdapter->dev->last_rx = jiffies;
2918
2919 return status;
2920}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002921/**============================================================================
2922 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2923 Enable/Disable split scan based on TX and RX traffic.
2924 @param HddContext : [in] pointer to Hdd context
2925 @return : None
2926 ===========================================================================*/
2927void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2928{
2929 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2930 hdd_adapter_t *pAdapter = NULL;
2931 hdd_station_ctx_t *pHddStaCtx = NULL;
2932 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2933 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2934 VOS_STATUS status;
2935 v_U8_t staId = 0;
2936 v_U8_t fconnected = 0;
2937
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +05302938 ENTER();
2939 if (0 != (wlan_hdd_validate_context(pHddCtx)))
2940 {
2941 return;
2942 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002943 if (!cfg_param->dynSplitscan)
2944 {
c_hpothu32490782014-03-14 19:14:34 +05302945 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002946 "%s: Error : Dynamic split scan is not Enabled : %d",
2947 __func__, pHddCtx->cfg_ini->dynSplitscan);
2948 return;
2949 }
2950
2951 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2952 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2953 {
2954 pAdapter = pAdapterNode->pAdapter;
2955
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +05302956 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002957 {
c_hpothu32490782014-03-14 19:14:34 +05302958 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002959 "%s: Adapter with device mode %d exists",
2960 __func__, pAdapter->device_mode);
2961
2962 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2963 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2964 {
2965 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2966 if ((eConnectionState_Associated ==
2967 pHddStaCtx->conn_info.connState) &&
2968 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2969 {
2970 fconnected = TRUE;
2971 }
2972 }
2973 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2974 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2975 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302976 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2977 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2978 if(pSapCtx == NULL){
2979 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2980 FL("psapCtx is NULL"));
2981 return;
2982 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002983 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2984 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302985 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002986 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302987 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002988 {
2989 fconnected = TRUE;
2990 }
2991 }
2992 }
2993 if ( fconnected )
2994 {
c_hpothu32490782014-03-14 19:14:34 +05302995 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002996 "%s: One of the interface is connected check for scan",
2997 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302998 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302999 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
3000 "miracast = %d", __func__,
3001 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
3002 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
3003 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003004
3005 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
3006 cfg_param->trafficMntrTmrForSplitScan);
3007 //Check for the previous statistics count
3008 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
3009 cfg_param->txRxThresholdForSplitScan) ||
3010 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
3011 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05303012 pHddCtx->drvr_miracast ||
3013 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003014 {
3015 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
3016 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
3017
3018 if (!pHddCtx->issplitscan_enabled)
3019 {
3020 pHddCtx->issplitscan_enabled = TRUE;
3021 sme_enable_disable_split_scan(
3022 WLAN_HDD_GET_HAL_CTX(pAdapter),
3023 cfg_param->nNumStaChanCombinedConc,
3024 cfg_param->nNumP2PChanCombinedConc);
3025 }
3026 return;
3027 }
3028 else
3029 {
3030 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
3031 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
3032 }
3033 fconnected = FALSE;
3034 }
3035 }
3036 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
3037 pAdapterNode = pNext;
3038 }
3039
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05303040 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
3041 * of disabling the split scan and thus do not disable the same when the
3042 * low TXRX condition is met.
3043 */
3044 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003045 {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +05303046 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003047 "%s: Disable split scan", __func__);
3048 pHddCtx->issplitscan_enabled = FALSE;
3049 sme_enable_disable_split_scan(
3050 pHddCtx->hHal,
3051 SME_DISABLE_SPLIT_SCAN,
3052 SME_DISABLE_SPLIT_SCAN);
3053 }
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +05303054 EXIT();
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003055 return;
3056}
Jeff Johnson295189b2012-06-20 16:38:30 -07003057
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +05303058/**
3059 * hdd_rx_fwd_eapol() - forward cached eapol frames
3060 * @vosContext : pointer to vos global context
3061 * @pVosPacket: pointer to vos packet
3062 *
3063 * Return: None
3064 *
3065 */
3066void hdd_rx_fwd_eapol(v_VOID_t *vosContext, vos_pkt_t *pVosPacket)
3067{
3068 hdd_context_t *pHddCtx = NULL;
3069 hdd_adapter_t * pAdapter;
3070 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3071 struct sk_buff *skb = NULL;
3072 uint8_t proto_type;
3073 uint8_t status;
3074
3075 if ((NULL == vosContext) || (NULL == pVosPacket))
3076 {
3077 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
3078 "%s: Null global context", __func__);
3079 return;
3080 }
3081
3082 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vosContext);
3083 if (NULL == pHddCtx)
3084 {
3085 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
3086 "%s: HDD adapter context is Null", __func__);
3087 return;
3088 }
3089
3090 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3091
3092 while ( NULL != pAdapterNode && 0 == status )
3093 {
3094 pAdapter = pAdapterNode->pAdapter;
3095
3096 if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3097 break;
3098
3099 status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
3100 pAdapterNode = pNext;
3101 }
3102
3103 if (NULL == pAdapter)
3104 {
3105 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
3106 "%s: No adapter", __func__);
3107 return;
3108 }
3109
3110 vos_pkt_get_os_packet(pVosPacket, (v_VOID_t **)&skb, VOS_FALSE);
3111 proto_type = vos_pkt_get_proto_type(skb,
3112 pHddCtx->cfg_ini->gEnableDebugLog);
3113 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
3114 {
3115 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3116 "STA RX EAPOL");
3117 }
3118
3119 skb->dev = pAdapter->dev;
3120 skb->protocol = eth_type_trans(skb, skb->dev);
3121 skb->ip_summed = CHECKSUM_NONE;
3122
3123 netif_rx_ni(skb);
3124}
3125
Sushant Kaushika8073312015-05-04 17:33:52 +05303126#ifdef FEATURE_WLAN_DIAG_SUPPORT
3127/*
3128 * wlan_hdd_get_eapol_params() - Function to extract EAPOL params
3129 * @skb: skb data
3130 * @eapol_params: Pointer to hold the parsed EAPOL params
3131 * @event_type: Event type to indicate Tx/Rx
3132 *
3133 * This function parses the input skb data to get the EAPOL params,if the
3134 * packet is EAPOL and store it in the pointer passed as input
3135 *
3136 */
3137void wlan_hdd_get_eapol_params(struct sk_buff *skb,
3138 struct vos_event_wlan_eapol *eapol_params,
3139 uint8_t event_type)
3140{
3141 uint8_t packet_type=0;
3142
3143 packet_type = (uint8_t)(*(uint8_t *)
3144 (skb->data + HDD_EAPOL_PACKET_TYPE_OFFSET));
3145
3146 /* EAPOL msg type i.e. whether EAPOL-Start or
3147 * EAPOL-Key etc. messages Present at 15 offset.
3148 */
3149 eapol_params->eapol_packet_type = packet_type;
3150
3151 /* This tells if its a M1/M2/M3/M4 packet.
3152 * Present at 19th offset in EAPOL frame.
3153 */
3154 eapol_params->eapol_key_info = (uint16_t)(*(uint16_t *)
3155 (skb->data + HDD_EAPOL_KEY_INFO_OFFSET));
3156 /* This tells if EAPOL packet is in RX or TX
3157 * direction.
3158 */
3159 eapol_params->event_sub_type = event_type;
3160
3161 /* This tells the rate at which EAPOL packet
3162 * is send or received.
3163 */
3164 //TODO fill data rate for rx packet.
3165 eapol_params->eapol_rate = 0;/* As of now, zero */
3166
3167 vos_mem_copy(eapol_params->dest_addr,
3168 (skb->data + HDD_EAPOL_DEST_MAC_OFFSET),
3169 sizeof(eapol_params->dest_addr));
3170 vos_mem_copy(eapol_params->src_addr,
3171 (skb->data + HDD_EAPOL_SRC_MAC_OFFSET),
3172 sizeof(eapol_params->src_addr));
3173 return;
3174}
3175/*
3176 * wlan_hdd_event_eapol_log() - Function to log EAPOL events
3177 * @eapol_params: Structure containing EAPOL params
3178 *
3179 * This function logs the parsed EAPOL params
3180 *
3181 * Return: None
3182 *
3183 */
3184
3185static void wlan_hdd_event_eapol_log(struct vos_event_wlan_eapol eapol_params)
3186{
3187 WLAN_VOS_DIAG_EVENT_DEF(wlan_diag_event, struct vos_event_wlan_eapol);
3188
3189 wlan_diag_event.event_sub_type = eapol_params.event_sub_type;
3190 wlan_diag_event.eapol_packet_type = eapol_params.eapol_packet_type;
3191 wlan_diag_event.eapol_key_info = eapol_params.eapol_key_info;
3192 wlan_diag_event.eapol_rate = eapol_params.eapol_rate;
3193 vos_mem_copy(wlan_diag_event.dest_addr,
3194 eapol_params.dest_addr,
3195 sizeof (wlan_diag_event.dest_addr));
3196 vos_mem_copy(wlan_diag_event.src_addr,
3197 eapol_params.src_addr,
3198 sizeof (wlan_diag_event.src_addr));
3199 WLAN_VOS_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL);
3200}
3201
3202/*
3203 * wlan_hdd_log_eapol() - Function to check and extract EAPOL params
3204 * @skb: skb data
3205 * @event_type: One of enum wifi_connectivity_events to indicate Tx/Rx
3206 *
3207 * This function parses the input skb data to get the EAPOL params,if the
3208 * packet is EAPOL and store it in the pointer passed as input
3209 *
3210 * Return: None
3211 *
3212 */
3213void wlan_hdd_log_eapol(struct sk_buff *skb,
3214 uint8_t event_type)
3215{
3216 struct vos_event_wlan_eapol eapol_params;
3217
3218 wlan_hdd_get_eapol_params(skb, &eapol_params, event_type);
3219 wlan_hdd_event_eapol_log(eapol_params);
Sushant Kaushik9811d8a2015-10-07 15:56:26 +05303220
3221 if ((eapol_params.eapol_key_info & EAPOL_MASK )== EAPOL_M1_BIT_MASK)
3222 {
3223 hddLog(LOG1, FL("%s: M1 packet"),eapol_params.event_sub_type ==
3224 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED ? "RX" : "TX");
3225 }
3226 else if ((eapol_params.eapol_key_info & EAPOL_MASK )== EAPOL_M2_BIT_MASK)
3227 {
3228 hddLog(LOG1, FL("%s: M2 packet"),eapol_params.event_sub_type ==
3229 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED ? "RX" : "TX");
3230
3231 }
3232
3233 else if ((eapol_params.eapol_key_info & EAPOL_MASK )== EAPOL_M3_BIT_MASK)
3234 {
3235 hddLog(LOG1, FL("%s: M3 packet"),eapol_params.event_sub_type ==
3236 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED ? "RX" : "TX");
3237 }
3238
3239 else if ((eapol_params.eapol_key_info & EAPOL_MASK )== EAPOL_M4_BIT_MASK)
3240 {
3241 hddLog(LOG1, FL("%s: M4 packet"),eapol_params.event_sub_type ==
3242 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED ? "RX" : "TX");
3243
3244 }
3245
Sushant Kaushika8073312015-05-04 17:33:52 +05303246}
3247#endif /* FEATURE_WLAN_DIAG_SUPPORT */