blob: 225f909181427a4b41b17b2b15c9259b0f0e9c2e [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,
83};
84
Mihir Shetec8fe71b2014-06-16 15:32:59 +053085#define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
86#define HDD_TX_TIMEOUT_RATELIMIT_BURST 1
Mihir Shetef3473692014-06-27 15:13:20 +053087#define HDD_TX_STALL_SSR_THRESHOLD 5
Mihir Shete0be28772015-02-17 18:42:14 +053088#define HDD_TX_STALL_SSR_THRESHOLD_HIGH 13
Mihir Shete327c2ab2014-11-13 15:17:02 +053089#define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
Mihir Shetec8fe71b2014-06-16 15:32:59 +053090
91static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs, \
92 HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
93 HDD_TX_TIMEOUT_RATELIMIT_BURST);
94
Jeff Johnson295189b2012-06-20 16:38:30 -070095static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070096
97/*---------------------------------------------------------------------------
98 Type declarations
99 -------------------------------------------------------------------------*/
100
101/*---------------------------------------------------------------------------
102 Function definitions and documenation
103 -------------------------------------------------------------------------*/
104
105#ifdef DATA_PATH_UNIT_TEST
106//Utility function to dump an sk_buff
107static void dump_sk_buff(struct sk_buff * skb)
108{
c_hpothu32490782014-03-14 19:14:34 +0530109 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
110 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
111 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
112 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
113 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
114 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
115 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 -0700116
c_hpothu32490782014-03-14 19:14:34 +0530117 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 -0700118 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
119 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu32490782014-03-14 19:14:34 +0530120 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 -0700121 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
122 skb->data[13], skb->data[14], skb->data[15]);
123}
124
125//Function for Unit Test only
126static void transport_thread(hdd_adapter_t *pAdapter)
127{
128 v_U8_t staId;
129 WLANTL_ACEnumType ac = WLANTL_AC_BE;
130 vos_pkt_t *pVosPacket = NULL ;
131 vos_pkt_t dummyPacket;
132 WLANTL_MetaInfoType pktMetaInfo;
133 WLANTL_RxMetaInfoType pktRxMetaInfo;
134 VOS_STATUS status = VOS_STATUS_E_FAILURE;
135
c_hpothub8245442013-11-20 23:41:09 +0530136 if (NULL == pAdapter)
137 {
c_hpothu32490782014-03-14 19:14:34 +0530138 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530139 FL("pAdapter is NULL"));
140 VOS_ASSERT(0);
141 return;
142 }
143
Jeff Johnson295189b2012-06-20 16:38:30 -0700144 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
145 &staId,
146 &ac,
147 &pVosPacket,
148 &pktMetaInfo );
149 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530150 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
151 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700152 else
c_hpothu32490782014-03-14 19:14:34 +0530153 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
154 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700156 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700157 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530158 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
159 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700160 else
c_hpothu32490782014-03-14 19:14:34 +0530161 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
162 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700163
164 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
165 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530166 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
167 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700168 else
c_hpothu32490782014-03-14 19:14:34 +0530169 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
170 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700171
172 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
173 &dummyPacket,
174 staId,
175 &pktRxMetaInfo);
176 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530177 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
178 "%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700179 else
c_hpothu32490782014-03-14 19:14:34 +0530180 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
181 "%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700182
183}
184#endif
185
186
187/**============================================================================
188 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
189
190 @param pAdapter : [in] pointer to adapter context
191 @return : VOS_STATUS_E_FAILURE if any errors encountered
192 : VOS_STATUS_SUCCESS otherwise
193 ===========================================================================*/
194static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
195{
196 VOS_STATUS status = VOS_STATUS_SUCCESS;
197 v_SINT_t i = -1;
198 hdd_list_node_t *anchor = NULL;
199 skb_list_node_t *pktNode = NULL;
200 struct sk_buff *skb = NULL;
201
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530202 pAdapter->isVosLowResource = VOS_FALSE;
203
Mihir Shete5d148f12014-12-16 17:54:49 +0530204 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_FLUSH_TX_QUEUES,
205 pAdapter->sessionId, 0));
206
Jeff Johnson295189b2012-06-20 16:38:30 -0700207 while (++i != NUM_TX_QUEUES)
208 {
209 //Free up any packets in the Tx queue
210 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
211 while (true)
212 {
213 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
214 if(VOS_STATUS_E_EMPTY != status)
215 {
216 pktNode = list_entry(anchor, skb_list_node_t, anchor);
217 skb = pktNode->skb;
218 //TODO
219 //++pAdapter->stats.tx_dropped;
220 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
221 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
222 kfree_skb(skb);
223 continue;
224 }
225 break;
226 }
227 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
228 // backpressure is no longer in effect
229 pAdapter->isTxSuspended[i] = VOS_FALSE;
230 }
231
232 return status;
233}
234
Ravi Joshif9520d62013-10-18 04:11:46 -0700235/**============================================================================
236 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
237 in IBSS mode
238
239 @param pAdapter : [in] pointer to adapter context
240 : [in] Staion Id
241 @return : VOS_STATUS_E_FAILURE if any errors encountered
242 : VOS_STATUS_SUCCESS otherwise
243 ===========================================================================*/
244void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
245{
246 v_U8_t i;
Ravi Joshi41914632013-10-21 23:02:21 -0700247 v_SIZE_t size = 0;
Ravi Joshif9520d62013-10-18 04:11:46 -0700248 v_U8_t skbStaIdx;
Ravi Joshi41914632013-10-21 23:02:21 -0700249 skb_list_node_t *pktNode = NULL;
250 hdd_list_node_t *tmp = NULL, *next = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700251 struct netdev_queue *txq;
Ravi Joshi41914632013-10-21 23:02:21 -0700252 struct sk_buff *skb = NULL;
Ravi Joshif9520d62013-10-18 04:11:46 -0700253
c_hpothub8245442013-11-20 23:41:09 +0530254 if (NULL == pAdapter)
255 {
c_hpothu32490782014-03-14 19:14:34 +0530256 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530257 FL("pAdapter is NULL %u"), STAId);
258 VOS_ASSERT(0);
259 return;
260 }
261
Ravi Joshif9520d62013-10-18 04:11:46 -0700262 for (i = 0; i < NUM_TX_QUEUES; i++)
263 {
264 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
265
266 if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) )
267 {
268 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
269 continue;
270 }
271
272 /* Iterate through the queue and identify the data for STAId */
Ravi Joshi41914632013-10-21 23:02:21 -0700273 list_for_each_safe(tmp, next, &pAdapter->wmm_tx_queue[i].anchor)
Ravi Joshif9520d62013-10-18 04:11:46 -0700274 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700275 pktNode = list_entry(tmp, skb_list_node_t, anchor);
276 if (pktNode != NULL)
277 {
278 skb = pktNode->skb;
279
280 /* Get the STAId from data */
281 skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
282 if (skbStaIdx == STAId)
283 {
Ravi Joshif9520d62013-10-18 04:11:46 -0700284 /* Data for STAId is freed along with the queue node */
Ravi Joshif9520d62013-10-18 04:11:46 -0700285 list_del(tmp);
Mihir Shete31e1e392014-03-24 17:09:09 +0530286 kfree_skb(skb);
Ravi Joshif9520d62013-10-18 04:11:46 -0700287
288 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
289 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
290 pAdapter->wmm_tx_queue[i].count--;
291 }
292 }
293 }
294
295 /* Restart the queue only-if suspend and the queue was flushed */
Ravi Joshi41914632013-10-21 23:02:21 -0700296 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
Ravi Joshif9520d62013-10-18 04:11:46 -0700297 txq = netdev_get_tx_queue(pAdapter->dev, i);
Ravi Joshi41914632013-10-21 23:02:21 -0700298
299 if (VOS_TRUE == pAdapter->isTxSuspended[i] &&
300 size <= HDD_TX_QUEUE_LOW_WATER_MARK &&
301 netif_tx_queue_stopped(txq) )
Ravi Joshif9520d62013-10-18 04:11:46 -0700302 {
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530303 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queue for queue %d"),i);
Ravi Joshif9520d62013-10-18 04:11:46 -0700304 netif_tx_start_queue(txq);
Ravi Joshi41914632013-10-21 23:02:21 -0700305 pAdapter->isTxSuspended[i] = VOS_FALSE;
306 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressured;
307 ++pAdapter->hdd_stats.hddTxRxStats.txDequeDePressuredAC[i];
Ravi Joshif9520d62013-10-18 04:11:46 -0700308 }
309
310 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
311 }
312}
313
Jeff Johnson295189b2012-06-20 16:38:30 -0700314static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
315{
316 skb_list_node_t *pktNode = NULL;
317 struct sk_buff *skb = NULL;
318 v_SIZE_t size = 0;
319 WLANTL_ACEnumType ac = 0;
320 VOS_STATUS status = VOS_STATUS_E_FAILURE;
321 hdd_list_node_t *anchor = NULL;
322
c_hpothu77731d42014-01-23 13:59:03 +0530323 if (NULL == pAdapter)
324 {
325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
326 FL("pAdapter is NULL"));
327 VOS_ASSERT(0);
328 return NULL;
329 }
330
Jeff Johnson295189b2012-06-20 16:38:30 -0700331 // do we have any packets pending in this AC?
332 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
333 if( size == 0 )
334 {
c_hpothu32490782014-03-14 19:14:34 +0530335 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700336 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700337 return NULL;
338 }
339
340 //Remove the packet from the queue
341 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
342 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
343 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
344
345 if(VOS_STATUS_SUCCESS == status)
346 {
347 //If success then we got a valid packet from some AC
348 pktNode = list_entry(anchor, skb_list_node_t, anchor);
349 skb = pktNode->skb;
350 }
351 else
352 {
c_hpothu32490782014-03-14 19:14:34 +0530353 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700354 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700355 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700356
357 return NULL;
358 }
359
360 // if we are in a backpressure situation see if we can turn the hose back on
361 if ( (pAdapter->isTxSuspended[ac]) &&
362 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
363 {
c_hpothu32490782014-03-14 19:14:34 +0530364 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700365 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700366 pAdapter->isTxSuspended[ac] = VOS_FALSE;
367 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530368 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700369 netif_tx_start_all_queues( pAdapter->dev );
370 }
371
372 return skb;
373}
374
375void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
376{
377 hdd_cfg80211_state_t *cfgState;
378 struct sk_buff* skb;
379 hdd_adapter_t* pMonAdapter = NULL;
380 struct ieee80211_hdr *hdr;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530381 hdd_context_t *pHddCtx;
382 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700383
Mukul Sharma23a92232014-04-07 18:04:00 +0530384 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 {
c_hpothu32490782014-03-14 19:14:34 +0530386 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530387 FL("pAdapter is NULL"));
388 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700389 return;
390 }
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530391 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
392 ret = wlan_hdd_validate_context(pHddCtx);
393 if (0 != ret)
394 {
395 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
396 "%s: HDD context is not valid, ret =%d",__func__, ret);
397 return;
398 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700399 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530400 if (pMonAdapter == NULL)
401 {
402 hddLog(VOS_TRACE_LEVEL_ERROR,
403 "%s: pMonAdapter is NULL", __func__);
404 return;
405 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700406 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
407
408 if( NULL != cfgState->buf )
409 {
c_hpothu32490782014-03-14 19:14:34 +0530410 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700411 "%s: Already one MGMT packet Tx going on", __func__);
412 return;
413 }
414
415 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
416
417 if (NULL == skb)
418 {
c_hpothu32490782014-03-14 19:14:34 +0530419 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700420 "%s: No Packet Pending", __func__);
421 return;
422 }
423
424 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
425 if( cfgState->buf == NULL )
426 {
c_hpothu32490782014-03-14 19:14:34 +0530427 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700428 "%s: Failed to Allocate memory", __func__);
429 goto fail;
430 }
431
432 cfgState->len = skb->len;
433
434 vos_mem_copy( cfgState->buf, skb->data, skb->len);
435
436 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800437 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700438
439 hdr = (struct ieee80211_hdr *)skb->data;
440 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
441 == HDD_FRAME_TYPE_MGMT )
442 {
443 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
444 == HDD_FRAME_SUBTYPE_DEAUTH )
445 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530446 struct tagCsrDelStaParams delStaParams;
447
Sushant Kaushik4cd28f62014-12-26 14:23:50 +0530448 WLANSAP_PopulateDelStaParams(hdr->addr1,
449 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530450 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
451
452 hdd_softap_sta_deauth(pAdapter, &delStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -0700453 goto mgmt_handled;
454 }
455 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
456 == HDD_FRAME_SUBTYPE_DISASSOC )
457 {
458 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
459 goto mgmt_handled;
460 }
461 }
c_hpothu32490782014-03-14 19:14:34 +0530462 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700463 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
464
Jeff Johnson43971f52012-07-17 12:26:56 -0700465 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700467 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 {
c_hpothu32490782014-03-14 19:14:34 +0530469 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700470 "%s: WLANSAP_SendAction returned fail", __func__);
471 hdd_sendActionCnf( pAdapter, FALSE );
472 }
473 return;
474
475mgmt_handled:
476 hdd_sendActionCnf( pAdapter, TRUE );
477 return;
478fail:
479 kfree_skb(pAdapter->skb_to_tx);
480 pAdapter->skb_to_tx = NULL;
481 return;
482}
483
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530484void __hdd_mon_tx_work_queue(struct work_struct *work)
Jeff Johnson295189b2012-06-20 16:38:30 -0700485{
486 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
487 hdd_mon_tx_mgmt_pkt(pAdapter);
488}
489
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530490void hdd_mon_tx_work_queue(struct work_struct *work)
491{
492 vos_ssr_protect(__func__);
493 __hdd_mon_tx_work_queue(work);
494 vos_ssr_unprotect(__func__);
495}
496
Jeff Johnson295189b2012-06-20 16:38:30 -0700497int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
498{
499 v_U16_t rt_hdr_len;
500 struct ieee80211_hdr *hdr;
501 hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
502 struct ieee80211_radiotap_header *rtap_hdr =
503 (struct ieee80211_radiotap_header *)skb->data;
504
505 /*Supplicant sends the EAPOL packet on monitor interface*/
506 pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;
507 if(pPgBkAdapter == NULL)
508 {
c_hpothu32490782014-03-14 19:14:34 +0530509 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700510 "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
511 __func__);
512 goto fail; /* too short to be possibly valid */
513 }
514
515 /* check if toal skb length is greater then radio tab header length of not */
516 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
517 goto fail; /* too short to be possibly valid */
518
519 /* check if radio tap header version is correct or not */
520 if (unlikely(rtap_hdr->it_version))
521 goto fail; /* only version 0 is supported */
522
523 /*Strip off the radio tap header*/
524 rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
525
526 /* check if skb length if greator then total radio tap header length ot not*/
527 if (unlikely(skb->len < rt_hdr_len))
528 goto fail;
529
530 /* Update the trans_start for this netdev */
531 dev->trans_start = jiffies;
532 /*
533 * fix up the pointers accounting for the radiotap
534 * header still being in there.
535 */
536 skb_set_mac_header(skb, rt_hdr_len);
537 skb_set_network_header(skb, rt_hdr_len);
538 skb_set_transport_header(skb, rt_hdr_len);
539
540 /* Pull rtap header out of the skb */
541 skb_pull(skb, rt_hdr_len);
542
543 /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after
544 * radio tap header and 802.11 header starts
545 */
546 hdr = (struct ieee80211_hdr *)skb->data;
547
548 /* Send data frames through the normal Data path. In this path we will
549 * conver rcvd 802.11 packet to 802.3 packet */
550 if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA)
551 {
552 v_U8_t da[6];
553 v_U8_t sa[6];
554
555 memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
556 memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
557
558 /* Pull 802.11 MAC header */
559 skb_pull(skb, HDD_80211_HEADER_LEN);
560
561 if ( HDD_FRAME_SUBTYPE_QOSDATA ==
562 (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
563 {
564 skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
565 }
566
567 /* Pull LLC header */
568 skb_pull(skb, HDD_LLC_HDR_LEN);
569
570 /* Create space for Ethernet header */
571 skb_push(skb, HDD_MAC_HDR_SIZE*2);
572 memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
573 memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
574
575 /* Only EAPOL Data packets are allowed through monitor interface */
576 if (vos_be16_to_cpu(
577 (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) )
578 != HDD_ETHERTYPE_802_1_X)
579 {
c_hpothu32490782014-03-14 19:14:34 +0530580 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700581 "%s: Not a Eapol packet. Drop this frame", __func__);
582 //If not EAPOL frames, drop them.
583 kfree_skb(skb);
584 return NETDEV_TX_OK;
585 }
586
587 skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
588
589 hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
590 return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
591 }
592 else
593 {
594 VOS_STATUS status;
595 WLANTL_ACEnumType ac = 0;
596 skb_list_node_t *pktNode = NULL;
597 v_SIZE_t pktListSize = 0;
598
599 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
600 //If we have already reached the max queue size, disable the TX queue
601 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
602 {
603 /* We want to process one packet at a time, so lets disable all TX queues
604 * and re-enable the queues once we get TX feedback for this packet */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530605 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700606 netif_tx_stop_all_queues(pAdapter->dev);
607 pAdapter->isTxSuspended[ac] = VOS_TRUE;
608 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
609 return NETDEV_TX_BUSY;
610 }
611 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
612
613 //Use the skb->cb field to hold the list node information
614 pktNode = (skb_list_node_t *)&skb->cb;
615
616 //Stick the OS packet inside this node.
617 pktNode->skb = skb;
618
619 INIT_LIST_HEAD(&pktNode->anchor);
620
621 //Insert the OS packet into the appropriate AC queue
622 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
623 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
624 &pktNode->anchor, &pktListSize );
625 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
626
627 if ( !VOS_IS_STATUS_SUCCESS( status ) )
628 {
c_hpothu32490782014-03-14 19:14:34 +0530629 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700630 "%s:Insert Tx queue failed. Pkt dropped", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700631 kfree_skb(skb);
632 return NETDEV_TX_OK;
633 }
634
635 if ( pktListSize == 1 )
636 {
637 /* In this context we cannot acquire any mutex etc. And to transmit
638 * this packet we need to call SME API. So to take care of this we will
639 * schedule a workqueue
640 */
641 schedule_work(&pPgBkAdapter->monTxWorkQueue);
642 }
643 return NETDEV_TX_OK;
644 }
645
646fail:
c_hpothu32490782014-03-14 19:14:34 +0530647 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700648 "%s: Packet Rcvd at Monitor interface is not proper,"
649 " Dropping the packet",
650 __func__);
651 kfree_skb(skb);
652 return NETDEV_TX_OK;
653}
Dino Mycled9b7cc12014-09-04 18:43:07 +0530654
655/**============================================================================
656 @brief hdd_dhcp_pkt_info() -
657 Function to log DHCP pkt info
658
659 @param skb : [in] pointer to OS packet (sk_buff)
660 @return : None
661 ===========================================================================*/
662
663void hdd_dhcp_pkt_info(struct sk_buff *skb)
664{
665 /* port no 67 (0x43) or 68 (0x44) */
666
667 if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_REQUEST_MSG)
668 hddLog(VOS_TRACE_LEVEL_INFO, FL("Request"));
669 else if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_RESPONSE_MSG)
670 hddLog(VOS_TRACE_LEVEL_INFO, FL("Response"));
671 else
672 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP invalid"));
673
674 hddLog(VOS_TRACE_LEVEL_INFO,
675 FL("DHCP Dest Addr: %pM Src Addr %pM "
676 " source port : %d, dest port : %d"),
677 skb->data, (skb->data + 6),
678 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))),
679 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))));
680
681 if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
682 (skb->data[DHCP_OPTION53_LENGTH_OFFSET] == DHCP_OPTION53_LENGTH)) {
683
684 switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
685 case DHCPDISCOVER:
686 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP DISCOVER"));
687 break;
688 case DHCPREQUEST:
689 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP REQUEST"));
690 break;
691 case DHCPOFFER:
692 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP OFFER"));
693 break;
694 case DHCPACK:
695 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP ACK"));
696 break;
697 case DHCPNAK:
698 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP NACK"));
699 break;
700 case DHCPRELEASE:
701 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP RELEASE"));
702 break;
703 case DHCPINFORM:
704 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP INFORM"));
705 break;
706
707 default:
708 hddLog(VOS_TRACE_LEVEL_INFO,
709 "%s: DHCP Not Defined OPTION53 : %d", __func__,
710 skb->data[DHCP_OPTION53_STATUS_OFFSET]);
711 }
712 }
713}
714
715/**============================================================================
716 @brief hdd_dump_dhcp_pkt() -
717 Function to dump DHCP packets in TX and RX path.
718
719 @param skb : [in] pointer to OS packet (sk_buff)
720 @param path : [in] bool indicating TX/RX path
721 @return : None
722 ===========================================================================*/
723void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path)
724{
725
726 if ((ntohs(*((u16*)((u8*)skb->data + ETH_TYPE_OFFSET)))
727 == ETH_TYPE_IP_PKT) ||
728 (ntohs(*((u8*)skb->data + PROTOCOL_OFFSET)) == UDP_PROTOCOL)) {
729
730 /* IP protocol 12 bytes of mac addresses in 802.3 header */
731 if ( ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
732 BOOTP_SERVER_PORT ||
733 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
734 BOOTP_CLIENT_PORT ||
735 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
736 BOOTP_SERVER_PORT ||
737 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
738 BOOTP_CLIENT_PORT ) {
739
740 if (path == TX_PATH) {
741 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP TX PATH"));
742 } else {
743 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP RX PATH"));
744 }
745
746 hdd_dhcp_pkt_info(skb);
747 }
748 }
749}
750
Jeff Johnson295189b2012-06-20 16:38:30 -0700751/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530752 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700753 transmitting packets. There are 2 versions of this function. One that uses
754 locked queue and other that uses lockless queues. Both have been retained to
755 do some performance testing
756
757 @param skb : [in] pointer to OS packet (sk_buff)
758 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530759
Jeff Johnson295189b2012-06-20 16:38:30 -0700760 @return : NET_XMIT_DROP if packets are dropped
761 : NET_XMIT_SUCCESS if packet is enqueued succesfully
762 ===========================================================================*/
763int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
764{
765 VOS_STATUS status;
766 WLANTL_ACEnumType ac;
767 sme_QosWmmUpType up;
768 skb_list_node_t *pktNode = NULL;
769 hdd_list_node_t *anchor = NULL;
770 v_SIZE_t pktListSize = 0;
771 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
772 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700773 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700774 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Dino Mycled9b7cc12014-09-04 18:43:07 +0530775 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700776 v_BOOL_t txSuspended = VOS_FALSE;
Mihir Shetef8f74532014-12-04 11:53:34 +0530777 struct sk_buff *skb1;
Jeff Johnson295189b2012-06-20 16:38:30 -0700778
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530779 if (NULL == pHddCtx) {
780 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
781 "%s HDD context is NULL", __func__);
782 return NETDEV_TX_BUSY;
783 }
784
Jeff Johnson295189b2012-06-20 16:38:30 -0700785 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
786
Ravi Joshif9520d62013-10-18 04:11:46 -0700787 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530788 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700789 "%s is called when netif TX %d is disabled",
790 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530791 return NETDEV_TX_BUSY;
792 }
793
Ravi Joshicc57ed42013-10-12 16:31:25 -0700794 //Get TL AC corresponding to Qdisc queue index/AC.
795 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
796
797 if (WLAN_HDD_IBSS == pAdapter->device_mode)
Shailender Karmuchia734f332013-04-19 14:02:48 -0700798 {
799 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
800
Ravi Joshif9520d62013-10-18 04:11:46 -0700801 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
Ravi Joshicc57ed42013-10-12 16:31:25 -0700802 {
c_hpothu32490782014-03-14 19:14:34 +0530803 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshicc57ed42013-10-12 16:31:25 -0700804 "%s: Tx frame in disconnected state in IBSS mode", __func__);
805 ++pAdapter->stats.tx_dropped;
806 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
807 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
808 kfree_skb(skb);
809 return NETDEV_TX_OK;
810 }
811
Shailender Karmuchia734f332013-04-19 14:02:48 -0700812 STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
813
814 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
815 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
816 vos_is_macaddr_group(pDestMacAddress)))
817 {
818 STAId = IBSS_BROADCAST_STAID;
c_hpothu32490782014-03-14 19:14:34 +0530819 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
Ravi Joshif9520d62013-10-18 04:11:46 -0700820 "%s: BC/MC packet", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700821 }
822 else if (STAId == HDD_WLAN_INVALID_STA_ID)
823 {
c_hpothu32490782014-03-14 19:14:34 +0530824 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Ravi Joshif9520d62013-10-18 04:11:46 -0700825 "%s: Received Unicast frame with invalid staID", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700826 ++pAdapter->stats.tx_dropped;
827 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700828 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Shailender Karmuchia734f332013-04-19 14:02:48 -0700829 kfree_skb(skb);
830 return NETDEV_TX_OK;
831 }
832 }
833 else
834 {
c_hpothu851d9862015-01-19 18:39:06 +0530835 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
836 {
837 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
838 FL("Tx frame in not associated state in %d context"),
839 pAdapter->device_mode);
840 ++pAdapter->stats.tx_dropped;
841 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
842 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
843 kfree_skb(skb);
844 return NETDEV_TX_OK;
845 }
Shailender Karmuchia734f332013-04-19 14:02:48 -0700846 STAId = pHddStaCtx->conn_info.staId[0];
847 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700848
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530849 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 //select_queue call back function
851 up = skb->priority;
852
853 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
854
855#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530856 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700857 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700858#endif // HDD_WMM_DEBUG
859
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530860 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
Mukul Sharma84f27252014-07-14 18:11:42 +0530861 {
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530862 vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
Mukul Sharma84f27252014-07-14 18:11:42 +0530863 }
Mukul Sharma84f27252014-07-14 18:11:42 +0530864
Jeff Johnson295189b2012-06-20 16:38:30 -0700865 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700866 /*CR 463598,384996*/
867 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
868 *We check for +1 in the logic,to take care of Zero count which
869 *occurs very frequently in low traffic cases */
870 if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
871 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700872 /* 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 -0700873 * 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 +0530874 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 -0700875
Ravi Joshi8a934352013-09-25 16:46:58 -0700876 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
877 STAId, ac
878 );
879 if ( !VOS_IS_STATUS_SUCCESS( status ) )
880 {
c_hpothu32490782014-03-14 19:14:34 +0530881 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700882 "%s: WLANTL_STAPktPending() returned error code %d",
883 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700884 ++pAdapter->stats.tx_dropped;
885 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
886 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Ravi Joshi8a934352013-09-25 16:46:58 -0700887 kfree_skb(skb);
888 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
889 return NETDEV_TX_OK;
890 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700891 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700892 //If we have already reached the max queue size, disable the TX queue
893 if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
894 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700895 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
896 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530897 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for ac %d"),ac);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700898 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
899 pAdapter->isTxSuspended[ac] = VOS_TRUE;
900 txSuspended = VOS_TRUE;
Mihir Shete5d148f12014-12-16 17:54:49 +0530901 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_NETDEV,
902 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 }
904
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530905 /* If 3/4th of the max queue size is used then enable the flag.
906 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
907 if (WLANTL_AC_BE == ac)
908 {
909 if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
910 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530911 pAdapter->isVosLowResource = VOS_TRUE;
912 }
913 else
914 {
915 pAdapter->isVosLowResource = VOS_FALSE;
916 }
917 }
918
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530919 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530920
Sachin Ahuja8c65f382014-12-12 15:34:21 +0530921 if (( NULL != pHddCtx ) &&
922 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +0530923 {
924 hdd_dump_dhcp_pkt(skb, TX_PATH);
925 }
926
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 if (VOS_TRUE == txSuspended)
928 {
c_hpothu32490782014-03-14 19:14:34 +0530929 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530930 "%s: TX queue full for AC=%d Disable OS TX queue",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700931 __func__, ac );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530932 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 }
934
935 //Use the skb->cb field to hold the list node information
936 pktNode = (skb_list_node_t *)&skb->cb;
937
938 //Stick the OS packet inside this node.
939 pktNode->skb = skb;
940
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530941 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700942 pktNode->userPriority = up;
943
944
945 INIT_LIST_HEAD(&pktNode->anchor);
946
947 //Insert the OS packet into the appropriate AC queue
948 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
949 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
950 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
951
952 if ( !VOS_IS_STATUS_SUCCESS( status ) )
953 {
c_hpothu32490782014-03-14 19:14:34 +0530954 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 -0700955 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
956 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
957 ++pAdapter->stats.tx_dropped;
958 kfree_skb(skb);
959 return NETDEV_TX_OK;
960 }
961
962 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
963 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700964 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700965
Kiet Lamf040f472013-11-20 21:15:23 +0530966 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
967 {
968 /* Function which will determine acquire admittance for a
969 * WMM AC is required or not based on psb configuration done
970 * in the framework
971 */
972 hdd_wmm_acquire_access_required(pAdapter, ac);
973 }
974
Jeff Johnson295189b2012-06-20 16:38:30 -0700975 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530976 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
977 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700978 {
979 granted = VOS_TRUE;
980 }
981 else
982 {
983 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530984 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700985 }
Nirav Shah4f765af2015-01-21 19:51:30 +0530986
987 if ( (granted && ( pktListSize == 1 )) ||
988 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700989 {
990 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +0530991 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700992 status = WLANTL_STAPktPending(
993 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
994 STAId, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 if ( !VOS_IS_STATUS_SUCCESS( status ) )
996 {
c_hpothu32490782014-03-14 19:14:34 +0530997 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d", __func__, ac );
Jeff Johnson295189b2012-06-20 16:38:30 -0700998
999 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
1000 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
1001 spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
1002 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
1003 spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
Mihir Shetef8f74532014-12-04 11:53:34 +05301004 /* Free the skb only if we are able to remove it from the list.
1005 * If we are not able to retrieve it from the list it means that
1006 * the skb was pulled by TX Thread and is use so we should not free
1007 * it here
1008 */
1009 if (VOS_IS_STATUS_SUCCESS(status))
1010 {
1011 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1012 skb1 = pktNode->skb;
1013 kfree_skb(skb1);
1014 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001015 ++pAdapter->stats.tx_dropped;
1016 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
1017 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Jeff Johnson295189b2012-06-20 16:38:30 -07001018 return NETDEV_TX_OK;
1019 }
1020 }
1021
1022 dev->trans_start = jiffies;
1023
1024 return NETDEV_TX_OK;
1025}
1026
1027/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -07001028 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
1029
1030 @param pHddStaCtx : [in] pointer to HDD Station Context
1031 pMacAddress [in] pointer to Peer Mac address
1032 staID [out] pointer to Station Index
1033 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
1034 ===========================================================================*/
1035
1036VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1037{
1038 v_U8_t idx;
1039
1040 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
1041 {
1042 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
1043 pMacAddress, sizeof(v_MACADDR_t)))
1044 {
1045 *staId = pHddStaCtx->conn_info.staId[idx];
1046 return VOS_STATUS_SUCCESS;
1047 }
1048 }
1049
1050 return VOS_STATUS_E_FAILURE;
1051}
1052
1053/**============================================================================
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301054 @brief __hdd_tx_timeout() - Function handles timeout during transmission.
Jeff Johnson295189b2012-06-20 16:38:30 -07001055
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301056 @param dev : [in] pointer to network device
Jeff Johnson295189b2012-06-20 16:38:30 -07001057 @return : None
1058 ===========================================================================*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301059void __hdd_tx_timeout(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001060{
Ravi Joshicc57ed42013-10-12 16:31:25 -07001061 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mihir Shete0be28772015-02-17 18:42:14 +05301062 hdd_context_t *pHddCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001063 struct netdev_queue *txq;
Mihir Shete0be28772015-02-17 18:42:14 +05301064 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001065 int i = 0;
Mukul Sharma42b3d432014-10-16 16:13:40 +05301066 v_ULONG_t diff_in_jiffies = 0;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001067
Mihir Shetef3473692014-06-27 15:13:20 +05301068 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301069 "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu",
1070 __func__,jiffies,dev->trans_start);
Mihir Shetef3473692014-06-27 15:13:20 +05301071
c_hpothub8245442013-11-20 23:41:09 +05301072 if ( NULL == pAdapter )
1073 {
c_hpothu32490782014-03-14 19:14:34 +05301074 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301075 FL("pAdapter is NULL"));
1076 VOS_ASSERT(0);
1077 return;
1078 }
1079
Mihir Shete0be28772015-02-17 18:42:14 +05301080 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1081 if (NULL == pHddCtx)
1082 {
1083 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1084 FL("HDD context is NULL"));
1085 VOS_ASSERT(0);
1086 return;
1087 }
1088
Mihir Shetef3473692014-06-27 15:13:20 +05301089 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
1090
Jeff Johnson295189b2012-06-20 16:38:30 -07001091 //Getting here implies we disabled the TX queues for too long. Queues are
1092 //disabled either because of disassociation or low resource scenarios. In
1093 //case of disassociation it is ok to ignore this. But if associated, we have
1094 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -07001095
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301096 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001097 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
1098 pAdapter->wmm_tx_queue[0].count,
1099 pAdapter->wmm_tx_queue[1].count,
1100 pAdapter->wmm_tx_queue[2].count,
1101 pAdapter->wmm_tx_queue[3].count);
1102
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301103 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001104 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
1105 pAdapter->isTxSuspended[0],
1106 pAdapter->isTxSuspended[1],
1107 pAdapter->isTxSuspended[2],
1108 pAdapter->isTxSuspended[3]);
1109
Mihir Shete0be28772015-02-17 18:42:14 +05301110 for (i = 0; i < dev->num_tx_queues; i++)
Ravi Joshicc57ed42013-10-12 16:31:25 -07001111 {
1112 txq = netdev_get_tx_queue(dev, i);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301113 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301114 "Queue%d status: %d txq->trans_start %lu",
1115 i, netif_tx_queue_stopped(txq),txq->trans_start);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001116 }
1117
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301118 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001119 "carrier state: %d", netif_carrier_ok(dev));
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301120
Mihir Shetef3473692014-06-27 15:13:20 +05301121 /* continuousTxTimeoutCount will be reset whenever TL fetches packet
1122 * from HDD
1123 */
1124 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
1125
Mukul Sharma42b3d432014-10-16 16:13:40 +05301126 diff_in_jiffies = jiffies - pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut;
1127 if((pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount > 1)&&
1128 ((diff_in_jiffies) > (HDD_TX_TIMEOUT * 2 ))
1129 )
1130 {
1131 /*
1132 * In Open security case when there is no traffic is running, it may possible
1133 * tx time-out may once happen and later we recovered then we need to
1134 * reset the continuousTxTimeoutCount because it is only getting modified
1135 * when traffic is running. So if over a period of time if this count reaches
1136 * to HDD_TX_STALL_SSR_THRESHOLD then host is triggering false subsystem restart.
1137 * so in genuine Tx Time out case kernel will call the tx time-out back to back at
1138 * interval of HDD_TX_TIMEOUT.So now we are checking if previous TX TIME out was
1139 * occurred more then twice of HDD_TX_TIMEOUT back then we may recovered here.
1140 */
1141 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1142 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1143 FL("This is false alarm so resetting the continuousTxTimeoutCount"));
1144 }
1145
1146 //update last jiffies after the check
1147 pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut = jiffies;
1148
Mihir Shete327c2ab2014-11-13 15:17:02 +05301149 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
1150 HDD_TX_STALL_RECOVERY_THRESHOLD)
1151 {
1152 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1153 "%s: Request firmware for recovery",__func__);
1154 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
1155 }
1156
Mihir Shete0be28772015-02-17 18:42:14 +05301157 pRemainChanCtx = hdd_get_remain_on_channel_ctx(pHddCtx);
1158 if (!pRemainChanCtx)
Mihir Shetef3473692014-06-27 15:13:20 +05301159 {
Mihir Shete0be28772015-02-17 18:42:14 +05301160 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1161 HDD_TX_STALL_SSR_THRESHOLD)
1162 {
1163 // Driver could not recover, issue SSR
1164 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1165 "%s: Cannot recover from Data stall Issue SSR",
1166 __func__);
1167 WLANTL_FatalError();
1168 return;
1169 }
1170 }
1171 else
1172 {
1173 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1174 "Remain on channel in progress");
1175 /* The supplicant can retry "P2P Invitation Request" for 120 times
1176 * and so there is a possbility that we can remain off channel for
1177 * the entire duration of these retries(which can be max 60sec).
1178 * If we encounter such a case, let us not trigger SSR after 30sec
1179 * but wait for 60sec to let the device go on home channel and start
1180 * tx. If tx does not start within 70sec we will issue SSR.
1181 */
1182 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1183 HDD_TX_STALL_SSR_THRESHOLD_HIGH)
1184 {
1185 // Driver could not recover, issue SSR
1186 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1187 "%s: Cannot recover from Data stall Issue SSR",
1188 __func__);
1189 WLANTL_FatalError();
1190 return;
1191 }
Mihir Shetef3473692014-06-27 15:13:20 +05301192 }
1193
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301194 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
1195 * every 5sec. The TL debug spits out a lot of information on the
1196 * serial console, if it is called every time *hdd_tx_timeout* is
1197 * called then we may get a watchdog bite on the Application
1198 * processor, so ratelimit the TL debug logs.
1199 */
1200 if (__ratelimit(&hdd_tx_timeout_rs))
1201 {
1202 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +05301203 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301204 }
Mihir Shetef3473692014-06-27 15:13:20 +05301205
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301206}
Jeff Johnson295189b2012-06-20 16:38:30 -07001207
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301208/**============================================================================
1209 @brief hdd_tx_timeout() - Function called by OS if there is any
1210 timeout during transmission. Since HDD simply enqueues packet
1211 and returns control to OS right away, this would never be invoked
1212
1213 @param dev : [in] pointer to network device
1214 @return : None
1215 ===========================================================================*/
1216void hdd_tx_timeout(struct net_device *dev)
1217{
1218 vos_ssr_protect(__func__);
1219 __hdd_tx_timeout(dev);
1220 vos_ssr_unprotect(__func__);
1221}
Jeff Johnson295189b2012-06-20 16:38:30 -07001222
1223/**============================================================================
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301224 @brief __hdd_stats() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -07001225 device TX/RX statistic
1226
1227 @param dev : [in] pointer to Libra network device
1228
1229 @return : pointer to net_device_stats structure
1230 ===========================================================================*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301231struct net_device_stats* __hdd_stats(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001232{
1233 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +05301234
1235 if ( NULL == pAdapter )
1236 {
c_hpothu32490782014-03-14 19:14:34 +05301237 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301238 FL("pAdapter is NULL"));
1239 VOS_ASSERT(0);
1240 return NULL;
1241 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001242
1243 return &pAdapter->stats;
1244}
1245
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301246struct net_device_stats* hdd_stats(struct net_device *dev)
1247{
1248 struct net_device_stats* dev_stats;
1249
1250 vos_ssr_protect(__func__);
1251 dev_stats = __hdd_stats(dev);
1252 vos_ssr_unprotect(__func__);
1253
1254 return dev_stats;
1255}
Jeff Johnson295189b2012-06-20 16:38:30 -07001256
1257/**============================================================================
1258 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
1259 modules in HDD
1260
1261 @param pAdapter : [in] pointer to adapter context
1262 @return : VOS_STATUS_E_FAILURE if any errors encountered
1263 : VOS_STATUS_SUCCESS otherwise
1264 ===========================================================================*/
1265VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
1266{
1267 VOS_STATUS status = VOS_STATUS_SUCCESS;
1268 v_SINT_t i = -1;
1269
c_hpothub8245442013-11-20 23:41:09 +05301270 if ( NULL == pAdapter )
1271 {
c_hpothu32490782014-03-14 19:14:34 +05301272 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301273 FL("pAdapter is NULL"));
1274 VOS_ASSERT(0);
1275 return VOS_STATUS_E_FAILURE;
1276 }
1277
Jeff Johnson295189b2012-06-20 16:38:30 -07001278 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301279 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001280
1281 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
1282 //Will be zeroed out during alloc
1283
1284 while (++i != NUM_TX_QUEUES)
1285 {
1286 pAdapter->isTxSuspended[i] = VOS_FALSE;
1287 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1288 }
1289
1290 return status;
1291}
1292
1293
1294/**============================================================================
1295 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
1296 modules in HDD
1297
1298 @param pAdapter : [in] pointer to adapter context
1299 @return : VOS_STATUS_E_FAILURE if any errors encountered
1300 : VOS_STATUS_SUCCESS otherwise
1301 ===========================================================================*/
1302VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
1303{
1304 VOS_STATUS status = VOS_STATUS_SUCCESS;
1305 v_SINT_t i = -1;
1306
c_hpothub8245442013-11-20 23:41:09 +05301307 if ( NULL == pAdapter )
1308 {
c_hpothu32490782014-03-14 19:14:34 +05301309 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301310 FL("pAdapter is NULL"));
1311 VOS_ASSERT(0);
1312 return VOS_STATUS_E_FAILURE;
1313 }
1314
Jeff Johnson295189b2012-06-20 16:38:30 -07001315 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301316 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301317 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301318 FL("failed to flush tx queues"));
1319
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 while (++i != NUM_TX_QUEUES)
1321 {
1322 //Free up actual list elements in the Tx queue
1323 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1324 }
1325
1326 return status;
1327}
1328
1329
1330/**============================================================================
1331 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1332 modules in HDD
1333
1334 @param pAdapter : [in] pointer to adapter context
1335 @return : VOS_STATUS_E_FAILURE if any errors encountered
1336 : VOS_STATUS_SUCCESS otherwise
1337 ===========================================================================*/
1338VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1339{
1340 return hdd_flush_tx_queues(pAdapter);
1341}
1342
1343
1344/**============================================================================
1345 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1346
1347 @param pVosPacket : [in] pointer to vos packet
1348 @return : VOS_TRUE if the packet is EAPOL
1349 : VOS_FALSE otherwise
1350 ===========================================================================*/
1351
1352v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1353{
1354 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1355 v_BOOL_t fEAPOL = VOS_FALSE;
1356 void *pBuffer = NULL;
1357
1358
1359 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1360 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
Abhishek Singhfa011222014-04-14 10:57:08 +05301361 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001362 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301363 if ( pBuffer && *(unsigned short*)pBuffer ==
1364 vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001365 {
1366 fEAPOL = VOS_TRUE;
1367 }
1368 }
1369
1370 return fEAPOL;
1371}
1372
Abhishek Singhfa011222014-04-14 10:57:08 +05301373/**============================================================================
Nirav Shah4f765af2015-01-21 19:51:30 +05301374 @brief hdd_FindEapolSubType() - Find EAPOL SubType.
1375
1376 @param pVosPacket : [in] pointer to vos packet
1377 @return : EAPOL_SubType value
1378 ===========================================================================*/
1379EAPOL_SubType hdd_FindEapolSubType( vos_pkt_t *pVosPacket )
1380{
1381 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1382 void *pBuffer = NULL;
1383 EAPOL_SubType subType = EAPOL_UNKNOWN;
1384 v_U16_t keyInfo;
1385 vosStatus = vos_pkt_peek_data( pVosPacket,
1386 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_SUB_TYPE_OFFSET,
1387 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1388 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1389 {
1390 if ( pBuffer )
1391 {
1392 keyInfo = (*(unsigned short*)pBuffer &
1393 HDD_ETHERTYPE_802_1_X_SUB_TYPE_MASK);
1394
1395 switch (keyInfo) {
1396 case HDD_ETHERTYPE_802_1_X_M1_VALUE:
1397 subType = EAPOL_M1;
1398 break;
1399 case HDD_ETHERTYPE_802_1_X_M2_VALUE:
1400 subType = EAPOL_M2;
1401 break;
1402 case HDD_ETHERTYPE_802_1_X_M3_VALUE:
1403 subType = EAPOL_M3;
1404 break;
1405 case HDD_ETHERTYPE_802_1_X_M4_VALUE:
1406 subType = EAPOL_M4;
1407 break;
1408 default:
1409 break;
1410 }
1411 }
1412 }
1413
1414 return subType;
1415}
1416
1417/**============================================================================
Abhishek Singhfa011222014-04-14 10:57:08 +05301418 @brief hdd_IsARP() - Checks the packet is ARP or not.
1419
1420 @param pVosPacket : [in] pointer to vos packet
1421 @return : VOS_TRUE if the packet is ARP
1422 : VOS_FALSE otherwise
1423 ===========================================================================*/
1424
1425v_BOOL_t hdd_IsARP( vos_pkt_t *pVosPacket )
1426{
1427 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1428 v_BOOL_t fIsARP = VOS_FALSE;
1429 void *pBuffer = NULL;
1430
1431
1432 vosStatus = vos_pkt_peek_data( pVosPacket,
1433 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1434 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1435 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1436 {
1437 if ( pBuffer && *(unsigned short*)pBuffer ==
1438 vos_cpu_to_be16(HDD_ETHERTYPE_ARP) )
1439 {
1440 fIsARP = VOS_TRUE;
1441 }
1442 }
1443
1444 return fIsARP;
1445}
Jeff Johnson295189b2012-06-20 16:38:30 -07001446
1447#ifdef FEATURE_WLAN_WAPI // Need to update this function
1448/**============================================================================
1449 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1450
1451 @param pVosPacket : [in] pointer to vos packet
1452 @return : VOS_TRUE if the packet is WAI
1453 : VOS_FALSE otherwise
1454 ===========================================================================*/
1455
1456v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1457{
1458 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1459 v_BOOL_t fIsWAI = VOS_FALSE;
1460 void *pBuffer = NULL;
1461
1462 // Need to update this function
1463 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1464 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1465
1466 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1467 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301468 if ( pBuffer && *(unsigned short*)pBuffer ==
1469 vos_cpu_to_be16(HDD_ETHERTYPE_WAI) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001470 {
1471 fIsWAI = VOS_TRUE;
1472 }
1473 }
1474
1475 return fIsWAI;
1476}
1477#endif /* FEATURE_WLAN_WAPI */
1478
1479/**============================================================================
1480 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1481 to indicate that a packet has been transmitted across the SDIO bus
1482 succesfully. OS packet resources can be released after this cbk.
1483
1484 @param vosContext : [in] pointer to VOS context
1485 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1486 @param vosStatusIn : [in] status of the transmission
1487
1488 @return : VOS_STATUS_E_FAILURE if any errors encountered
1489 : VOS_STATUS_SUCCESS otherwise
1490 ===========================================================================*/
1491VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1492 vos_pkt_t *pVosPacket,
1493 VOS_STATUS vosStatusIn )
1494{
1495 VOS_STATUS status = VOS_STATUS_SUCCESS;
1496 hdd_adapter_t *pAdapter = NULL;
1497 hdd_context_t *pHddCtx = NULL;
1498 void* pOsPkt = NULL;
1499
1500 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1501 {
c_hpothu32490782014-03-14 19:14:34 +05301502 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301503 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001504 return VOS_STATUS_E_FAILURE;
1505 }
1506
1507 //Return the skb to the OS
1508 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301509 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001510 {
1511 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301512 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301513 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001514 vos_pkt_return_packet( pVosPacket );
1515 return VOS_STATUS_E_FAILURE;
1516 }
1517
1518 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001519 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001520 //Get the Adapter context.
1521 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Agarwal Ashish971c2882013-10-30 20:11:12 +05301522 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07001523 {
c_hpothu32490782014-03-14 19:14:34 +05301524 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301525 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 }
1527 else
1528 {
1529 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1530 }
1531
1532 kfree_skb((struct sk_buff *)pOsPkt);
1533
1534 //Return the VOS packet resources.
1535 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301536 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001537 {
c_hpothu32490782014-03-14 19:14:34 +05301538 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301539 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001540 }
1541
1542 return status;
1543}
1544
1545
1546/**============================================================================
1547 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1548 fetch a packet for transmission.
1549
1550 @param vosContext : [in] pointer to VOS context
1551 @param staId : [in] Station for which TL is requesting a pkt
1552 @param ac : [in] access category requested by TL
1553 @param pVosPacket : [out] pointer to VOS packet packet pointer
1554 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1555
1556 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1557 : VOS_STATUS_E_FAILURE if any errors encountered
1558 : VOS_STATUS_SUCCESS otherwise
1559 ===========================================================================*/
1560VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1561 v_U8_t *pStaId,
1562 WLANTL_ACEnumType ac,
1563 vos_pkt_t **ppVosPacket,
1564 WLANTL_MetaInfoType *pPktMetaInfo )
1565{
1566 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1567 hdd_adapter_t *pAdapter = NULL;
1568 hdd_context_t *pHddCtx = NULL;
1569 hdd_list_node_t *anchor = NULL;
1570 skb_list_node_t *pktNode = NULL;
1571 struct sk_buff *skb = NULL;
1572 vos_pkt_t *pVosPacket = NULL;
1573 v_MACADDR_t* pDestMacAddress = NULL;
1574 v_TIME_t timestamp;
1575 WLANTL_ACEnumType newAc;
1576 v_SIZE_t size = 0;
Abhishek Singhfa011222014-04-14 10:57:08 +05301577 v_U16_t packet_size;
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001579 v_U8_t proto_type = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001580
1581 //Sanity check on inputs
1582 if ( ( NULL == vosContext ) ||
1583 ( NULL == pStaId ) ||
1584 ( NULL == ppVosPacket ) ||
1585 ( NULL == pPktMetaInfo ) )
1586 {
c_hpothu32490782014-03-14 19:14:34 +05301587 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301588 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 return VOS_STATUS_E_FAILURE;
1590 }
1591
1592 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001593 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001594 if(pHddCtx == NULL)
1595 {
c_hpothu32490782014-03-14 19:14:34 +05301596 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301597 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001598 return VOS_STATUS_E_FAILURE;
1599 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001600 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001601 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001602 {
c_hpothu32490782014-03-14 19:14:34 +05301603 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301604 FL("pAdapter is NULL %u"), *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001605 VOS_ASSERT(0);
1606 return VOS_STATUS_E_FAILURE;
1607 }
1608
1609 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1610
1611 *ppVosPacket = NULL;
1612
1613 //Make sure the AC being asked for is sane
1614 if( ac >= WLANTL_MAX_AC || ac < 0)
1615 {
c_hpothu32490782014-03-14 19:14:34 +05301616 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301617 "%s: Invalid AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 return VOS_STATUS_E_FAILURE;
1619 }
1620
1621 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1622
1623#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301624 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301625 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001626#endif // HDD_WMM_DEBUG
1627
1628 // We find an AC with packets
1629 // or we determine we have no more packets to send
1630 // HDD is not allowed to change AC.
1631
1632 // has this AC been admitted? or
1633 // To allow EAPOL packets when not authenticated
1634 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1635 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1636 {
1637 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1638#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301639 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001640 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001641#endif // HDD_WMM_DEBUG
1642 return VOS_STATUS_E_FAILURE;
1643 }
1644
1645 // do we have any packets pending in this AC?
1646 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1647 if( size > 0 )
1648 {
1649 // yes, so process it
1650#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301651 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001652 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001653#endif // HDD_WMM_DEBUG
1654 }
1655 else
1656 {
1657 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1658#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301659 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001660 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001661#endif // HDD_WMM_DEBUG
1662 return VOS_STATUS_E_FAILURE;
1663 }
1664
1665 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1666 //This simplifies the locking and unlocking of Tx queue
1667 status = vos_pkt_wrap_data_packet( &pVosPacket,
1668 VOS_PKT_TYPE_TX_802_3_DATA,
1669 NULL, //OS Pkt is not being passed
1670 hdd_tx_low_resource_cbk,
1671 pAdapter );
1672
1673 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1674 {
1675 //Remember VOS is in a low resource situation
1676 pAdapter->isVosOutOfResource = VOS_TRUE;
1677 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05301678 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 -07001679 //TL will now think we have no more packets in this AC
1680 return VOS_STATUS_E_FAILURE;
1681 }
1682
1683 //Remove the packet from the queue
1684 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1685 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
1686 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
1687
1688 if(VOS_STATUS_SUCCESS == status)
1689 {
1690 //If success then we got a valid packet from some AC
1691 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1692 skb = pktNode->skb;
1693 }
1694 else
1695 {
1696 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05301697 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001698 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07001699 vos_pkt_return_packet(pVosPacket);
1700 return VOS_STATUS_E_FAILURE;
1701 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001702 //Attach skb to VOS packet.
1703 status = vos_pkt_set_os_packet( pVosPacket, skb );
1704 if (status != VOS_STATUS_SUCCESS)
1705 {
c_hpothu32490782014-03-14 19:14:34 +05301706 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001707 vos_pkt_return_packet(pVosPacket);
1708 ++pAdapter->stats.tx_dropped;
1709 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1710 kfree_skb(skb);
1711 return VOS_STATUS_E_FAILURE;
1712 }
1713
1714 //Just being paranoid. To be removed later
1715 if(pVosPacket == NULL)
1716 {
c_hpothu32490782014-03-14 19:14:34 +05301717 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 -07001718 ++pAdapter->stats.tx_dropped;
1719 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1720 kfree_skb(skb);
1721 return VOS_STATUS_E_FAILURE;
1722 }
1723
Dino Mycle3b9536d2014-07-09 22:05:24 +05301724#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1725 {
1726 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
1727 /* vos_is_macaddr_group expects data in v_MACADDR_t format
1728 */
1729 if (vos_is_macaddr_group(pDestMacAddress))
1730 {
1731 pAdapter->hdd_stats.hddTxRxStats.txMcast[ac]++;
1732 }
1733
1734 }
1735
1736#endif
1737
Chilam NG571c65a2013-01-19 12:27:36 +05301738#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001739 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05301740 {
1741 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05301742 u8 mac[6];
1743
Hoonki Lee387663d2013-02-05 18:08:43 -08001744 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05301745
Hoonki Lee5fcc4582013-02-05 20:28:26 -08001746 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05301747 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301748 "broadcast packet, not adding to peer list");
1749 } else if (memcmp(pHddStaCtx->conn_info.bssId,
1750 mac, 6) != 0) {
c_hpothu32490782014-03-14 19:14:34 +05301751 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07001752 "extract mac: " MAC_ADDRESS_STR,
1753 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05301754
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001755 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05301756 } else {
c_hpothu32490782014-03-14 19:14:34 +05301757 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05301758 "packet da is bssid, not adding to peer list");
1759 }
1760 }
1761#endif
1762
Jeff Johnson295189b2012-06-20 16:38:30 -07001763 //Return VOS packet to TL;
1764 *ppVosPacket = pVosPacket;
1765
1766 //Fill out the meta information needed by TL
1767 //FIXME This timestamp is really the time stamp of wrap_data_packet
1768 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1769 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1770
1771 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1772 pPktMetaInfo->ucIsEapol = 0;
Nirav Shah4f765af2015-01-21 19:51:30 +05301773 else
1774 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001775 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
Nirav Shah4f765af2015-01-21 19:51:30 +05301776 if(pPktMetaInfo->ucIsEapol)
1777 pPktMetaInfo->ucEapolSubType = hdd_FindEapolSubType( pVosPacket );
1778 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001779
Sachin Ahuja8c65f382014-12-12 15:34:21 +05301780 if ((NULL != pHddCtx) &&
1781 (pHddCtx->cfg_ini->gEnableDebugLog))
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001782 {
1783 proto_type = vos_pkt_get_proto_type(skb,
1784 pHddCtx->cfg_ini->gEnableDebugLog);
1785 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1786 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05301787 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4f765af2015-01-21 19:51:30 +05301788 "STA TX EAPOL SubType %d",pPktMetaInfo->ucEapolSubType);
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001789 }
1790 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1791 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05301792 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001793 "STA TX DHCP");
1794 }
1795 }
1796
Abhishek Singhfa011222014-04-14 10:57:08 +05301797 vos_pkt_get_packet_length( pVosPacket,&packet_size );
1798 if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
1799 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
1800
Jeff Johnson295189b2012-06-20 16:38:30 -07001801#ifdef FEATURE_WLAN_WAPI
1802 // Override usIsEapol value when its zero for WAPI case
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301803 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001804#endif /* FEATURE_WLAN_WAPI */
1805
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301806 /* 1. Check if ACM is set for this AC
1807 * 2. If set, check if this AC had already admitted
1808 * 3. If not already admitted, downgrade the UP to next best UP
1809 * 4. Allow only when medium time is non zero when Addts accepted
1810 * else downgrade traffic. we opted downgrading over Delts when
1811 * medium time is zero because while doing downgradig driver is not
1812 * clearing the wmm context so consider in subsequent roaming
1813 * if AP (new or same AP) accept the Addts with valid medium time
1814 * no application support is required where if we have opted
1815 * delts Applications have to again do Addts or STA will never
1816 * go for Addts.
1817 */
1818
1819 if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
1820 (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid &&
1821 pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301823 pPktMetaInfo->ucUP = pktNode->userPriority;
1824 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 }
1826 else
1827 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301828 //Downgrade the UP
1829 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
1830 newAc = WLANTL_AC_BK;
1831 for (i=ac-1; i>0; i--)
Jeff Johnson295189b2012-06-20 16:38:30 -07001832 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301833 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
1834 {
1835 newAc = i;
1836 break;
1837 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001838 }
Agarwal Ashish8b343f12015-01-08 20:06:44 +05301839 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
1840 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1841 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
1842 "Downgrading UP %d to UP %d ",
1843 pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07001844 }
1845
Girish Gowlibf0e1ab2015-01-19 16:05:16 +05301846 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
1847 {
1848 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
1849 }
Mukul Sharma84f27252014-07-14 18:11:42 +05301850
Jeff Johnson295189b2012-06-20 16:38:30 -07001851 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
1852 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
1853 if ( 1 < size )
1854 {
1855 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1856 }
1857 else
1858 {
1859 pPktMetaInfo->bMorePackets = 0;
1860 }
1861
1862 //Extract the destination address from ethernet frame
1863 pDestMacAddress = (v_MACADDR_t*)skb->data;
1864 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1865 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1866
1867
1868
1869 // if we are in a backpressure situation see if we can turn the hose back on
1870 if ( (pAdapter->isTxSuspended[ac]) &&
1871 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
1872 {
1873 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
1874 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05301875 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001876 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001877 pAdapter->isTxSuspended[ac] = VOS_FALSE;
1878 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
1879 skb_get_queue_mapping(skb) ));
Mihir Shete5d148f12014-12-16 17:54:49 +05301880 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_WAKE_NETDEV,
1881 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001882 }
1883
1884
1885 // We're giving the packet to TL so consider it transmitted from
1886 // a statistics perspective. We account for it here instead of
1887 // when the packet is returned for two reasons. First, TL will
1888 // manipulate the skb to the point where the len field is not
1889 // accurate, leading to inaccurate byte counts if we account for
1890 // it later. Second, TL does not provide any feedback as to
1891 // whether or not the packet was successfully sent over the air,
1892 // so the packet counts will be the same regardless of where we
1893 // account for them
1894 pAdapter->stats.tx_bytes += skb->len;
1895 ++pAdapter->stats.tx_packets;
1896 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1897 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05301898 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001899
Leo Chang50bbd252013-04-25 14:58:01 -07001900 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
1901 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07001902 {
1903 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
1904 {
c_hpothu32490782014-03-14 19:14:34 +05301905 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001906 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001907 return VOS_STATUS_E_FAILURE;
1908 }
1909 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
1910 {
1911 if(0 == pHddCtx->tmInfo.txFrameCount)
1912 {
1913 /* Just recovered from sleep timeout */
1914 pHddCtx->tmInfo.lastOpenTs = timestamp;
1915 }
1916
Leo Chang50bbd252013-04-25 14:58:01 -07001917 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
1918 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001919 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1920 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001921 /* During TX open duration, TX frame count is larger than threshold
1922 * Block TX during Sleep time */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05301923 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001924 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07001925 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001926 pHddCtx->tmInfo.lastblockTs = timestamp;
1927 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
1928 {
1929 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
1930 }
1931 }
1932 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
1933 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
1934 {
1935 /* During TX open duration, TX frame count is less than threshold
1936 * Reset count and timestamp to prepare next cycle */
1937 pHddCtx->tmInfo.lastOpenTs = timestamp;
1938 pHddCtx->tmInfo.txFrameCount = 0;
1939 }
1940 else
1941 {
1942 /* Do Nothing */
1943 }
1944 pHddCtx->tmInfo.txFrameCount++;
1945 }
1946 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
1947 }
1948
1949
1950#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301951 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 -07001952#endif // HDD_WMM_DEBUG
1953
1954 return status;
1955}
1956
1957
1958/**============================================================================
1959 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
1960 case where VOS packets are not available at the time of the call to get
1961 packets. This callback function is invoked by VOS when packets are
1962 available.
1963
1964 @param pVosPacket : [in] pointer to VOS packet
1965 @param userData : [in] opaque user data that was passed initially
1966
1967 @return : VOS_STATUS_E_FAILURE if any errors encountered,
1968 : VOS_STATUS_SUCCESS otherwise
1969 =============================================================================*/
1970VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
1971 v_VOID_t *userData )
1972{
1973 VOS_STATUS status;
1974 v_SINT_t i = 0;
1975 v_SIZE_t size = 0;
1976 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
1977
Agarwal Ashish971c2882013-10-30 20:11:12 +05301978 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001979 {
c_hpothu32490782014-03-14 19:14:34 +05301980 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301981 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001982 return VOS_STATUS_E_FAILURE;
1983 }
1984
1985 //Return the packet to VOS. We just needed to know that VOS is out of low resource
1986 //situation. Here we will only signal TL that there is a pending data for a STA.
1987 //VOS packet will be requested (if needed) when TL comes back to fetch data.
1988 vos_pkt_return_packet( pVosPacket );
1989
1990 pAdapter->isVosOutOfResource = VOS_FALSE;
1991
1992 //Indicate to TL that there is pending data if a queue is non empty
1993 for( i=NUM_TX_QUEUES-1; i>=0; --i )
1994 {
1995 size = 0;
1996 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
1997 if ( size > 0 )
1998 {
1999 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
2000 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
2001 (WLANTL_ACEnumType)i );
2002 if( !VOS_IS_STATUS_SUCCESS( status ) )
2003 {
c_hpothu32490782014-03-14 19:14:34 +05302004 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302005 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07002006 }
2007 }
2008 }
2009
2010 return VOS_STATUS_SUCCESS;
2011}
2012
2013
2014/**============================================================================
2015 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
2016 TL will call this to notify the HDD when one or more packets were
2017 received for a registered STA.
2018
2019 @param vosContext : [in] pointer to VOS context
2020 @param pVosPacketChain : [in] pointer to VOS packet chain
2021 @param staId : [in] Station Id
2022 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
2023
2024 @return : VOS_STATUS_E_FAILURE if any errors encountered,
2025 : VOS_STATUS_SUCCESS otherwise
2026 ===========================================================================*/
2027VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
2028 vos_pkt_t *pVosPacketChain,
2029 v_U8_t staId,
2030 WLANTL_RxMetaInfoType* pRxMetaInfo )
2031{
2032 hdd_adapter_t *pAdapter = NULL;
2033 hdd_context_t *pHddCtx = NULL;
2034 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2035 int rxstat;
2036 struct sk_buff *skb = NULL;
2037 vos_pkt_t* pVosPacket;
2038 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002039 v_U8_t proto_type;
Nirav Shah4f765af2015-01-21 19:51:30 +05302040 EAPOL_SubType eapolSubType;
Jeff Johnson295189b2012-06-20 16:38:30 -07002041
2042 //Sanity check on inputs
2043 if ( ( NULL == vosContext ) ||
2044 ( NULL == pVosPacketChain ) ||
2045 ( NULL == pRxMetaInfo ) )
2046 {
c_hpothu32490782014-03-14 19:14:34 +05302047 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302048 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002049 return VOS_STATUS_E_FAILURE;
2050 }
2051
Kiet Lam3c2ee302014-03-23 23:23:22 -07002052 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07002053 if ( NULL == pHddCtx )
2054 {
c_hpothu32490782014-03-14 19:14:34 +05302055 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302056 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002057 return VOS_STATUS_E_FAILURE;
2058 }
2059
2060 pAdapter = pHddCtx->sta_to_adapter[staId];
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05302061 if( (NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002062 {
Abhishek Singh82a7a5b2014-10-07 13:05:12 +05302063 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2064 "%s: pAdapter is Null or adapter has invalid magic for staId %u",
Madan Mohan Koyyalamudi858bb362013-08-05 19:57:37 +05302065 __func__, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002066 return VOS_STATUS_E_FAILURE;
2067 }
2068
2069 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
2070
2071 // walk the chain until all are processed
2072 pVosPacket = pVosPacketChain;
2073 do
2074 {
2075 // get the pointer to the next packet in the chain
2076 // (but don't unlink the packet since we free the entire chain later)
2077 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
2078
2079 // both "success" and "empty" are acceptable results
2080 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
2081 {
2082 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302083 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302084 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002085 return VOS_STATUS_E_FAILURE;
2086 }
2087
Nirav Shah4f765af2015-01-21 19:51:30 +05302088 if (pHddCtx->cfg_ini->gEnableDebugLog)
2089 {
2090 if (hdd_IsEAPOLPacket(pVosPacket))
2091 eapolSubType = hdd_FindEapolSubType(pVosPacket);
2092 }
2093
Jeff Johnson295189b2012-06-20 16:38:30 -07002094 // Extract the OS packet (skb).
2095 // Tell VOS to detach the OS packet from the VOS packet
2096 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
2097 if(!VOS_IS_STATUS_SUCCESS( status ))
2098 {
2099 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302100 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302101 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002102 return VOS_STATUS_E_FAILURE;
2103 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002104
2105 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2106 {
c_hpothu32490782014-03-14 19:14:34 +05302107 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07002108 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
2109 return eHAL_STATUS_FAILURE;
2110 }
2111
Chilam Ng1279e232013-01-25 15:06:52 -08002112#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002113 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
2114 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08002115 {
2116 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08002117 u8 mac[6];
2118
Hoonki Lee387663d2013-02-05 18:08:43 -08002119 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08002120
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002121 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302122 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002123 "rx broadcast packet, not adding to peer list");
2124 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2125 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002126 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05302127 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002128 "rx extract mac:" MAC_ADDRESS_STR,
2129 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302130 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05302131 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
2132 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002133 {
2134 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05302135 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002136 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
2137 }
Chilam Ng1279e232013-01-25 15:06:52 -08002138 } else {
c_hpothu32490782014-03-14 19:14:34 +05302139 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002140 "rx packet sa is bssid, not adding to peer list");
2141 }
2142 }
2143#endif
2144
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002145 if (pHddCtx->cfg_ini->gEnableDebugLog)
2146 {
2147 proto_type = vos_pkt_get_proto_type(skb,
2148 pHddCtx->cfg_ini->gEnableDebugLog);
2149 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2150 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4f765af2015-01-21 19:51:30 +05302152 "STA RX EAPOL SubType %d",eapolSubType);
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002153 }
2154 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2155 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302156 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002157 "STA RX DHCP");
2158 }
2159 }
2160
Girish Gowli8a7bc042015-01-19 16:20:20 +05302161 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
2162 {
2163 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2164 }
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302165 if (( NULL != pHddCtx ) &&
2166 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05302167 {
2168 hdd_dump_dhcp_pkt(skb, RX_PATH);
2169 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302170
Jeff Johnson295189b2012-06-20 16:38:30 -07002171 skb->dev = pAdapter->dev;
2172 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002173 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002174 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2175 ++pAdapter->stats.rx_packets;
2176 pAdapter->stats.rx_bytes += skb->len;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002177#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002178#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002179 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002180#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002181#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002182 rxstat = netif_rx_ni(skb);
2183 if (NET_RX_SUCCESS == rxstat)
2184 {
2185 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002186 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002187 }
2188 else
2189 {
2190 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2191 }
2192 // now process the next packet in the chain
2193 pVosPacket = pNextVosPacket;
2194
2195 } while (pVosPacket);
2196
2197 //Return the entire VOS packet chain to the resource pool
2198 status = vos_pkt_return_packet( pVosPacketChain );
2199 if(!VOS_IS_STATUS_SUCCESS( status ))
2200 {
c_hpothu32490782014-03-14 19:14:34 +05302201 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002202 }
2203
2204 pAdapter->dev->last_rx = jiffies;
2205
2206 return status;
2207}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002208/**============================================================================
2209 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2210 Enable/Disable split scan based on TX and RX traffic.
2211 @param HddContext : [in] pointer to Hdd context
2212 @return : None
2213 ===========================================================================*/
2214void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2215{
2216 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2217 hdd_adapter_t *pAdapter = NULL;
2218 hdd_station_ctx_t *pHddStaCtx = NULL;
2219 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2220 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2221 VOS_STATUS status;
2222 v_U8_t staId = 0;
2223 v_U8_t fconnected = 0;
2224
c_hpothub8245442013-11-20 23:41:09 +05302225 if (NULL == phddctx)
2226 {
c_hpothu32490782014-03-14 19:14:34 +05302227 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05302228 FL("phddctx is NULL"));
2229 VOS_ASSERT(0);
2230 return;
2231 }
2232
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002233 if (!cfg_param->dynSplitscan)
2234 {
c_hpothu32490782014-03-14 19:14:34 +05302235 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002236 "%s: Error : Dynamic split scan is not Enabled : %d",
2237 __func__, pHddCtx->cfg_ini->dynSplitscan);
2238 return;
2239 }
2240
2241 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2242 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2243 {
2244 pAdapter = pAdapterNode->pAdapter;
2245
2246 if ( pAdapter )
2247 {
c_hpothu32490782014-03-14 19:14:34 +05302248 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002249 "%s: Adapter with device mode %d exists",
2250 __func__, pAdapter->device_mode);
2251
2252 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2253 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2254 {
2255 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2256 if ((eConnectionState_Associated ==
2257 pHddStaCtx->conn_info.connState) &&
2258 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2259 {
2260 fconnected = TRUE;
2261 }
2262 }
2263 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2264 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2265 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302266 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2267 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2268 if(pSapCtx == NULL){
2269 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2270 FL("psapCtx is NULL"));
2271 return;
2272 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002273 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2274 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302275 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002276 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302277 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002278 {
2279 fconnected = TRUE;
2280 }
2281 }
2282 }
2283 if ( fconnected )
2284 {
c_hpothu32490782014-03-14 19:14:34 +05302285 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002286 "%s: One of the interface is connected check for scan",
2287 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302288 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302289 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
2290 "miracast = %d", __func__,
2291 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
2292 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
2293 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002294
2295 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
2296 cfg_param->trafficMntrTmrForSplitScan);
2297 //Check for the previous statistics count
2298 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
2299 cfg_param->txRxThresholdForSplitScan) ||
2300 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
2301 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05302302 pHddCtx->drvr_miracast ||
2303 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002304 {
2305 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2306 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2307
2308 if (!pHddCtx->issplitscan_enabled)
2309 {
2310 pHddCtx->issplitscan_enabled = TRUE;
2311 sme_enable_disable_split_scan(
2312 WLAN_HDD_GET_HAL_CTX(pAdapter),
2313 cfg_param->nNumStaChanCombinedConc,
2314 cfg_param->nNumP2PChanCombinedConc);
2315 }
2316 return;
2317 }
2318 else
2319 {
2320 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2321 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2322 }
2323 fconnected = FALSE;
2324 }
2325 }
2326 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
2327 pAdapterNode = pNext;
2328 }
2329
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05302330 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
2331 * of disabling the split scan and thus do not disable the same when the
2332 * low TXRX condition is met.
2333 */
2334 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002335 {
c_hpothu32490782014-03-14 19:14:34 +05302336 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002337 "%s: Disable split scan", __func__);
2338 pHddCtx->issplitscan_enabled = FALSE;
2339 sme_enable_disable_split_scan(
2340 pHddCtx->hHal,
2341 SME_DISABLE_SPLIT_SCAN,
2342 SME_DISABLE_SPLIT_SCAN);
2343 }
2344 return;
2345}
Jeff Johnson295189b2012-06-20 16:38:30 -07002346