blob: 10f76b87f0e500c0ec8f62a80c4502be3f3d32b5 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Mihir Shete0be28772015-02-17 18:42:14 +05302 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**===========================================================================
29
30 \file wlan_hdd_tx_rx.c
31
32 \brief Linux HDD Tx/RX APIs
Jeff Johnson295189b2012-06-20 16:38:30 -070033
34 ==========================================================================*/
35
36/*---------------------------------------------------------------------------
37 Include files
38 -------------------------------------------------------------------------*/
39#include <wlan_hdd_tx_rx.h>
40#include <wlan_hdd_softap_tx_rx.h>
41#include <wlan_hdd_dp_utils.h>
42#include <wlan_qct_tl.h>
43#include <linux/netdevice.h>
44#include <linux/skbuff.h>
45#include <linux/etherdevice.h>
Mihir Shetec8fe71b2014-06-16 15:32:59 +053046#include <linux/ratelimit.h>
Mihir Shetef3473692014-06-27 15:13:20 +053047#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
48#include <soc/qcom/subsystem_restart.h>
49#else
50#include <mach/subsystem_restart.h>
51#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070052
Jeff Johnson295189b2012-06-20 16:38:30 -070053#include <wlan_hdd_p2p.h>
54#include <linux/wireless.h>
55#include <net/cfg80211.h>
56#include <net/ieee80211_radiotap.h>
57#include "sapApi.h"
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053058#include <vos_sched.h>
Chilam NG571c65a2013-01-19 12:27:36 +053059#ifdef FEATURE_WLAN_TDLS
60#include "wlan_hdd_tdls.h"
61#endif
62
Mukul Sharma84f27252014-07-14 18:11:42 +053063#include "vos_utils.h"
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053064#include "sapInternal.h"
Mihir Shete5d148f12014-12-16 17:54:49 +053065#include "wlan_hdd_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070066/*---------------------------------------------------------------------------
67 Preprocessor definitions and constants
68 -------------------------------------------------------------------------*/
69
70const v_U8_t hddWmmAcToHighestUp[] = {
71 SME_QOS_WMM_UP_RESV,
72 SME_QOS_WMM_UP_EE,
73 SME_QOS_WMM_UP_VI,
74 SME_QOS_WMM_UP_NC
75};
76
77//Mapping Linux AC interpretation to TL AC.
78const v_U8_t hdd_QdiscAcToTlAC[] = {
79 WLANTL_AC_VO,
80 WLANTL_AC_VI,
81 WLANTL_AC_BE,
82 WLANTL_AC_BK,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +053083 WLANTL_AC_HIGH_PRIO,
Jeff Johnson295189b2012-06-20 16:38:30 -070084};
85
Mihir Shetec8fe71b2014-06-16 15:32:59 +053086#define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
87#define HDD_TX_TIMEOUT_RATELIMIT_BURST 1
Mihir Shetef3473692014-06-27 15:13:20 +053088#define HDD_TX_STALL_SSR_THRESHOLD 5
Mihir Shete0be28772015-02-17 18:42:14 +053089#define HDD_TX_STALL_SSR_THRESHOLD_HIGH 13
Mihir Shete327c2ab2014-11-13 15:17:02 +053090#define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
Mihir Shetec8fe71b2014-06-16 15:32:59 +053091
92static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs, \
93 HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
94 HDD_TX_TIMEOUT_RATELIMIT_BURST);
95
Jeff Johnson295189b2012-06-20 16:38:30 -070096static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070097
98/*---------------------------------------------------------------------------
99 Type declarations
100 -------------------------------------------------------------------------*/
101
102/*---------------------------------------------------------------------------
103 Function definitions and documenation
104 -------------------------------------------------------------------------*/
105
106#ifdef DATA_PATH_UNIT_TEST
107//Utility function to dump an sk_buff
108static void dump_sk_buff(struct sk_buff * skb)
109{
c_hpothu32490782014-03-14 19:14:34 +0530110 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
111 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
112 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
113 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
114 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
115 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
116 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700117
c_hpothu32490782014-03-14 19:14:34 +0530118 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -0700119 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
120 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu32490782014-03-14 19:14:34 +0530121 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
Jeff Johnson295189b2012-06-20 16:38:30 -0700122 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
123 skb->data[13], skb->data[14], skb->data[15]);
124}
125
126//Function for Unit Test only
127static void transport_thread(hdd_adapter_t *pAdapter)
128{
129 v_U8_t staId;
130 WLANTL_ACEnumType ac = WLANTL_AC_BE;
131 vos_pkt_t *pVosPacket = NULL ;
132 vos_pkt_t dummyPacket;
133 WLANTL_MetaInfoType pktMetaInfo;
134 WLANTL_RxMetaInfoType pktRxMetaInfo;
135 VOS_STATUS status = VOS_STATUS_E_FAILURE;
136
c_hpothub8245442013-11-20 23:41:09 +0530137 if (NULL == pAdapter)
138 {
c_hpothu32490782014-03-14 19:14:34 +0530139 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530140 FL("pAdapter is NULL"));
141 VOS_ASSERT(0);
142 return;
143 }
144
Jeff Johnson295189b2012-06-20 16:38:30 -0700145 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
146 &staId,
147 &ac,
148 &pVosPacket,
149 &pktMetaInfo );
150 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530151 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
152 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700153 else
c_hpothu32490782014-03-14 19:14:34 +0530154 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
155 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700156
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700157 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700158 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530159 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
160 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700161 else
c_hpothu32490782014-03-14 19:14:34 +0530162 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
163 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
165 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
166 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530167 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
168 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700169 else
c_hpothu32490782014-03-14 19:14:34 +0530170 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
171 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700172
173 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
174 &dummyPacket,
175 staId,
176 &pktRxMetaInfo);
177 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530178 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
179 "%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700180 else
c_hpothu32490782014-03-14 19:14:34 +0530181 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
182 "%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700183
184}
185#endif
186
187
188/**============================================================================
189 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
190
191 @param pAdapter : [in] pointer to adapter context
192 @return : VOS_STATUS_E_FAILURE if any errors encountered
193 : VOS_STATUS_SUCCESS otherwise
194 ===========================================================================*/
195static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
196{
197 VOS_STATUS status = VOS_STATUS_SUCCESS;
198 v_SINT_t i = -1;
199 hdd_list_node_t *anchor = NULL;
200 skb_list_node_t *pktNode = NULL;
201 struct sk_buff *skb = NULL;
202
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530203 pAdapter->isVosLowResource = VOS_FALSE;
204
Mihir Shete5d148f12014-12-16 17:54:49 +0530205 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_FLUSH_TX_QUEUES,
206 pAdapter->sessionId, 0));
207
Jeff Johnson295189b2012-06-20 16:38:30 -0700208 while (++i != NUM_TX_QUEUES)
209 {
210 //Free up any packets in the Tx queue
211 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
212 while (true)
213 {
214 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
215 if(VOS_STATUS_E_EMPTY != status)
216 {
217 pktNode = list_entry(anchor, skb_list_node_t, anchor);
218 skb = pktNode->skb;
219 //TODO
220 //++pAdapter->stats.tx_dropped;
221 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
222 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
223 kfree_skb(skb);
224 continue;
225 }
226 break;
227 }
228 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
229 // backpressure is no longer in effect
230 pAdapter->isTxSuspended[i] = VOS_FALSE;
231 }
232
233 return status;
234}
235
Ravi Joshif9520d62013-10-18 04:11:46 -0700236/**============================================================================
237 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
238 in IBSS mode
239
240 @param pAdapter : [in] pointer to adapter context
241 : [in] Staion Id
242 @return : VOS_STATUS_E_FAILURE if any errors encountered
243 : VOS_STATUS_SUCCESS otherwise
244 ===========================================================================*/
245void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
246{
247 v_U8_t i;
Katya Nigam47528772015-02-11 12:24:49 +0530248 hdd_list_node_t *anchor = NULL;
Ravi Joshi41914632013-10-21 23:02:21 -0700249 skb_list_node_t *pktNode = NULL;
Ravi Joshi41914632013-10-21 23:02:21 -0700250 struct sk_buff *skb = NULL;
Katya Nigam47528772015-02-11 12:24:49 +0530251 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
252 hdd_ibss_peer_info_t *pPeerInfo = &pHddStaCtx->ibss_peer_info;
Ravi Joshif9520d62013-10-18 04:11:46 -0700253
Katya Nigam47528772015-02-11 12:24:49 +0530254 for (i = 0; i < NUM_TX_QUEUES; i ++)
c_hpothub8245442013-11-20 23:41:09 +0530255 {
Katya Nigam47528772015-02-11 12:24:49 +0530256 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
257 while (true)
Ravi Joshif9520d62013-10-18 04:11:46 -0700258 {
Katya Nigam47528772015-02-11 12:24:49 +0530259 if (VOS_STATUS_E_EMPTY !=
260 hdd_list_remove_front(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i],
261 &anchor))
Ravi Joshif9520d62013-10-18 04:11:46 -0700262 {
Katya Nigam47528772015-02-11 12:24:49 +0530263 //If success then we got a valid packet from some AC
264 pktNode = list_entry(anchor, skb_list_node_t, anchor);
Ravi Joshif9520d62013-10-18 04:11:46 -0700265 skb = pktNode->skb;
Katya Nigam47528772015-02-11 12:24:49 +0530266 ++pAdapter->stats.tx_dropped;
267 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
268 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
269 kfree_skb(skb);
270 continue;
Ravi Joshif9520d62013-10-18 04:11:46 -0700271 }
Katya Nigam47528772015-02-11 12:24:49 +0530272 break;
Ravi Joshif9520d62013-10-18 04:11:46 -0700273 }
Katya Nigam47528772015-02-11 12:24:49 +0530274 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
Ravi Joshif9520d62013-10-18 04:11:46 -0700275 }
276}
277
Jeff Johnson295189b2012-06-20 16:38:30 -0700278static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
279{
280 skb_list_node_t *pktNode = NULL;
281 struct sk_buff *skb = NULL;
282 v_SIZE_t size = 0;
283 WLANTL_ACEnumType ac = 0;
284 VOS_STATUS status = VOS_STATUS_E_FAILURE;
285 hdd_list_node_t *anchor = NULL;
286
c_hpothu77731d42014-01-23 13:59:03 +0530287 if (NULL == pAdapter)
288 {
289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
290 FL("pAdapter is NULL"));
291 VOS_ASSERT(0);
292 return NULL;
293 }
294
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 // do we have any packets pending in this AC?
296 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
297 if( size == 0 )
298 {
c_hpothu32490782014-03-14 19:14:34 +0530299 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700300 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700301 return NULL;
302 }
303
304 //Remove the packet from the queue
305 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
306 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
307 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
308
309 if(VOS_STATUS_SUCCESS == status)
310 {
311 //If success then we got a valid packet from some AC
312 pktNode = list_entry(anchor, skb_list_node_t, anchor);
313 skb = pktNode->skb;
314 }
315 else
316 {
c_hpothu32490782014-03-14 19:14:34 +0530317 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700318 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700319 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320
321 return NULL;
322 }
323
324 // if we are in a backpressure situation see if we can turn the hose back on
325 if ( (pAdapter->isTxSuspended[ac]) &&
326 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
327 {
c_hpothu32490782014-03-14 19:14:34 +0530328 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700329 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700330 pAdapter->isTxSuspended[ac] = VOS_FALSE;
331 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530332 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700333 netif_tx_start_all_queues( pAdapter->dev );
334 }
335
336 return skb;
337}
338
339void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
340{
341 hdd_cfg80211_state_t *cfgState;
342 struct sk_buff* skb;
343 hdd_adapter_t* pMonAdapter = NULL;
344 struct ieee80211_hdr *hdr;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530345 hdd_context_t *pHddCtx;
346 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700347
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530348 ENTER();
Mukul Sharma23a92232014-04-07 18:04:00 +0530349 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700350 {
c_hpothu32490782014-03-14 19:14:34 +0530351 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530352 FL("pAdapter is NULL"));
353 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700354 return;
355 }
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530356 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
357 ret = wlan_hdd_validate_context(pHddCtx);
358 if (0 != ret)
359 {
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530360 return;
361 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700362 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530363 if (pMonAdapter == NULL)
364 {
365 hddLog(VOS_TRACE_LEVEL_ERROR,
366 "%s: pMonAdapter is NULL", __func__);
367 return;
368 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700369 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
370
371 if( NULL != cfgState->buf )
372 {
c_hpothu32490782014-03-14 19:14:34 +0530373 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700374 "%s: Already one MGMT packet Tx going on", __func__);
375 return;
376 }
377
378 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
379
380 if (NULL == skb)
381 {
c_hpothu32490782014-03-14 19:14:34 +0530382 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700383 "%s: No Packet Pending", __func__);
384 return;
385 }
386
387 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
388 if( cfgState->buf == NULL )
389 {
c_hpothu32490782014-03-14 19:14:34 +0530390 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700391 "%s: Failed to Allocate memory", __func__);
392 goto fail;
393 }
394
395 cfgState->len = skb->len;
396
397 vos_mem_copy( cfgState->buf, skb->data, skb->len);
398
399 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800400 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700401
402 hdr = (struct ieee80211_hdr *)skb->data;
403 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
404 == HDD_FRAME_TYPE_MGMT )
405 {
406 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
407 == HDD_FRAME_SUBTYPE_DEAUTH )
408 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530409 struct tagCsrDelStaParams delStaParams;
410
Sushant Kaushik4cd28f62014-12-26 14:23:50 +0530411 WLANSAP_PopulateDelStaParams(hdr->addr1,
412 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530413 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
414
415 hdd_softap_sta_deauth(pAdapter, &delStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -0700416 goto mgmt_handled;
417 }
418 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
419 == HDD_FRAME_SUBTYPE_DISASSOC )
420 {
421 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
422 goto mgmt_handled;
423 }
424 }
c_hpothu32490782014-03-14 19:14:34 +0530425 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700426 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
427
Jeff Johnson43971f52012-07-17 12:26:56 -0700428 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700429 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700430 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700431 {
c_hpothu32490782014-03-14 19:14:34 +0530432 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700433 "%s: WLANSAP_SendAction returned fail", __func__);
434 hdd_sendActionCnf( pAdapter, FALSE );
435 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530436 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700437 return;
438
439mgmt_handled:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530440 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700441 hdd_sendActionCnf( pAdapter, TRUE );
442 return;
443fail:
444 kfree_skb(pAdapter->skb_to_tx);
445 pAdapter->skb_to_tx = NULL;
446 return;
447}
448
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530449void __hdd_mon_tx_work_queue(struct work_struct *work)
Jeff Johnson295189b2012-06-20 16:38:30 -0700450{
451 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
452 hdd_mon_tx_mgmt_pkt(pAdapter);
453}
454
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530455void hdd_mon_tx_work_queue(struct work_struct *work)
456{
457 vos_ssr_protect(__func__);
458 __hdd_mon_tx_work_queue(work);
459 vos_ssr_unprotect(__func__);
460}
461
Jeff Johnson295189b2012-06-20 16:38:30 -0700462int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
463{
464 v_U16_t rt_hdr_len;
465 struct ieee80211_hdr *hdr;
466 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
467 struct ieee80211_radiotap_header *rtap_hdr =
468 (struct ieee80211_radiotap_header *)skb->data;
469
470 /*Supplicant sends the EAPOL packet on monitor interface*/
471 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
472 if(pPgBkAdapter == NULL)
473 {
c_hpothu32490782014-03-14 19:14:34 +0530474 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700475 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
476 __func__);
477 goto fail; /* too short to be possibly valid */
478 }
479
480 /* check if toal skb length is greater then radio tab header length of not */
481 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
482 goto fail; /* too short to be possibly valid */
483
484 /* check if radio tap header version is correct or not */
485 if (unlikely(rtap_hdr->it_version))
486 goto fail; /* only version 0 is supported */
487
488 /*Strip off the radio tap header*/
489 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
490
491 /* check if skb length if greator then total radio tap header length ot not*/
492 if (unlikely(skb->len < rt_hdr_len))
493 goto fail;
494
495 /* Update the trans_start for this netdev */
496 dev->trans_start = jiffies;
497 /*
498 * fix up the pointers accounting for the radiotap
499 * header still being in there.
500 */
501 skb_set_mac_header(skb, rt_hdr_len);
502 skb_set_network_header(skb, rt_hdr_len);
503 skb_set_transport_header(skb, rt_hdr_len);
504
505 /* Pull rtap header out of the skb */
506 skb_pull(skb, rt_hdr_len);
507
508 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
509 * radio tap header and 802.11 header starts
510 */
511 hdr = (struct ieee80211_hdr *)skb->data;
512
513 /* Send data frames through the normal Data path. In this path we will
514 * conver rcvd 802.11 packet to 802.3 packet */
515 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
516 {
517 v_U8_t da[6];
518 v_U8_t sa[6];
519
520 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
521 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
522
523 /* Pull 802.11 MAC header */
524 skb_pull(skb, HDD_80211_HEADER_LEN);
525
526 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
527 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
528 {
529 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
530 }
531
532 /* Pull LLC header */
533 skb_pull(skb, HDD_LLC_HDR_LEN);
534
535 /* Create space for Ethernet header */
536 skb_push(skb, HDD_MAC_HDR_SIZE*2);
537 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
538 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
539
540 /* Only EAPOL Data packets are allowed through monitor interface */
541 if (vos_be16_to_cpu(
542 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
543 != HDD_ETHERTYPE_802_1_X)
544 {
c_hpothu32490782014-03-14 19:14:34 +0530545 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 "%s: Not a Eapol packet. Drop this frame", __func__);
547 //If not EAPOL frames, drop them.
548 kfree_skb(skb);
549 return NETDEV_TX_OK;
550 }
551
552 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
553
554 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
555 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
556 }
557 else
558 {
559 VOS_STATUS status;
560 WLANTL_ACEnumType ac = 0;
561 skb_list_node_t *pktNode = NULL;
562 v_SIZE_t pktListSize = 0;
563
564 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
565 //If we have already reached the max queue size, disable the TX queue
566 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
567 {
568 /* We want to process one packet at a time, so lets disable all TX queues
569 * and re-enable the queues once we get TX feedback for this packet */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530570 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700571 netif_tx_stop_all_queues(pAdapter->dev);
572 pAdapter->isTxSuspended[ac] = VOS_TRUE;
573 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
574 return NETDEV_TX_BUSY;
575 }
576 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
577
578 //Use the skb->cb field to hold the list node information
579 pktNode = (skb_list_node_t *)&skb->cb;
580
581 //Stick the OS packet inside this node.
582 pktNode->skb = skb;
583
584 INIT_LIST_HEAD(&pktNode->anchor);
585
586 //Insert the OS packet into the appropriate AC queue
587 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
588 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
589 &pktNode->anchor, &pktListSize );
590 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
591
592 if ( !VOS_IS_STATUS_SUCCESS( status ) )
593 {
c_hpothu32490782014-03-14 19:14:34 +0530594 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700595 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700596 kfree_skb(skb);
597 return NETDEV_TX_OK;
598 }
599
600 if ( pktListSize == 1 )
601 {
602 /* In this context we cannot acquire any mutex etc. And to transmit
603 * this packet we need to call SME API. So to take care of this we will
604 * schedule a workqueue
605 */
606 schedule_work(&pPgBkAdapter->monTxWorkQueue);
607 }
608 return NETDEV_TX_OK;
609 }
610
611fail:
c_hpothu32490782014-03-14 19:14:34 +0530612 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700613 "%s: Packet Rcvd at Monitor interface is not proper,"
614 " Dropping the packet",
615 __func__);
616 kfree_skb(skb);
617 return NETDEV_TX_OK;
618}
Dino Mycled9b7cc12014-09-04 18:43:07 +0530619
620/**============================================================================
621 @brief hdd_dhcp_pkt_info() -
622 Function to log DHCP pkt info
623
624 @param skb : [in] pointer to OS packet (sk_buff)
625 @return : None
626 ===========================================================================*/
627
628void hdd_dhcp_pkt_info(struct sk_buff *skb)
629{
630 /* port no 67 (0x43) or 68 (0x44) */
631
632 if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_REQUEST_MSG)
633 hddLog(VOS_TRACE_LEVEL_INFO, FL("Request"));
634 else if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_RESPONSE_MSG)
635 hddLog(VOS_TRACE_LEVEL_INFO, FL("Response"));
636 else
637 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP invalid"));
638
639 hddLog(VOS_TRACE_LEVEL_INFO,
640 FL("DHCP Dest Addr: %pM Src Addr %pM "
641 " source port : %d, dest port : %d"),
642 skb->data, (skb->data + 6),
643 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))),
644 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))));
645
646 if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
647 (skb->data[DHCP_OPTION53_LENGTH_OFFSET] == DHCP_OPTION53_LENGTH)) {
648
649 switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
650 case DHCPDISCOVER:
651 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP DISCOVER"));
652 break;
653 case DHCPREQUEST:
654 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP REQUEST"));
655 break;
656 case DHCPOFFER:
657 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP OFFER"));
658 break;
659 case DHCPACK:
660 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP ACK"));
661 break;
662 case DHCPNAK:
663 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP NACK"));
664 break;
665 case DHCPRELEASE:
666 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP RELEASE"));
667 break;
668 case DHCPINFORM:
669 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP INFORM"));
670 break;
671
672 default:
673 hddLog(VOS_TRACE_LEVEL_INFO,
674 "%s: DHCP Not Defined OPTION53 : %d", __func__,
675 skb->data[DHCP_OPTION53_STATUS_OFFSET]);
676 }
677 }
678}
679
680/**============================================================================
681 @brief hdd_dump_dhcp_pkt() -
682 Function to dump DHCP packets in TX and RX path.
683
684 @param skb : [in] pointer to OS packet (sk_buff)
685 @param path : [in] bool indicating TX/RX path
686 @return : None
687 ===========================================================================*/
688void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path)
689{
690
691 if ((ntohs(*((u16*)((u8*)skb->data + ETH_TYPE_OFFSET)))
692 == ETH_TYPE_IP_PKT) ||
693 (ntohs(*((u8*)skb->data + PROTOCOL_OFFSET)) == UDP_PROTOCOL)) {
694
695 /* IP protocol 12 bytes of mac addresses in 802.3 header */
696 if ( ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
697 BOOTP_SERVER_PORT ||
698 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
699 BOOTP_CLIENT_PORT ||
700 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
701 BOOTP_SERVER_PORT ||
702 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
703 BOOTP_CLIENT_PORT ) {
704
705 if (path == TX_PATH) {
706 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP TX PATH"));
707 } else {
708 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP RX PATH"));
709 }
710
711 hdd_dhcp_pkt_info(skb);
712 }
713 }
714}
715
Jeff Johnson295189b2012-06-20 16:38:30 -0700716/**============================================================================
Katya Nigam77fcf582015-02-09 16:48:24 +0530717 @brief hdd_ibss_hard_start_xmit() - Function registered with the Linux OS for
718 transmitting packets in case of IBSS. There are 2 versions of this function.
719 One that uses locked queue and other that uses lockless queues. Both have been
720 retained to do some performance testing
721
722 @param skb : [in] pointer to OS packet (sk_buff)
723 @param dev : [in] pointer to network device
724
725 @return : NET_XMIT_DROP if packets are dropped
726 : NET_XMIT_SUCCESS if packet is enqueued succesfully
727 ===========================================================================*/
728 int hdd_ibss_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
729 {
730 VOS_STATUS status;
731 WLANTL_ACEnumType ac;
732 sme_QosWmmUpType up;
733 skb_list_node_t *pktNode = NULL;
734 hdd_list_node_t *anchor = NULL;
735 v_SIZE_t pktListSize = 0;
736 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
737 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
738 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
739 hdd_ibss_peer_info_t * pPeerInfo;
740 v_U8_t STAId = WLAN_MAX_STA_COUNT;
741 v_BOOL_t txSuspended = VOS_FALSE;
742 struct sk_buff *skb1;
743 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
744
745 if (NULL == pHddCtx || NULL == pHddStaCtx) {
746 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
747 "%s HDD context is NULL", __func__);
748 return NETDEV_TX_BUSY;
749 }
750 pPeerInfo = &pHddStaCtx->ibss_peer_info;
751 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
752
753 //Get TL AC corresponding to Qdisc queue index/AC.
754 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
755
756 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
757 {
758 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
759 "%s: Tx frame in disconnected state in IBSS mode", __func__);
760 ++pAdapter->stats.tx_dropped;
761 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
762 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
763 kfree_skb(skb);
764 return NETDEV_TX_OK;
765 }
766
767 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
768
769 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
770 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
771 vos_is_macaddr_group(pDestMacAddress)))
772 {
773 STAId = IBSS_BROADCAST_STAID;
774 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
775 "%s: BC/MC packet", __func__);
776 }
777 else if (STAId >= HDD_MAX_NUM_IBSS_STA)
778 {
779 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
780 "%s: Received Unicast frame with invalid staID", __func__);
781 ++pAdapter->stats.tx_dropped;
782 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
783 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
784 kfree_skb(skb);
785 return NETDEV_TX_OK;
786 }
787
788 //user priority from IP header, which is already extracted and set from
789 //select_queue call back function
790 up = skb->priority;
791 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
792
793 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
794 "%s: Classified as ac %d up %d", __func__, ac, up);
795
796 if ( pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP )
797 {
798 hdd_dump_dhcp_pkt(skb, TX_PATH);
799 }
800
801 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
802 hdd_list_size(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
803 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
804 {
805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
806 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
807 pPeerInfo->ibssStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
808 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
809 txSuspended = VOS_TRUE;
810 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
812 "%s: TX queue full for AC=%d Disable OS TX queue",
813 __func__, ac );
814 return NETDEV_TX_BUSY;
815 }
816
817 /* If 3/4th of the max queue size is used then enable the flag.
818 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
819 if (WLANTL_AC_BE == ac)
820 {
821 if (pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
822 {
823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
824 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
825 pAdapter->isVosLowResource = VOS_TRUE;
826 }
827 else
828 {
829 pAdapter->isVosLowResource = VOS_FALSE;
830 }
831 }
832
833 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
834
835 //Use the skb->cb field to hold the list node information
836 pktNode = (skb_list_node_t *)&skb->cb;
837
838 //Stick the OS packet inside this node.
839 pktNode->skb = skb;
840
841 //Stick the User Priority inside this node
842 pktNode->userPriority = up;
843
844 INIT_LIST_HEAD(&pktNode->anchor);
845
846 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
847 status = hdd_list_insert_back_size( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac],
848 &pktNode->anchor, &pktListSize );
849 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
850 if ( !VOS_IS_STATUS_SUCCESS( status ) )
851 {
852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
853 "%s:Insert Tx queue failed. Pkt dropped", __func__);
854 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
855 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
856 ++pAdapter->stats.tx_dropped;
857 kfree_skb(skb);
858 return NETDEV_TX_OK;
859 }
860
861 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
862 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
863 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
864
865 if (1 == pktListSize)
866 {
867 //Let TL know we have a packet to send for this AC
868 status = WLANTL_STAPktPending( pHddCtx->pvosContext, STAId, ac );
869
870 if ( !VOS_IS_STATUS_SUCCESS( status ) )
871 {
872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
873 "%s: Failed to signal TL for AC=%d STAId =%d",
874 __func__, ac, STAId );
875
876 /* Remove the packet from queue. It must be at the back of the queue, as TX thread
877 * cannot preempt us in the middle as we are in a soft irq context.
878 * Also it must be the same packet that we just allocated.
879 */
880 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
881 status = hdd_list_remove_back( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &anchor);
882 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
883 /* Free the skb only if we are able to remove it from the list.
884 * If we are not able to retrieve it from the list it means that
885 * the skb was pulled by TX Thread and is use so we should not free
886 * it here
887 */
888 if (VOS_IS_STATUS_SUCCESS(status))
889 {
890 pktNode = list_entry(anchor, skb_list_node_t, anchor);
891 skb1 = pktNode->skb;
892 kfree_skb(skb1);
893 }
894 ++pAdapter->stats.tx_dropped;
895 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
896 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
897 return NETDEV_TX_OK;
898 }
899 }
900
901 dev->trans_start = jiffies;
902
903 return NETDEV_TX_OK;
904 }
905
906/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530907 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700908 transmitting packets. There are 2 versions of this function. One that uses
909 locked queue and other that uses lockless queues. Both have been retained to
910 do some performance testing
911
912 @param skb : [in] pointer to OS packet (sk_buff)
913 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530914
Jeff Johnson295189b2012-06-20 16:38:30 -0700915 @return : NET_XMIT_DROP if packets are dropped
916 : NET_XMIT_SUCCESS if packet is enqueued succesfully
917 ===========================================================================*/
918int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
919{
920 VOS_STATUS status;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530921 WLANTL_ACEnumType qid, ac;
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 sme_QosWmmUpType up;
923 skb_list_node_t *pktNode = NULL;
924 hdd_list_node_t *anchor = NULL;
925 v_SIZE_t pktListSize = 0;
926 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
927 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700928 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700929 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Dino Mycled9b7cc12014-09-04 18:43:07 +0530930 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700931 v_BOOL_t txSuspended = VOS_FALSE;
Mihir Shetef8f74532014-12-04 11:53:34 +0530932 struct sk_buff *skb1;
Jeff Johnson295189b2012-06-20 16:38:30 -0700933
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530934 if (NULL == pHddCtx) {
935 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
936 "%s HDD context is NULL", __func__);
937 return NETDEV_TX_BUSY;
938 }
939
Jeff Johnson295189b2012-06-20 16:38:30 -0700940 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
941
Ravi Joshif9520d62013-10-18 04:11:46 -0700942 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530943 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700944 "%s is called when netif TX %d is disabled",
945 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530946 return NETDEV_TX_BUSY;
947 }
948
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530949 //Get TL Q index corresponding to Qdisc queue index/AC.
950 qid = hdd_QdiscAcToTlAC[skb->queue_mapping];
951 ac = qid;
952
953 if (qid == WLANTL_AC_HIGH_PRIO)
954 {
955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
956 "%s It must be a Eapol/Wapi/DHCP packet device_mode:%d",
957 __func__, pAdapter->device_mode);
958 ac = hddWmmUpToAcMap[skb->priority];
959 }
Ravi Joshicc57ed42013-10-12 16:31:25 -0700960
c_hpothu851d9862015-01-19 18:39:06 +0530961 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
962 {
963 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
964 FL("Tx frame in not associated state in %d context"),
965 pAdapter->device_mode);
966 ++pAdapter->stats.tx_dropped;
967 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530968 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
c_hpothu851d9862015-01-19 18:39:06 +0530969 kfree_skb(skb);
970 return NETDEV_TX_OK;
971 }
Shailender Karmuchia734f332013-04-19 14:02:48 -0700972 STAId = pHddStaCtx->conn_info.staId[0];
Jeff Johnson295189b2012-06-20 16:38:30 -0700973
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530974 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700975 //select_queue call back function
976 up = skb->priority;
977
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530978 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -0700979
980#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530981 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700982 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700983#endif // HDD_WMM_DEBUG
984
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530985 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
Mukul Sharma84f27252014-07-14 18:11:42 +0530986 {
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530987 vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
Mukul Sharma84f27252014-07-14 18:11:42 +0530988 }
Mukul Sharma84f27252014-07-14 18:11:42 +0530989
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530990 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700991 /*CR 463598,384996*/
992 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
993 *We check for +1 in the logic,to take care of Zero count which
994 *occurs very frequently in low traffic cases */
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530995 if((pAdapter->wmm_tx_queue[qid].count + 1) % 10 == 0)
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700996 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700997 /* 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 -0700998 * 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 +0530999 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 -07001000
Ravi Joshi8a934352013-09-25 16:46:58 -07001001 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301002 STAId, qid
Ravi Joshi8a934352013-09-25 16:46:58 -07001003 );
1004 if ( !VOS_IS_STATUS_SUCCESS( status ) )
1005 {
c_hpothu32490782014-03-14 19:14:34 +05301006 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -07001007 "%s: WLANTL_STAPktPending() returned error code %d",
1008 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001009 ++pAdapter->stats.tx_dropped;
1010 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301011 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Ravi Joshi8a934352013-09-25 16:46:58 -07001012 kfree_skb(skb);
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301013 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Ravi Joshi8a934352013-09-25 16:46:58 -07001014 return NETDEV_TX_OK;
1015 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -07001016 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001017 //If we have already reached the max queue size, disable the TX queue
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301018 if ( pAdapter->wmm_tx_queue[qid].count == pAdapter->wmm_tx_queue[qid].max_size)
Jeff Johnson295189b2012-06-20 16:38:30 -07001019 {
Ravi Joshicc57ed42013-10-12 16:31:25 -07001020 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301021 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[qid];
1022 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for QId %d"), qid);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001023 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301024 pAdapter->isTxSuspended[qid] = VOS_TRUE;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001025 txSuspended = VOS_TRUE;
Mihir Shete5d148f12014-12-16 17:54:49 +05301026 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_NETDEV,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301027 pAdapter->sessionId, qid));
Jeff Johnson295189b2012-06-20 16:38:30 -07001028 }
1029
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301030 /* If 3/4th of the max queue size is used then enable the flag.
1031 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301032 if (WLANTL_AC_BE == qid)
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301033 {
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301034 if (pAdapter->wmm_tx_queue[qid].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301035 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301036 pAdapter->isVosLowResource = VOS_TRUE;
1037 }
1038 else
1039 {
1040 pAdapter->isVosLowResource = VOS_FALSE;
1041 }
1042 }
1043
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301044 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Dino Mycled9b7cc12014-09-04 18:43:07 +05301045
Sachin Ahuja8c65f382014-12-12 15:34:21 +05301046 if (( NULL != pHddCtx ) &&
1047 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05301048 {
1049 hdd_dump_dhcp_pkt(skb, TX_PATH);
1050 }
1051
Jeff Johnson295189b2012-06-20 16:38:30 -07001052 if (VOS_TRUE == txSuspended)
1053 {
c_hpothu32490782014-03-14 19:14:34 +05301054 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301055 "%s: TX queue full for QId=%d Disable OS TX queue",
1056 __func__, qid );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +05301057 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07001058 }
1059
1060 //Use the skb->cb field to hold the list node information
1061 pktNode = (skb_list_node_t *)&skb->cb;
1062
1063 //Stick the OS packet inside this node.
1064 pktNode->skb = skb;
1065
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +05301066 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 pktNode->userPriority = up;
1068
1069
1070 INIT_LIST_HEAD(&pktNode->anchor);
1071
1072 //Insert the OS packet into the appropriate AC queue
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301073 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
1074 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[qid], &pktNode->anchor, &pktListSize );
1075 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001076
1077 if ( !VOS_IS_STATUS_SUCCESS( status ) )
1078 {
c_hpothu32490782014-03-14 19:14:34 +05301079 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001080 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301081 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 ++pAdapter->stats.tx_dropped;
1083 kfree_skb(skb);
1084 return NETDEV_TX_OK;
1085 }
1086
1087 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301088 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[qid];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07001089 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07001090
Kiet Lamf040f472013-11-20 21:15:23 +05301091 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
1092 {
1093 /* Function which will determine acquire admittance for a
1094 * WMM AC is required or not based on psb configuration done
1095 * in the framework
1096 */
1097 hdd_wmm_acquire_access_required(pAdapter, ac);
1098 }
1099
Jeff Johnson295189b2012-06-20 16:38:30 -07001100 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +05301101 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
1102 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 {
1104 granted = VOS_TRUE;
1105 }
1106 else
1107 {
1108 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +05301109 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 }
Nirav Shah4f765af2015-01-21 19:51:30 +05301111
1112 if ( (granted && ( pktListSize == 1 )) ||
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301113 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE) ||
1114 (qid == WLANTL_AC_HIGH_PRIO))
Jeff Johnson295189b2012-06-20 16:38:30 -07001115 {
1116 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +05301117 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -07001118 status = WLANTL_STAPktPending(
1119 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301120 STAId, qid );
Jeff Johnson295189b2012-06-20 16:38:30 -07001121 if ( !VOS_IS_STATUS_SUCCESS( status ) )
1122 {
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301123 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
1124 "%s: Failed to signal TL for QId=%d", __func__, qid );
Jeff Johnson295189b2012-06-20 16:38:30 -07001125
1126 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
1127 //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 +05301128 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
1129 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[qid], &anchor );
1130 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Mihir Shetef8f74532014-12-04 11:53:34 +05301131 /* Free the skb only if we are able to remove it from the list.
1132 * If we are not able to retrieve it from the list it means that
1133 * the skb was pulled by TX Thread and is use so we should not free
1134 * it here
1135 */
1136 if (VOS_IS_STATUS_SUCCESS(status))
1137 {
1138 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1139 skb1 = pktNode->skb;
1140 kfree_skb(skb1);
1141 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001142 ++pAdapter->stats.tx_dropped;
1143 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301144 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -07001145 return NETDEV_TX_OK;
1146 }
1147 }
1148
1149 dev->trans_start = jiffies;
1150
1151 return NETDEV_TX_OK;
1152}
1153
1154/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -07001155 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
1156
1157 @param pHddStaCtx : [in] pointer to HDD Station Context
1158 pMacAddress [in] pointer to Peer Mac address
1159 staID [out] pointer to Station Index
1160 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
1161 ===========================================================================*/
1162
1163VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1164{
1165 v_U8_t idx;
1166
1167 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
1168 {
1169 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
1170 pMacAddress, sizeof(v_MACADDR_t)))
1171 {
1172 *staId = pHddStaCtx->conn_info.staId[idx];
1173 return VOS_STATUS_SUCCESS;
1174 }
1175 }
1176
1177 return VOS_STATUS_E_FAILURE;
1178}
1179
1180/**============================================================================
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301181 @brief __hdd_tx_timeout() - Function handles timeout during transmission.
Jeff Johnson295189b2012-06-20 16:38:30 -07001182
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301183 @param dev : [in] pointer to network device
Jeff Johnson295189b2012-06-20 16:38:30 -07001184 @return : None
1185 ===========================================================================*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301186void __hdd_tx_timeout(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001187{
Ravi Joshicc57ed42013-10-12 16:31:25 -07001188 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mihir Shete0be28772015-02-17 18:42:14 +05301189 hdd_context_t *pHddCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001190 struct netdev_queue *txq;
Mihir Shete0be28772015-02-17 18:42:14 +05301191 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001192 int i = 0;
Mukul Sharma4b322632015-02-28 20:21:43 +05301193 int status = 0;
Mukul Sharma42b3d432014-10-16 16:13:40 +05301194 v_ULONG_t diff_in_jiffies = 0;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001195
Mihir Shetef3473692014-06-27 15:13:20 +05301196 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301197 "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu",
1198 __func__,jiffies,dev->trans_start);
Mihir Shetef3473692014-06-27 15:13:20 +05301199
c_hpothub8245442013-11-20 23:41:09 +05301200 if ( NULL == pAdapter )
1201 {
c_hpothu32490782014-03-14 19:14:34 +05301202 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301203 FL("pAdapter is NULL"));
1204 VOS_ASSERT(0);
1205 return;
1206 }
1207
Mihir Shete0be28772015-02-17 18:42:14 +05301208 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Mukul Sharma4b322632015-02-28 20:21:43 +05301209 status = wlan_hdd_validate_context(pHddCtx);
1210 if (status !=0 )
Mihir Shete0be28772015-02-17 18:42:14 +05301211 {
Mukul Sharma4b322632015-02-28 20:21:43 +05301212 return;
Mihir Shete0be28772015-02-17 18:42:14 +05301213 }
1214
Mihir Shetef3473692014-06-27 15:13:20 +05301215 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
1216
Jeff Johnson295189b2012-06-20 16:38:30 -07001217 //Getting here implies we disabled the TX queues for too long. Queues are
1218 //disabled either because of disassociation or low resource scenarios. In
1219 //case of disassociation it is ok to ignore this. But if associated, we have
1220 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -07001221
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301222 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001223 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
1224 pAdapter->wmm_tx_queue[0].count,
1225 pAdapter->wmm_tx_queue[1].count,
1226 pAdapter->wmm_tx_queue[2].count,
1227 pAdapter->wmm_tx_queue[3].count);
1228
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301229 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001230 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
1231 pAdapter->isTxSuspended[0],
1232 pAdapter->isTxSuspended[1],
1233 pAdapter->isTxSuspended[2],
1234 pAdapter->isTxSuspended[3]);
1235
Mihir Shete0be28772015-02-17 18:42:14 +05301236 for (i = 0; i < dev->num_tx_queues; i++)
Ravi Joshicc57ed42013-10-12 16:31:25 -07001237 {
1238 txq = netdev_get_tx_queue(dev, i);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301239 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301240 "Queue%d status: %d txq->trans_start %lu",
1241 i, netif_tx_queue_stopped(txq),txq->trans_start);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001242 }
1243
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301244 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001245 "carrier state: %d", netif_carrier_ok(dev));
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301246
Mihir Shetef3473692014-06-27 15:13:20 +05301247 /* continuousTxTimeoutCount will be reset whenever TL fetches packet
1248 * from HDD
1249 */
1250 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
1251
Mukul Sharma42b3d432014-10-16 16:13:40 +05301252 diff_in_jiffies = jiffies - pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut;
1253 if((pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount > 1)&&
1254 ((diff_in_jiffies) > (HDD_TX_TIMEOUT * 2 ))
1255 )
1256 {
1257 /*
1258 * In Open security case when there is no traffic is running, it may possible
1259 * tx time-out may once happen and later we recovered then we need to
1260 * reset the continuousTxTimeoutCount because it is only getting modified
1261 * when traffic is running. So if over a period of time if this count reaches
1262 * to HDD_TX_STALL_SSR_THRESHOLD then host is triggering false subsystem restart.
1263 * so in genuine Tx Time out case kernel will call the tx time-out back to back at
1264 * interval of HDD_TX_TIMEOUT.So now we are checking if previous TX TIME out was
1265 * occurred more then twice of HDD_TX_TIMEOUT back then we may recovered here.
1266 */
1267 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1268 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1269 FL("This is false alarm so resetting the continuousTxTimeoutCount"));
1270 }
1271
1272 //update last jiffies after the check
1273 pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut = jiffies;
1274
Mihir Shete327c2ab2014-11-13 15:17:02 +05301275 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
1276 HDD_TX_STALL_RECOVERY_THRESHOLD)
1277 {
1278 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1279 "%s: Request firmware for recovery",__func__);
1280 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
1281 }
1282
Mihir Shete0be28772015-02-17 18:42:14 +05301283 pRemainChanCtx = hdd_get_remain_on_channel_ctx(pHddCtx);
1284 if (!pRemainChanCtx)
Mihir Shetef3473692014-06-27 15:13:20 +05301285 {
Mihir Shete0be28772015-02-17 18:42:14 +05301286 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1287 HDD_TX_STALL_SSR_THRESHOLD)
1288 {
1289 // Driver could not recover, issue SSR
1290 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1291 "%s: Cannot recover from Data stall Issue SSR",
1292 __func__);
1293 WLANTL_FatalError();
1294 return;
1295 }
1296 }
1297 else
1298 {
1299 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1300 "Remain on channel in progress");
1301 /* The supplicant can retry "P2P Invitation Request" for 120 times
1302 * and so there is a possbility that we can remain off channel for
1303 * the entire duration of these retries(which can be max 60sec).
1304 * If we encounter such a case, let us not trigger SSR after 30sec
1305 * but wait for 60sec to let the device go on home channel and start
1306 * tx. If tx does not start within 70sec we will issue SSR.
1307 */
1308 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1309 HDD_TX_STALL_SSR_THRESHOLD_HIGH)
1310 {
1311 // Driver could not recover, issue SSR
1312 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1313 "%s: Cannot recover from Data stall Issue SSR",
1314 __func__);
1315 WLANTL_FatalError();
1316 return;
1317 }
Mihir Shetef3473692014-06-27 15:13:20 +05301318 }
1319
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301320 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
1321 * every 5sec. The TL debug spits out a lot of information on the
1322 * serial console, if it is called every time *hdd_tx_timeout* is
1323 * called then we may get a watchdog bite on the Application
1324 * processor, so ratelimit the TL debug logs.
1325 */
1326 if (__ratelimit(&hdd_tx_timeout_rs))
1327 {
1328 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +05301329 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301330 }
Mihir Shetef3473692014-06-27 15:13:20 +05301331
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301332}
Jeff Johnson295189b2012-06-20 16:38:30 -07001333
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301334/**============================================================================
1335 @brief hdd_tx_timeout() - Function called by OS if there is any
1336 timeout during transmission. Since HDD simply enqueues packet
1337 and returns control to OS right away, this would never be invoked
1338
1339 @param dev : [in] pointer to network device
1340 @return : None
1341 ===========================================================================*/
1342void hdd_tx_timeout(struct net_device *dev)
1343{
1344 vos_ssr_protect(__func__);
1345 __hdd_tx_timeout(dev);
1346 vos_ssr_unprotect(__func__);
1347}
Jeff Johnson295189b2012-06-20 16:38:30 -07001348
1349/**============================================================================
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301350 @brief __hdd_stats() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -07001351 device TX/RX statistic
1352
1353 @param dev : [in] pointer to Libra network device
1354
1355 @return : pointer to net_device_stats structure
1356 ===========================================================================*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301357struct net_device_stats* __hdd_stats(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001358{
1359 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +05301360
1361 if ( NULL == pAdapter )
1362 {
c_hpothu32490782014-03-14 19:14:34 +05301363 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301364 FL("pAdapter is NULL"));
1365 VOS_ASSERT(0);
1366 return NULL;
1367 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001368
1369 return &pAdapter->stats;
1370}
1371
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301372struct net_device_stats* hdd_stats(struct net_device *dev)
1373{
1374 struct net_device_stats* dev_stats;
1375
1376 vos_ssr_protect(__func__);
1377 dev_stats = __hdd_stats(dev);
1378 vos_ssr_unprotect(__func__);
1379
1380 return dev_stats;
1381}
Jeff Johnson295189b2012-06-20 16:38:30 -07001382
1383/**============================================================================
1384 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
1385 modules in HDD
1386
1387 @param pAdapter : [in] pointer to adapter context
1388 @return : VOS_STATUS_E_FAILURE if any errors encountered
1389 : VOS_STATUS_SUCCESS otherwise
1390 ===========================================================================*/
1391VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
1392{
1393 VOS_STATUS status = VOS_STATUS_SUCCESS;
1394 v_SINT_t i = -1;
1395
c_hpothub8245442013-11-20 23:41:09 +05301396 if ( NULL == pAdapter )
1397 {
c_hpothu32490782014-03-14 19:14:34 +05301398 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301399 FL("pAdapter is NULL"));
1400 VOS_ASSERT(0);
1401 return VOS_STATUS_E_FAILURE;
1402 }
1403
Jeff Johnson295189b2012-06-20 16:38:30 -07001404 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301405 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001406
1407 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
1408 //Will be zeroed out during alloc
1409
1410 while (++i != NUM_TX_QUEUES)
1411 {
1412 pAdapter->isTxSuspended[i] = VOS_FALSE;
1413 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1414 }
1415
1416 return status;
1417}
1418
1419
1420/**============================================================================
1421 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
1422 modules in HDD
1423
1424 @param pAdapter : [in] pointer to adapter context
1425 @return : VOS_STATUS_E_FAILURE if any errors encountered
1426 : VOS_STATUS_SUCCESS otherwise
1427 ===========================================================================*/
1428VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
1429{
1430 VOS_STATUS status = VOS_STATUS_SUCCESS;
1431 v_SINT_t i = -1;
1432
c_hpothub8245442013-11-20 23:41:09 +05301433 if ( NULL == pAdapter )
1434 {
c_hpothu32490782014-03-14 19:14:34 +05301435 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301436 FL("pAdapter is NULL"));
1437 VOS_ASSERT(0);
1438 return VOS_STATUS_E_FAILURE;
1439 }
1440
Jeff Johnson295189b2012-06-20 16:38:30 -07001441 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301442 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301443 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301444 FL("failed to flush tx queues"));
1445
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 while (++i != NUM_TX_QUEUES)
1447 {
1448 //Free up actual list elements in the Tx queue
1449 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1450 }
1451
1452 return status;
1453}
1454
1455
1456/**============================================================================
1457 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1458 modules in HDD
1459
1460 @param pAdapter : [in] pointer to adapter context
1461 @return : VOS_STATUS_E_FAILURE if any errors encountered
1462 : VOS_STATUS_SUCCESS otherwise
1463 ===========================================================================*/
1464VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1465{
1466 return hdd_flush_tx_queues(pAdapter);
1467}
1468
1469
1470/**============================================================================
1471 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1472
1473 @param pVosPacket : [in] pointer to vos packet
1474 @return : VOS_TRUE if the packet is EAPOL
1475 : VOS_FALSE otherwise
1476 ===========================================================================*/
1477
1478v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1479{
1480 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1481 v_BOOL_t fEAPOL = VOS_FALSE;
1482 void *pBuffer = NULL;
1483
1484
1485 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1486 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
Abhishek Singhfa011222014-04-14 10:57:08 +05301487 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001488 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301489 if ( pBuffer && *(unsigned short*)pBuffer ==
1490 vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001491 {
1492 fEAPOL = VOS_TRUE;
1493 }
1494 }
1495
1496 return fEAPOL;
1497}
1498
Abhishek Singhfa011222014-04-14 10:57:08 +05301499/**============================================================================
Nirav Shah4f765af2015-01-21 19:51:30 +05301500 @brief hdd_FindEapolSubType() - Find EAPOL SubType.
1501
1502 @param pVosPacket : [in] pointer to vos packet
1503 @return : EAPOL_SubType value
1504 ===========================================================================*/
1505EAPOL_SubType hdd_FindEapolSubType( vos_pkt_t *pVosPacket )
1506{
1507 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1508 void *pBuffer = NULL;
1509 EAPOL_SubType subType = EAPOL_UNKNOWN;
1510 v_U16_t keyInfo;
1511 vosStatus = vos_pkt_peek_data( pVosPacket,
1512 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_SUB_TYPE_OFFSET,
1513 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1514 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1515 {
1516 if ( pBuffer )
1517 {
1518 keyInfo = (*(unsigned short*)pBuffer &
1519 HDD_ETHERTYPE_802_1_X_SUB_TYPE_MASK);
1520
1521 switch (keyInfo) {
1522 case HDD_ETHERTYPE_802_1_X_M1_VALUE:
1523 subType = EAPOL_M1;
1524 break;
1525 case HDD_ETHERTYPE_802_1_X_M2_VALUE:
1526 subType = EAPOL_M2;
1527 break;
1528 case HDD_ETHERTYPE_802_1_X_M3_VALUE:
1529 subType = EAPOL_M3;
1530 break;
1531 case HDD_ETHERTYPE_802_1_X_M4_VALUE:
1532 subType = EAPOL_M4;
1533 break;
1534 default:
1535 break;
1536 }
1537 }
1538 }
1539
1540 return subType;
1541}
1542
1543/**============================================================================
Abhishek Singhfa011222014-04-14 10:57:08 +05301544 @brief hdd_IsARP() - Checks the packet is ARP or not.
1545
1546 @param pVosPacket : [in] pointer to vos packet
1547 @return : VOS_TRUE if the packet is ARP
1548 : VOS_FALSE otherwise
1549 ===========================================================================*/
1550
1551v_BOOL_t hdd_IsARP( vos_pkt_t *pVosPacket )
1552{
1553 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1554 v_BOOL_t fIsARP = VOS_FALSE;
1555 void *pBuffer = NULL;
1556
1557
1558 vosStatus = vos_pkt_peek_data( pVosPacket,
1559 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1560 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1561 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1562 {
1563 if ( pBuffer && *(unsigned short*)pBuffer ==
1564 vos_cpu_to_be16(HDD_ETHERTYPE_ARP) )
1565 {
1566 fIsARP = VOS_TRUE;
1567 }
1568 }
1569
1570 return fIsARP;
1571}
Jeff Johnson295189b2012-06-20 16:38:30 -07001572
1573#ifdef FEATURE_WLAN_WAPI // Need to update this function
1574/**============================================================================
1575 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1576
1577 @param pVosPacket : [in] pointer to vos packet
1578 @return : VOS_TRUE if the packet is WAI
1579 : VOS_FALSE otherwise
1580 ===========================================================================*/
1581
1582v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1583{
1584 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1585 v_BOOL_t fIsWAI = VOS_FALSE;
1586 void *pBuffer = NULL;
1587
1588 // Need to update this function
1589 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1590 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1591
1592 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1593 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301594 if ( pBuffer && *(unsigned short*)pBuffer ==
1595 vos_cpu_to_be16(HDD_ETHERTYPE_WAI) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001596 {
1597 fIsWAI = VOS_TRUE;
1598 }
1599 }
1600
1601 return fIsWAI;
1602}
1603#endif /* FEATURE_WLAN_WAPI */
1604
1605/**============================================================================
1606 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1607 to indicate that a packet has been transmitted across the SDIO bus
1608 succesfully. OS packet resources can be released after this cbk.
1609
1610 @param vosContext : [in] pointer to VOS context
1611 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1612 @param vosStatusIn : [in] status of the transmission
1613
1614 @return : VOS_STATUS_E_FAILURE if any errors encountered
1615 : VOS_STATUS_SUCCESS otherwise
1616 ===========================================================================*/
1617VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1618 vos_pkt_t *pVosPacket,
1619 VOS_STATUS vosStatusIn )
1620{
1621 VOS_STATUS status = VOS_STATUS_SUCCESS;
1622 hdd_adapter_t *pAdapter = NULL;
1623 hdd_context_t *pHddCtx = NULL;
1624 void* pOsPkt = NULL;
1625
1626 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1627 {
c_hpothu32490782014-03-14 19:14:34 +05301628 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301629 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001630 return VOS_STATUS_E_FAILURE;
1631 }
1632
1633 //Return the skb to the OS
1634 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301635 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 {
1637 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301638 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301639 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001640 vos_pkt_return_packet( pVosPacket );
1641 return VOS_STATUS_E_FAILURE;
1642 }
1643
1644 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001645 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001646 //Get the Adapter context.
1647 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301648 if (pAdapter == NULL || WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
Jeff Johnson295189b2012-06-20 16:38:30 -07001649 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301650 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1651 "%s: Invalid adapter %p", __func__, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001652 }
1653 else
1654 {
1655 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1656 }
1657
1658 kfree_skb((struct sk_buff *)pOsPkt);
1659
1660 //Return the VOS packet resources.
1661 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301662 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001663 {
c_hpothu32490782014-03-14 19:14:34 +05301664 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301665 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 }
1667
1668 return status;
1669}
1670
Katya Nigamf944e5e2015-02-10 15:05:43 +05301671/**============================================================================
1672 @brief hdd_ibss_tx_fetch_packet_cbk() - Callback function invoked by TL to
1673 fetch a packet for transmission.
1674
1675 @param vosContext : [in] pointer to VOS context
1676 @param staId : [in] Station for which TL is requesting a pkt
1677 @param ac : [in] access category requested by TL
1678 @param pVosPacket : [out] pointer to VOS packet packet pointer
1679 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1680
1681 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1682 : VOS_STATUS_E_FAILURE if any errors encountered
1683 : VOS_STATUS_SUCCESS otherwise
1684 ===========================================================================*/
1685VOS_STATUS hdd_ibss_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1686 v_U8_t *pStaId,
1687 WLANTL_ACEnumType ac,
1688 vos_pkt_t **ppVosPacket,
1689 WLANTL_MetaInfoType *pPktMetaInfo )
1690{
1691 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1692 hdd_adapter_t *pAdapter = NULL;
1693 hdd_list_node_t *anchor = NULL;
1694 skb_list_node_t *pktNode = NULL;
1695 struct sk_buff *skb = NULL;
1696 vos_pkt_t *pVosPacket = NULL;
1697 v_MACADDR_t* pDestMacAddress = NULL;
1698 v_TIME_t timestamp;
1699 v_SIZE_t size = 0;
1700 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1701 hdd_context_t *pHddCtx = NULL;
1702 hdd_station_ctx_t *pHddStaCtx = NULL;
1703 hdd_ibss_peer_info_t *pPeerInfo = NULL;
1704 v_U8_t proto_type = 0;
1705
1706 //Sanity check on inputs
1707 if ( ( NULL == vosContext ) ||
1708 ( NULL == pStaId ) ||
1709 ( NULL == ppVosPacket ) ||
1710 ( NULL == pPktMetaInfo ) )
1711 {
1712 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1713 "%s: Null Params being passed", __func__);
1714 return VOS_STATUS_E_FAILURE;
1715 }
1716
1717 //Get the HDD context.
1718 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1719 if ( NULL == pHddCtx )
1720 {
1721 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1722 "%s: HDD adapter context is Null", __func__);
1723 return VOS_STATUS_E_FAILURE;
1724 }
1725
1726 STAId = *pStaId;
1727 pAdapter = pHddCtx->sta_to_adapter[STAId];
1728 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1729 {
1730 VOS_ASSERT(0);
1731 return VOS_STATUS_E_FAILURE;
1732 }
1733
1734 pHddStaCtx = &pAdapter->sessionCtx.station;
1735 pPeerInfo = &pHddStaCtx->ibss_peer_info;
1736
1737 if (FALSE == pPeerInfo->ibssStaInfo[STAId].isUsed )
1738 {
1739 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1740 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1741 return VOS_STATUS_E_FAILURE;
1742 }
1743
1744 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1745
1746 *ppVosPacket = NULL;
1747
1748 //Make sure the AC being asked for is sane
1749 if( ac > WLANTL_MAX_AC || ac < 0)
1750 {
1751 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1752 "%s: Invalid AC %d passed by TL", __func__, ac);
1753 return VOS_STATUS_E_FAILURE;
1754 }
1755
1756 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1757
1758 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
1759 "%s: AC %d passed by TL", __func__, ac);
1760
1761 //Get the vos packet before so that we are prepare for VOS low reseurce condition
1762 //This simplifies the locking and unlocking of Tx queue
1763 status = vos_pkt_wrap_data_packet( &pVosPacket,
1764 VOS_PKT_TYPE_TX_802_3_DATA,
1765 NULL, //OS Pkt is not being passed
1766 hdd_tx_low_resource_cbk,
1767 pAdapter );
1768
1769 if ((status == VOS_STATUS_E_ALREADY) || (status == VOS_STATUS_E_RESOURCES))
1770 {
1771 //Remember VOS is in a low resource situation
1772 pAdapter->isVosOutOfResource = VOS_TRUE;
1773 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
1774 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
1775 "%s: VOSS in Low Resource scenario", __func__);
1776 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1777 return VOS_STATUS_E_FAILURE;
1778 }
1779
1780 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there.
1781 Do not get next AC as the other branch does.
1782 */
1783 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1784 hdd_list_size(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &size);
1785
1786 if (0 == size)
1787 {
1788 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1789 vos_pkt_return_packet(pVosPacket);
1790 return VOS_STATUS_E_EMPTY;
1791 }
1792
1793 status = hdd_list_remove_front( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1794 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1795
1796 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1797 "%s: AC %d has packets pending", __func__, ac);
1798
1799 if(VOS_STATUS_SUCCESS == status)
1800 {
1801 //If success then we got a valid packet from some AC
1802 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1803 skb = pktNode->skb;
1804 }
1805 else
1806 {
1807 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1808 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1809 "%s: Error in de-queuing skb from Tx queue status = %d",
1810 __func__, status );
1811 vos_pkt_return_packet(pVosPacket);
1812 return VOS_STATUS_E_FAILURE;
1813 }
1814
1815 //Attach skb to VOS packet.
1816 status = vos_pkt_set_os_packet( pVosPacket, skb );
1817 if (status != VOS_STATUS_SUCCESS)
1818 {
1819 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1820 "%s: Error attaching skb", __func__);
1821 vos_pkt_return_packet(pVosPacket);
1822 ++pAdapter->stats.tx_dropped;
1823 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1824 kfree_skb(skb);
1825 return VOS_STATUS_E_FAILURE;
1826 }
1827
1828 //Return VOS packet to TL;
1829 *ppVosPacket = pVosPacket;
1830
1831 //Fill out the meta information needed by TL
1832 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1833 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1834 if ( 1 < size )
1835 {
1836 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1837 }
1838 else
1839 {
1840 pPktMetaInfo->bMorePackets = 0;
1841 }
1842
1843 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1844 pPktMetaInfo->ucIsEapol = 0;
1845 else
1846 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1847
1848 if ((NULL != pHddCtx) &&
1849 (pHddCtx->cfg_ini->gEnableDebugLog))
1850 {
1851 proto_type = vos_pkt_get_proto_type(skb,
1852 pHddCtx->cfg_ini->gEnableDebugLog);
1853 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1854 {
1855 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1856 "IBSS STA TX EAPOL");
1857 }
1858 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1859 {
1860 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1861 "IBSS STA TX DHCP");
1862 }
1863 }
1864
1865 pPktMetaInfo->ucUP = pktNode->userPriority;
1866 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1867 pPktMetaInfo->ucType = 0;
1868
1869 //Extract the destination address from ethernet frame
1870 pDestMacAddress = (v_MACADDR_t*)skb->data;
1871
1872 // we need 802.3 to 802.11 frame translation
1873 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1874 pPktMetaInfo->ucDisableFrmXtl = 0;
1875 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1876 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1877
1878 if ( (pPeerInfo->ibssStaInfo[STAId].txSuspended[ac]) &&
1879 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1880 {
1881 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1882 "%s: TX queue re-enabled", __func__);
1883 pPeerInfo->ibssStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1884 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1885 }
1886
1887 // We're giving the packet to TL so consider it transmitted from
1888 // a statistics perspective. We account for it here instead of
1889 // when the packet is returned for two reasons. First, TL will
1890 // manipulate the skb to the point where the len field is not
1891 // accurate, leading to inaccurate byte counts if we account for
1892 // it later. Second, TL does not provide any feedback as to
1893 // whether or not the packet was successfully sent over the air,
1894 // so the packet counts will be the same regardless of where we
1895 // account for them
1896 pAdapter->stats.tx_bytes += skb->len;
1897 ++pAdapter->stats.tx_packets;
1898 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1899 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1900 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1901
1902 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1903 "%s: Valid VOS PKT returned to TL", __func__);
1904
1905 return status;
1906}
Jeff Johnson295189b2012-06-20 16:38:30 -07001907
1908/**============================================================================
1909 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1910 fetch a packet for transmission.
1911
1912 @param vosContext : [in] pointer to VOS context
1913 @param staId : [in] Station for which TL is requesting a pkt
1914 @param ac : [in] access category requested by TL
1915 @param pVosPacket : [out] pointer to VOS packet packet pointer
1916 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1917
1918 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1919 : VOS_STATUS_E_FAILURE if any errors encountered
1920 : VOS_STATUS_SUCCESS otherwise
1921 ===========================================================================*/
1922VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1923 v_U8_t *pStaId,
1924 WLANTL_ACEnumType ac,
1925 vos_pkt_t **ppVosPacket,
1926 WLANTL_MetaInfoType *pPktMetaInfo )
1927{
1928 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1929 hdd_adapter_t *pAdapter = NULL;
1930 hdd_context_t *pHddCtx = NULL;
1931 hdd_list_node_t *anchor = NULL;
1932 skb_list_node_t *pktNode = NULL;
1933 struct sk_buff *skb = NULL;
1934 vos_pkt_t *pVosPacket = NULL;
1935 v_MACADDR_t* pDestMacAddress = NULL;
1936 v_TIME_t timestamp;
1937 WLANTL_ACEnumType newAc;
1938 v_SIZE_t size = 0;
Abhishek Singhfa011222014-04-14 10:57:08 +05301939 v_U16_t packet_size;
Jeff Johnson295189b2012-06-20 16:38:30 -07001940 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001941 v_U8_t proto_type = 0;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301942 WLANTL_ACEnumType actualAC;
Jeff Johnson295189b2012-06-20 16:38:30 -07001943
1944 //Sanity check on inputs
1945 if ( ( NULL == vosContext ) ||
1946 ( NULL == pStaId ) ||
1947 ( NULL == ppVosPacket ) ||
1948 ( NULL == pPktMetaInfo ) )
1949 {
c_hpothu32490782014-03-14 19:14:34 +05301950 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301951 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001952 return VOS_STATUS_E_FAILURE;
1953 }
1954
1955 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001956 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001957 if(pHddCtx == NULL)
1958 {
c_hpothu32490782014-03-14 19:14:34 +05301959 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301960 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 return VOS_STATUS_E_FAILURE;
1962 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001963 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001964 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001965 {
c_hpothu32490782014-03-14 19:14:34 +05301966 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301967 FL("invalid adapter:%p for staId:%u"), pAdapter, *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001968 VOS_ASSERT(0);
1969 return VOS_STATUS_E_FAILURE;
1970 }
1971
1972 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1973
1974 *ppVosPacket = NULL;
1975
1976 //Make sure the AC being asked for is sane
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301977 if (ac > WLANTL_AC_HIGH_PRIO || ac < 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 {
c_hpothu32490782014-03-14 19:14:34 +05301979 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301980 "%s: Invalid QId %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001981 return VOS_STATUS_E_FAILURE;
1982 }
1983
1984 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1985
1986#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301987 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301988 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001989#endif // HDD_WMM_DEBUG
1990
Jeff Johnson295189b2012-06-20 16:38:30 -07001991 // do we have any packets pending in this AC?
1992 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1993 if( size > 0 )
1994 {
1995 // yes, so process it
1996#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301997 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001998 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001999#endif // HDD_WMM_DEBUG
2000 }
2001 else
2002 {
2003 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
2004#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05302005 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002006 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002007#endif // HDD_WMM_DEBUG
2008 return VOS_STATUS_E_FAILURE;
2009 }
2010
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302011 // Note here that we are not checking "wmmAcAccessAllowed" for packets
2012 // in new queue since there is no one AC associated to the new queue.
2013 // Since there will be either eapol or dhcp pkts in new queue overlooking
2014 // this should be okay from implicit QoS perspective.
2015 if (ac != WLANTL_AC_HIGH_PRIO)
2016 {
2017 // We find an AC with packets
2018 // or we determine we have no more packets to send
2019 // HDD is not allowed to change AC.
2020
2021 // has this AC been admitted? or
2022 // To allow EAPOL packets when not authenticated
2023 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
2024 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
2025 {
2026 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
2027#ifdef HDD_WMM_DEBUG
2028 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
2029 "%s: no packets pending", __func__);
2030#endif // HDD_WMM_DEBUG
2031 return VOS_STATUS_E_FAILURE;
2032 }
2033 }
2034
Jeff Johnson295189b2012-06-20 16:38:30 -07002035 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
2036 //This simplifies the locking and unlocking of Tx queue
2037 status = vos_pkt_wrap_data_packet( &pVosPacket,
2038 VOS_PKT_TYPE_TX_802_3_DATA,
2039 NULL, //OS Pkt is not being passed
2040 hdd_tx_low_resource_cbk,
2041 pAdapter );
2042
2043 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
2044 {
2045 //Remember VOS is in a low resource situation
2046 pAdapter->isVosOutOfResource = VOS_TRUE;
2047 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05302048 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 -07002049 //TL will now think we have no more packets in this AC
2050 return VOS_STATUS_E_FAILURE;
2051 }
2052
2053 //Remove the packet from the queue
2054 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
2055 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
2056 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
2057
2058 if(VOS_STATUS_SUCCESS == status)
2059 {
2060 //If success then we got a valid packet from some AC
2061 pktNode = list_entry(anchor, skb_list_node_t, anchor);
2062 skb = pktNode->skb;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302063 actualAC = hddWmmUpToAcMap[pktNode->userPriority];
2064 if (actualAC >= WLANTL_MAX_AC)
2065 {
2066 /* To fix klocwork */
2067 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
2068 "%s: Invalid AC for packet:%d", __func__, actualAC);
2069 actualAC = WLANTL_AC_BE;
2070 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002071 }
2072 else
2073 {
2074 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05302075 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002076 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07002077 vos_pkt_return_packet(pVosPacket);
2078 return VOS_STATUS_E_FAILURE;
2079 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002080 //Attach skb to VOS packet.
2081 status = vos_pkt_set_os_packet( pVosPacket, skb );
2082 if (status != VOS_STATUS_SUCCESS)
2083 {
c_hpothu32490782014-03-14 19:14:34 +05302084 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002085 vos_pkt_return_packet(pVosPacket);
2086 ++pAdapter->stats.tx_dropped;
2087 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
2088 kfree_skb(skb);
2089 return VOS_STATUS_E_FAILURE;
2090 }
2091
2092 //Just being paranoid. To be removed later
2093 if(pVosPacket == NULL)
2094 {
c_hpothu32490782014-03-14 19:14:34 +05302095 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 -07002096 ++pAdapter->stats.tx_dropped;
2097 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
2098 kfree_skb(skb);
2099 return VOS_STATUS_E_FAILURE;
2100 }
2101
Dino Mycle3b9536d2014-07-09 22:05:24 +05302102#ifdef WLAN_FEATURE_LINK_LAYER_STATS
2103 {
2104 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
2105 /* vos_is_macaddr_group expects data in v_MACADDR_t format
2106 */
2107 if (vos_is_macaddr_group(pDestMacAddress))
2108 {
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302109 pAdapter->hdd_stats.hddTxRxStats.txMcast[actualAC]++;
Dino Mycle3b9536d2014-07-09 22:05:24 +05302110 }
2111
2112 }
2113
2114#endif
2115
Chilam NG571c65a2013-01-19 12:27:36 +05302116#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002117 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05302118 {
2119 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05302120 u8 mac[6];
2121
Hoonki Lee387663d2013-02-05 18:08:43 -08002122 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05302123
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002124 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302125 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05302126 "broadcast packet, not adding to peer list");
2127 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2128 mac, 6) != 0) {
c_hpothu32490782014-03-14 19:14:34 +05302129 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002130 "extract mac: " MAC_ADDRESS_STR,
2131 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05302132
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002133 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05302134 } else {
c_hpothu32490782014-03-14 19:14:34 +05302135 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05302136 "packet da is bssid, not adding to peer list");
2137 }
2138 }
2139#endif
2140
Jeff Johnson295189b2012-06-20 16:38:30 -07002141 //Return VOS packet to TL;
2142 *ppVosPacket = pVosPacket;
2143
2144 //Fill out the meta information needed by TL
2145 //FIXME This timestamp is really the time stamp of wrap_data_packet
2146 vos_pkt_get_timestamp( pVosPacket, &timestamp );
2147 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
2148
2149 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
2150 pPktMetaInfo->ucIsEapol = 0;
Nirav Shah4f765af2015-01-21 19:51:30 +05302151 else
2152 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002153 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
Nirav Shah4f765af2015-01-21 19:51:30 +05302154 if(pPktMetaInfo->ucIsEapol)
2155 pPktMetaInfo->ucEapolSubType = hdd_FindEapolSubType( pVosPacket );
2156 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002157
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302158 if ((NULL != pHddCtx) &&
2159 (pHddCtx->cfg_ini->gEnableDebugLog))
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002160 {
2161 proto_type = vos_pkt_get_proto_type(skb,
2162 pHddCtx->cfg_ini->gEnableDebugLog);
2163 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2164 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4f765af2015-01-21 19:51:30 +05302166 "STA TX EAPOL SubType %d",pPktMetaInfo->ucEapolSubType);
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002167 }
2168 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2169 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302170 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002171 "STA TX DHCP");
2172 }
2173 }
2174
Abhishek Singhfa011222014-04-14 10:57:08 +05302175 vos_pkt_get_packet_length( pVosPacket,&packet_size );
2176 if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
2177 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
2178
Jeff Johnson295189b2012-06-20 16:38:30 -07002179#ifdef FEATURE_WLAN_WAPI
2180 // Override usIsEapol value when its zero for WAPI case
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302181 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002182#endif /* FEATURE_WLAN_WAPI */
2183
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302184 /* 1. Check if ACM is set for this AC
2185 * 2. If set, check if this AC had already admitted
2186 * 3. If not already admitted, downgrade the UP to next best UP
2187 * 4. Allow only when medium time is non zero when Addts accepted
2188 * else downgrade traffic. we opted downgrading over Delts when
2189 * medium time is zero because while doing downgradig driver is not
2190 * clearing the wmm context so consider in subsequent roaming
2191 * if AP (new or same AP) accept the Addts with valid medium time
2192 * no application support is required where if we have opted
2193 * delts Applications have to again do Addts or STA will never
2194 * go for Addts.
2195 */
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302196 pPktMetaInfo->ac = actualAC;
2197 if(!pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcAccessRequired ||
2198 (pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid &&
2199 pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07002200 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302201 pPktMetaInfo->ucUP = pktNode->userPriority;
2202 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07002203 }
2204 else
2205 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302206 //Downgrade the UP
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302207 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid;
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302208 newAc = WLANTL_AC_BK;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302209 for (i=actualAC-1; i>0; i--)
Jeff Johnson295189b2012-06-20 16:38:30 -07002210 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302211 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
2212 {
2213 newAc = i;
2214 break;
2215 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002216 }
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302217 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
2218 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
2219 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
2220 "Downgrading UP %d to UP %d ",
2221 pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 }
2223
Girish Gowlibf0e1ab2015-01-19 16:05:16 +05302224 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
2225 {
2226 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
2227 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302228
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
2230 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
2231 if ( 1 < size )
2232 {
2233 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
2234 }
2235 else
2236 {
2237 pPktMetaInfo->bMorePackets = 0;
2238 }
2239
2240 //Extract the destination address from ethernet frame
2241 pDestMacAddress = (v_MACADDR_t*)skb->data;
2242 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
2243 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
2244
2245
2246
2247 // if we are in a backpressure situation see if we can turn the hose back on
2248 if ( (pAdapter->isTxSuspended[ac]) &&
2249 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
2250 {
2251 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
2252 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05302253 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002254 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07002255 pAdapter->isTxSuspended[ac] = VOS_FALSE;
2256 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
2257 skb_get_queue_mapping(skb) ));
Mihir Shete5d148f12014-12-16 17:54:49 +05302258 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_WAKE_NETDEV,
2259 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -07002260 }
2261
2262
2263 // We're giving the packet to TL so consider it transmitted from
2264 // a statistics perspective. We account for it here instead of
2265 // when the packet is returned for two reasons. First, TL will
2266 // manipulate the skb to the point where the len field is not
2267 // accurate, leading to inaccurate byte counts if we account for
2268 // it later. Second, TL does not provide any feedback as to
2269 // whether or not the packet was successfully sent over the air,
2270 // so the packet counts will be the same regardless of where we
2271 // account for them
2272 pAdapter->stats.tx_bytes += skb->len;
2273 ++pAdapter->stats.tx_packets;
2274 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
2275 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05302276 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002277
Leo Chang50bbd252013-04-25 14:58:01 -07002278 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
2279 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07002280 {
2281 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
2282 {
c_hpothu32490782014-03-14 19:14:34 +05302283 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002284 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002285 return VOS_STATUS_E_FAILURE;
2286 }
2287 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
2288 {
2289 if(0 == pHddCtx->tmInfo.txFrameCount)
2290 {
2291 /* Just recovered from sleep timeout */
2292 pHddCtx->tmInfo.lastOpenTs = timestamp;
2293 }
2294
Leo Chang50bbd252013-04-25 14:58:01 -07002295 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
2296 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002297 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
2298 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002299 /* During TX open duration, TX frame count is larger than threshold
2300 * Block TX during Sleep time */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302301 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002302 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07002303 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002304 pHddCtx->tmInfo.lastblockTs = timestamp;
2305 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
2306 {
2307 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
2308 }
2309 }
2310 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
2311 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
2312 {
2313 /* During TX open duration, TX frame count is less than threshold
2314 * Reset count and timestamp to prepare next cycle */
2315 pHddCtx->tmInfo.lastOpenTs = timestamp;
2316 pHddCtx->tmInfo.txFrameCount = 0;
2317 }
2318 else
2319 {
2320 /* Do Nothing */
2321 }
2322 pHddCtx->tmInfo.txFrameCount++;
2323 }
2324 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
2325 }
2326
2327
2328#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05302329 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 -07002330#endif // HDD_WMM_DEBUG
2331
2332 return status;
2333}
2334
2335
2336/**============================================================================
2337 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
2338 case where VOS packets are not available at the time of the call to get
2339 packets. This callback function is invoked by VOS when packets are
2340 available.
2341
2342 @param pVosPacket : [in] pointer to VOS packet
2343 @param userData : [in] opaque user data that was passed initially
2344
2345 @return : VOS_STATUS_E_FAILURE if any errors encountered,
2346 : VOS_STATUS_SUCCESS otherwise
2347 =============================================================================*/
2348VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
2349 v_VOID_t *userData )
2350{
2351 VOS_STATUS status;
2352 v_SINT_t i = 0;
2353 v_SIZE_t size = 0;
2354 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
2355
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302356 if (NULL == pAdapter || WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
Jeff Johnson295189b2012-06-20 16:38:30 -07002357 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302358 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2359 FL("Invalid adapter %p"), pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002360 return VOS_STATUS_E_FAILURE;
2361 }
2362
2363 //Return the packet to VOS. We just needed to know that VOS is out of low resource
2364 //situation. Here we will only signal TL that there is a pending data for a STA.
2365 //VOS packet will be requested (if needed) when TL comes back to fetch data.
2366 vos_pkt_return_packet( pVosPacket );
2367
2368 pAdapter->isVosOutOfResource = VOS_FALSE;
2369
2370 //Indicate to TL that there is pending data if a queue is non empty
2371 for( i=NUM_TX_QUEUES-1; i>=0; --i )
2372 {
2373 size = 0;
2374 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
2375 if ( size > 0 )
2376 {
2377 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
2378 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
2379 (WLANTL_ACEnumType)i );
2380 if( !VOS_IS_STATUS_SUCCESS( status ) )
2381 {
c_hpothu32490782014-03-14 19:14:34 +05302382 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302383 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07002384 }
2385 }
2386 }
2387
2388 return VOS_STATUS_SUCCESS;
2389}
2390
2391
2392/**============================================================================
2393 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
2394 TL will call this to notify the HDD when one or more packets were
2395 received for a registered STA.
2396
2397 @param vosContext : [in] pointer to VOS context
2398 @param pVosPacketChain : [in] pointer to VOS packet chain
2399 @param staId : [in] Station Id
2400 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
2401
2402 @return : VOS_STATUS_E_FAILURE if any errors encountered,
2403 : VOS_STATUS_SUCCESS otherwise
2404 ===========================================================================*/
2405VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
2406 vos_pkt_t *pVosPacketChain,
2407 v_U8_t staId,
2408 WLANTL_RxMetaInfoType* pRxMetaInfo )
2409{
2410 hdd_adapter_t *pAdapter = NULL;
2411 hdd_context_t *pHddCtx = NULL;
2412 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2413 int rxstat;
2414 struct sk_buff *skb = NULL;
2415 vos_pkt_t* pVosPacket;
2416 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002417 v_U8_t proto_type;
Nirav Shah4f765af2015-01-21 19:51:30 +05302418 EAPOL_SubType eapolSubType;
Jeff Johnson295189b2012-06-20 16:38:30 -07002419
2420 //Sanity check on inputs
2421 if ( ( NULL == vosContext ) ||
2422 ( NULL == pVosPacketChain ) ||
2423 ( NULL == pRxMetaInfo ) )
2424 {
c_hpothu32490782014-03-14 19:14:34 +05302425 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302426 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002427 return VOS_STATUS_E_FAILURE;
2428 }
2429
Kiet Lam3c2ee302014-03-23 23:23:22 -07002430 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07002431 if ( NULL == pHddCtx )
2432 {
c_hpothu32490782014-03-14 19:14:34 +05302433 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302434 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002435 return VOS_STATUS_E_FAILURE;
2436 }
2437
2438 pAdapter = pHddCtx->sta_to_adapter[staId];
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302439 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002440 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302441 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2442 FL("Invalid adapter %p for staId %u"), pAdapter, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002443 return VOS_STATUS_E_FAILURE;
2444 }
2445
2446 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
2447
2448 // walk the chain until all are processed
2449 pVosPacket = pVosPacketChain;
2450 do
2451 {
2452 // get the pointer to the next packet in the chain
2453 // (but don't unlink the packet since we free the entire chain later)
2454 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
2455
2456 // both "success" and "empty" are acceptable results
2457 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
2458 {
2459 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302460 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302461 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002462 return VOS_STATUS_E_FAILURE;
2463 }
2464
Nirav Shah4f765af2015-01-21 19:51:30 +05302465 if (pHddCtx->cfg_ini->gEnableDebugLog)
2466 {
2467 if (hdd_IsEAPOLPacket(pVosPacket))
2468 eapolSubType = hdd_FindEapolSubType(pVosPacket);
2469 }
2470
Jeff Johnson295189b2012-06-20 16:38:30 -07002471 // Extract the OS packet (skb).
2472 // Tell VOS to detach the OS packet from the VOS packet
2473 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
2474 if(!VOS_IS_STATUS_SUCCESS( status ))
2475 {
2476 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302477 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302478 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002479 return VOS_STATUS_E_FAILURE;
2480 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002481
2482 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2483 {
c_hpothu32490782014-03-14 19:14:34 +05302484 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07002485 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
2486 return eHAL_STATUS_FAILURE;
2487 }
2488
Chilam Ng1279e232013-01-25 15:06:52 -08002489#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002490 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
2491 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08002492 {
2493 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08002494 u8 mac[6];
2495
Hoonki Lee387663d2013-02-05 18:08:43 -08002496 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08002497
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002498 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302499 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002500 "rx broadcast packet, not adding to peer list");
2501 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2502 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002503 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05302504 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002505 "rx extract mac:" MAC_ADDRESS_STR,
2506 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302507 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05302508 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
2509 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002510 {
2511 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05302512 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002513 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
2514 }
Chilam Ng1279e232013-01-25 15:06:52 -08002515 } else {
c_hpothu32490782014-03-14 19:14:34 +05302516 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002517 "rx packet sa is bssid, not adding to peer list");
2518 }
2519 }
2520#endif
2521
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002522 if (pHddCtx->cfg_ini->gEnableDebugLog)
2523 {
2524 proto_type = vos_pkt_get_proto_type(skb,
2525 pHddCtx->cfg_ini->gEnableDebugLog);
2526 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2527 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302528 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4f765af2015-01-21 19:51:30 +05302529 "STA RX EAPOL SubType %d",eapolSubType);
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002530 }
2531 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2532 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302533 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002534 "STA RX DHCP");
2535 }
2536 }
2537
Girish Gowli8a7bc042015-01-19 16:20:20 +05302538 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
2539 {
2540 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2541 }
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302542 if (( NULL != pHddCtx ) &&
2543 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05302544 {
2545 hdd_dump_dhcp_pkt(skb, RX_PATH);
2546 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302547
Jeff Johnson295189b2012-06-20 16:38:30 -07002548 skb->dev = pAdapter->dev;
2549 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002550 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002551 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2552 ++pAdapter->stats.rx_packets;
2553 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002554#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002555#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002556 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002557#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002558#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002559 rxstat = netif_rx_ni(skb);
2560 if (NET_RX_SUCCESS == rxstat)
2561 {
2562 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002563 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002564 }
2565 else
2566 {
2567 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2568 }
2569 // now process the next packet in the chain
2570 pVosPacket = pNextVosPacket;
2571
2572 } while (pVosPacket);
2573
2574 //Return the entire VOS packet chain to the resource pool
2575 status = vos_pkt_return_packet( pVosPacketChain );
2576 if(!VOS_IS_STATUS_SUCCESS( status ))
2577 {
c_hpothu32490782014-03-14 19:14:34 +05302578 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002579 }
2580
2581 pAdapter->dev->last_rx = jiffies;
2582
2583 return status;
2584}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002585/**============================================================================
2586 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2587 Enable/Disable split scan based on TX and RX traffic.
2588 @param HddContext : [in] pointer to Hdd context
2589 @return : None
2590 ===========================================================================*/
2591void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2592{
2593 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2594 hdd_adapter_t *pAdapter = NULL;
2595 hdd_station_ctx_t *pHddStaCtx = NULL;
2596 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2597 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2598 VOS_STATUS status;
2599 v_U8_t staId = 0;
2600 v_U8_t fconnected = 0;
2601
c_hpothub8245442013-11-20 23:41:09 +05302602 if (NULL == phddctx)
2603 {
c_hpothu32490782014-03-14 19:14:34 +05302604 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05302605 FL("phddctx is NULL"));
2606 VOS_ASSERT(0);
2607 return;
2608 }
2609
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002610 if (!cfg_param->dynSplitscan)
2611 {
c_hpothu32490782014-03-14 19:14:34 +05302612 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002613 "%s: Error : Dynamic split scan is not Enabled : %d",
2614 __func__, pHddCtx->cfg_ini->dynSplitscan);
2615 return;
2616 }
2617
2618 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2619 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2620 {
2621 pAdapter = pAdapterNode->pAdapter;
2622
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +05302623 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002624 {
c_hpothu32490782014-03-14 19:14:34 +05302625 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002626 "%s: Adapter with device mode %d exists",
2627 __func__, pAdapter->device_mode);
2628
2629 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2630 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2631 {
2632 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2633 if ((eConnectionState_Associated ==
2634 pHddStaCtx->conn_info.connState) &&
2635 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2636 {
2637 fconnected = TRUE;
2638 }
2639 }
2640 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2641 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2642 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302643 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2644 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2645 if(pSapCtx == NULL){
2646 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2647 FL("psapCtx is NULL"));
2648 return;
2649 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002650 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2651 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302652 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002653 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302654 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002655 {
2656 fconnected = TRUE;
2657 }
2658 }
2659 }
2660 if ( fconnected )
2661 {
c_hpothu32490782014-03-14 19:14:34 +05302662 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002663 "%s: One of the interface is connected check for scan",
2664 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302665 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302666 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
2667 "miracast = %d", __func__,
2668 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
2669 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
2670 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002671
2672 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
2673 cfg_param->trafficMntrTmrForSplitScan);
2674 //Check for the previous statistics count
2675 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
2676 cfg_param->txRxThresholdForSplitScan) ||
2677 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
2678 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05302679 pHddCtx->drvr_miracast ||
2680 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002681 {
2682 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2683 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2684
2685 if (!pHddCtx->issplitscan_enabled)
2686 {
2687 pHddCtx->issplitscan_enabled = TRUE;
2688 sme_enable_disable_split_scan(
2689 WLAN_HDD_GET_HAL_CTX(pAdapter),
2690 cfg_param->nNumStaChanCombinedConc,
2691 cfg_param->nNumP2PChanCombinedConc);
2692 }
2693 return;
2694 }
2695 else
2696 {
2697 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2698 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2699 }
2700 fconnected = FALSE;
2701 }
2702 }
2703 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
2704 pAdapterNode = pNext;
2705 }
2706
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05302707 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
2708 * of disabling the split scan and thus do not disable the same when the
2709 * low TXRX condition is met.
2710 */
2711 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002712 {
c_hpothu32490782014-03-14 19:14:34 +05302713 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002714 "%s: Disable split scan", __func__);
2715 pHddCtx->issplitscan_enabled = FALSE;
2716 sme_enable_disable_split_scan(
2717 pHddCtx->hHal,
2718 SME_DISABLE_SPLIT_SCAN,
2719 SME_DISABLE_SPLIT_SCAN);
2720 }
2721 return;
2722}
Jeff Johnson295189b2012-06-20 16:38:30 -07002723