blob: c21d892442e327d0e17bce460f550effc66d3440 [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
Sushant Kaushika8073312015-05-04 17:33:52 +053063#include "vos_diag_core_event.h"
Mukul Sharma84f27252014-07-14 18:11:42 +053064#include "vos_utils.h"
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053065#include "sapInternal.h"
Mihir Shete5d148f12014-12-16 17:54:49 +053066#include "wlan_hdd_trace.h"
Katya Nigame7b69a82015-04-28 15:24:06 +053067#include "wlan_qct_wda.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070068/*---------------------------------------------------------------------------
69 Preprocessor definitions and constants
70 -------------------------------------------------------------------------*/
71
72const v_U8_t hddWmmAcToHighestUp[] = {
73 SME_QOS_WMM_UP_RESV,
74 SME_QOS_WMM_UP_EE,
75 SME_QOS_WMM_UP_VI,
76 SME_QOS_WMM_UP_NC
77};
78
79//Mapping Linux AC interpretation to TL AC.
80const v_U8_t hdd_QdiscAcToTlAC[] = {
81 WLANTL_AC_VO,
82 WLANTL_AC_VI,
83 WLANTL_AC_BE,
84 WLANTL_AC_BK,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +053085 WLANTL_AC_HIGH_PRIO,
Jeff Johnson295189b2012-06-20 16:38:30 -070086};
87
Mihir Shetec8fe71b2014-06-16 15:32:59 +053088#define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
89#define HDD_TX_TIMEOUT_RATELIMIT_BURST 1
Mihir Shetef3473692014-06-27 15:13:20 +053090#define HDD_TX_STALL_SSR_THRESHOLD 5
Mihir Shete0be28772015-02-17 18:42:14 +053091#define HDD_TX_STALL_SSR_THRESHOLD_HIGH 13
Mihir Shete327c2ab2014-11-13 15:17:02 +053092#define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
Mihir Shetec8fe71b2014-06-16 15:32:59 +053093
Katya Nigame7b69a82015-04-28 15:24:06 +053094int gRatefromIdx[] = {
95 10,20,55,100,
96 10,20,55,110,
97 60,90,120,180,240,360,480,540,
98 65,130,195,260,390,520,585,650,
99 72,144,217,289,434,578,650,722,
100 65,130,195,260,390,520,585,650,
101 135,270,405,540,810,1080,1215,1350,
102 150,300,450,600,900,1200,1350,1500,
103 135,270,405,540,810,1080,1215,1350,
104 1350,1350,65,130,195,260,390, 520,
105 585,650,780,1350,1350,1350,1350,1350,
106 1350,1350,1350,1350,655,722,866,1350,
107 1350,1350,135,270,405,540,810,1080,
108 1215,1350,1350,1620,1800,1350,1350,1350,
109 1350,1350,1350,1200,1350,1500,1350,1800,
110 2000,1350, 292,585,877,1170,1755,2340,
111 2632,2925,1350,3510,3900,1350,1350,1350,
112 1350,1350,1350,1350,2925,3250,1350,3900,
113 4333
114 };
Sushant Kaushika8073312015-05-04 17:33:52 +0530115#ifdef FEATURE_WLAN_DIAG_SUPPORT
116#define HDD_EAPOL_PACKET_TYPE_OFFSET (15)
117#define HDD_EAPOL_KEY_INFO_OFFSET (19)
118#define HDD_EAPOL_DEST_MAC_OFFSET (0)
119#define HDD_EAPOL_SRC_MAC_OFFSET (6)
120#endif /* FEATURE_WLAN_DIAG_SUPPORT */
Katya Nigame7b69a82015-04-28 15:24:06 +0530121
122
Mihir Shetec8fe71b2014-06-16 15:32:59 +0530123static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs, \
124 HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
125 HDD_TX_TIMEOUT_RATELIMIT_BURST);
126
Jeff Johnson295189b2012-06-20 16:38:30 -0700127static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129/*---------------------------------------------------------------------------
130 Type declarations
131 -------------------------------------------------------------------------*/
132
133/*---------------------------------------------------------------------------
134 Function definitions and documenation
135 -------------------------------------------------------------------------*/
136
137#ifdef DATA_PATH_UNIT_TEST
138//Utility function to dump an sk_buff
139static void dump_sk_buff(struct sk_buff * skb)
140{
c_hpothu32490782014-03-14 19:14:34 +0530141 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head);
142 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data);
143 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail);
144 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end);
145 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len);
146 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len);
147 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 -0700148
c_hpothu32490782014-03-14 19:14:34 +0530149 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 -0700150 skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4],
151 skb->data[5], skb->data[6], skb->data[7]);
c_hpothu32490782014-03-14 19:14:34 +0530152 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 -0700153 skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12],
154 skb->data[13], skb->data[14], skb->data[15]);
155}
156
157//Function for Unit Test only
158static void transport_thread(hdd_adapter_t *pAdapter)
159{
160 v_U8_t staId;
161 WLANTL_ACEnumType ac = WLANTL_AC_BE;
162 vos_pkt_t *pVosPacket = NULL ;
163 vos_pkt_t dummyPacket;
164 WLANTL_MetaInfoType pktMetaInfo;
165 WLANTL_RxMetaInfoType pktRxMetaInfo;
166 VOS_STATUS status = VOS_STATUS_E_FAILURE;
167
c_hpothub8245442013-11-20 23:41:09 +0530168 if (NULL == pAdapter)
169 {
c_hpothu32490782014-03-14 19:14:34 +0530170 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530171 FL("pAdapter is NULL"));
172 VOS_ASSERT(0);
173 return;
174 }
175
Jeff Johnson295189b2012-06-20 16:38:30 -0700176 status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext,
177 &staId,
178 &ac,
179 &pVosPacket,
180 &pktMetaInfo );
181 if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY)
c_hpothu32490782014-03-14 19:14:34 +0530182 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
183 "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700184 else
c_hpothu32490782014-03-14 19:14:34 +0530185 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
186 "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700187
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700188 status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS);
Jeff Johnson295189b2012-06-20 16:38:30 -0700189 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530190 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
191 "%s: Test FAIL hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192 else
c_hpothu32490782014-03-14 19:14:34 +0530193 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
194 "%s: Test PASS hdd_tx_complete_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700195
196 status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter);
197 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530198 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
199 "%s: Test FAIL hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700200 else
c_hpothu32490782014-03-14 19:14:34 +0530201 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
202 "%s: Test PASS hdd_tx_low_resource_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700203
204 status = hdd_rx_packet_cbk( pAdapter->pvosContext,
205 &dummyPacket,
206 staId,
207 &pktRxMetaInfo);
208 if (status != VOS_STATUS_SUCCESS)
c_hpothu32490782014-03-14 19:14:34 +0530209 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
210 "%s: Test FAIL hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700211 else
c_hpothu32490782014-03-14 19:14:34 +0530212 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
213 "%s: Test PASS hdd_rx_packet_cbk", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700214
215}
216#endif
217
218
219/**============================================================================
220 @brief hdd_flush_tx_queues() - Utility function to flush the TX queues
221
222 @param pAdapter : [in] pointer to adapter context
223 @return : VOS_STATUS_E_FAILURE if any errors encountered
224 : VOS_STATUS_SUCCESS otherwise
225 ===========================================================================*/
226static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter )
227{
228 VOS_STATUS status = VOS_STATUS_SUCCESS;
229 v_SINT_t i = -1;
230 hdd_list_node_t *anchor = NULL;
231 skb_list_node_t *pktNode = NULL;
232 struct sk_buff *skb = NULL;
233
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530234 pAdapter->isVosLowResource = VOS_FALSE;
235
Mihir Shete5d148f12014-12-16 17:54:49 +0530236 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_FLUSH_TX_QUEUES,
237 pAdapter->sessionId, 0));
238
Jeff Johnson295189b2012-06-20 16:38:30 -0700239 while (++i != NUM_TX_QUEUES)
240 {
241 //Free up any packets in the Tx queue
242 spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
243 while (true)
244 {
245 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor );
246 if(VOS_STATUS_E_EMPTY != status)
247 {
248 pktNode = list_entry(anchor, skb_list_node_t, anchor);
249 skb = pktNode->skb;
250 //TODO
251 //++pAdapter->stats.tx_dropped;
252 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
253 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
254 kfree_skb(skb);
255 continue;
256 }
257 break;
258 }
259 spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
260 // backpressure is no longer in effect
261 pAdapter->isTxSuspended[i] = VOS_FALSE;
262 }
263
264 return status;
265}
266
Ravi Joshif9520d62013-10-18 04:11:46 -0700267/**============================================================================
268 @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues
269 in IBSS mode
270
271 @param pAdapter : [in] pointer to adapter context
272 : [in] Staion Id
273 @return : VOS_STATUS_E_FAILURE if any errors encountered
274 : VOS_STATUS_SUCCESS otherwise
275 ===========================================================================*/
276void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId)
277{
278 v_U8_t i;
Katya Nigam47528772015-02-11 12:24:49 +0530279 hdd_list_node_t *anchor = NULL;
Ravi Joshi41914632013-10-21 23:02:21 -0700280 skb_list_node_t *pktNode = NULL;
Ravi Joshi41914632013-10-21 23:02:21 -0700281 struct sk_buff *skb = NULL;
Katya Nigam47528772015-02-11 12:24:49 +0530282 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
283 hdd_ibss_peer_info_t *pPeerInfo = &pHddStaCtx->ibss_peer_info;
Ravi Joshif9520d62013-10-18 04:11:46 -0700284
Katya Nigam47528772015-02-11 12:24:49 +0530285 for (i = 0; i < NUM_TX_QUEUES; i ++)
c_hpothub8245442013-11-20 23:41:09 +0530286 {
Katya Nigam47528772015-02-11 12:24:49 +0530287 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
288 while (true)
Ravi Joshif9520d62013-10-18 04:11:46 -0700289 {
Katya Nigam47528772015-02-11 12:24:49 +0530290 if (VOS_STATUS_E_EMPTY !=
291 hdd_list_remove_front(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i],
292 &anchor))
Ravi Joshif9520d62013-10-18 04:11:46 -0700293 {
Katya Nigam47528772015-02-11 12:24:49 +0530294 //If success then we got a valid packet from some AC
295 pktNode = list_entry(anchor, skb_list_node_t, anchor);
Ravi Joshif9520d62013-10-18 04:11:46 -0700296 skb = pktNode->skb;
Katya Nigam47528772015-02-11 12:24:49 +0530297 ++pAdapter->stats.tx_dropped;
298 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
299 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
300 kfree_skb(skb);
301 continue;
Ravi Joshif9520d62013-10-18 04:11:46 -0700302 }
Katya Nigam47528772015-02-11 12:24:49 +0530303 break;
Ravi Joshif9520d62013-10-18 04:11:46 -0700304 }
Katya Nigam47528772015-02-11 12:24:49 +0530305 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
Ravi Joshif9520d62013-10-18 04:11:46 -0700306 }
307}
308
Jeff Johnson295189b2012-06-20 16:38:30 -0700309static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter)
310{
311 skb_list_node_t *pktNode = NULL;
312 struct sk_buff *skb = NULL;
313 v_SIZE_t size = 0;
314 WLANTL_ACEnumType ac = 0;
315 VOS_STATUS status = VOS_STATUS_E_FAILURE;
316 hdd_list_node_t *anchor = NULL;
317
c_hpothu77731d42014-01-23 13:59:03 +0530318 if (NULL == pAdapter)
319 {
320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
321 FL("pAdapter is NULL"));
322 VOS_ASSERT(0);
323 return NULL;
324 }
325
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 // do we have any packets pending in this AC?
327 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
328 if( size == 0 )
329 {
c_hpothu32490782014-03-14 19:14:34 +0530330 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700331 "%s: NO Packet Pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700332 return NULL;
333 }
334
335 //Remove the packet from the queue
336 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
337 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
338 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
339
340 if(VOS_STATUS_SUCCESS == status)
341 {
342 //If success then we got a valid packet from some AC
343 pktNode = list_entry(anchor, skb_list_node_t, anchor);
344 skb = pktNode->skb;
345 }
346 else
347 {
c_hpothu32490782014-03-14 19:14:34 +0530348 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700349 "%s: Not able to remove Packet from the list",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700350 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700351
352 return NULL;
353 }
354
355 // if we are in a backpressure situation see if we can turn the hose back on
356 if ( (pAdapter->isTxSuspended[ac]) &&
357 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
358 {
c_hpothu32490782014-03-14 19:14:34 +0530359 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700360 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700361 pAdapter->isTxSuspended[ac] = VOS_FALSE;
362 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530363 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700364 netif_tx_start_all_queues( pAdapter->dev );
365 }
366
367 return skb;
368}
369
370void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
371{
372 hdd_cfg80211_state_t *cfgState;
373 struct sk_buff* skb;
374 hdd_adapter_t* pMonAdapter = NULL;
375 struct ieee80211_hdr *hdr;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530376 hdd_context_t *pHddCtx;
377 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700378
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530379 ENTER();
Mukul Sharma23a92232014-04-07 18:04:00 +0530380 if (pAdapter == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700381 {
c_hpothu32490782014-03-14 19:14:34 +0530382 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +0530383 FL("pAdapter is NULL"));
384 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 return;
386 }
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530387 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
388 ret = wlan_hdd_validate_context(pHddCtx);
389 if (0 != ret)
390 {
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530391 return;
392 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700393 pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
Mukul Sharma23a92232014-04-07 18:04:00 +0530394 if (pMonAdapter == NULL)
395 {
396 hddLog(VOS_TRACE_LEVEL_ERROR,
397 "%s: pMonAdapter is NULL", __func__);
398 return;
399 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700400 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
401
402 if( NULL != cfgState->buf )
403 {
c_hpothu32490782014-03-14 19:14:34 +0530404 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700405 "%s: Already one MGMT packet Tx going on", __func__);
406 return;
407 }
408
409 skb = hdd_mon_tx_fetch_pkt(pMonAdapter);
410
411 if (NULL == skb)
412 {
c_hpothu32490782014-03-14 19:14:34 +0530413 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700414 "%s: No Packet Pending", __func__);
415 return;
416 }
417
418 cfgState->buf = vos_mem_malloc( skb->len ); //buf;
419 if( cfgState->buf == NULL )
420 {
c_hpothu32490782014-03-14 19:14:34 +0530421 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700422 "%s: Failed to Allocate memory", __func__);
423 goto fail;
424 }
425
426 cfgState->len = skb->len;
427
428 vos_mem_copy( cfgState->buf, skb->data, skb->len);
429
430 cfgState->skb = skb; //buf;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800431 cfgState->action_cookie = (uintptr_t)cfgState->buf;
Jeff Johnson295189b2012-06-20 16:38:30 -0700432
433 hdr = (struct ieee80211_hdr *)skb->data;
434 if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
435 == HDD_FRAME_TYPE_MGMT )
436 {
437 if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
438 == HDD_FRAME_SUBTYPE_DEAUTH )
439 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530440 struct tagCsrDelStaParams delStaParams;
441
Sushant Kaushik4cd28f62014-12-26 14:23:50 +0530442 WLANSAP_PopulateDelStaParams(hdr->addr1,
443 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +0530444 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
445
446 hdd_softap_sta_deauth(pAdapter, &delStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -0700447 goto mgmt_handled;
448 }
449 else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
450 == HDD_FRAME_SUBTYPE_DISASSOC )
451 {
452 hdd_softap_sta_disassoc( pAdapter, hdr->addr1 );
453 goto mgmt_handled;
454 }
455 }
c_hpothu32490782014-03-14 19:14:34 +0530456 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700457 "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);
458
Jeff Johnson43971f52012-07-17 12:26:56 -0700459 if (VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700460 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700461 skb->data, skb->len, 0) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700462 {
c_hpothu32490782014-03-14 19:14:34 +0530463 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -0700464 "%s: WLANSAP_SendAction returned fail", __func__);
465 hdd_sendActionCnf( pAdapter, FALSE );
466 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530467 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 return;
469
470mgmt_handled:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530471 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 hdd_sendActionCnf( pAdapter, TRUE );
473 return;
474fail:
475 kfree_skb(pAdapter->skb_to_tx);
476 pAdapter->skb_to_tx = NULL;
477 return;
478}
479
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530480void __hdd_mon_tx_work_queue(struct work_struct *work)
Jeff Johnson295189b2012-06-20 16:38:30 -0700481{
482 hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue);
483 hdd_mon_tx_mgmt_pkt(pAdapter);
484}
485
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530486void hdd_mon_tx_work_queue(struct work_struct *work)
487{
488 vos_ssr_protect(__func__);
489 __hdd_mon_tx_work_queue(work);
490 vos_ssr_unprotect(__func__);
491}
492
Jeff Johnson295189b2012-06-20 16:38:30 -0700493int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
494{
Katya Nigame7b69a82015-04-28 15:24:06 +0530495 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
496 "%s: Packet Rcvd at Monitor interface,"
497 " Dropping the packet",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700498 kfree_skb(skb);
499 return NETDEV_TX_OK;
500}
Dino Mycled9b7cc12014-09-04 18:43:07 +0530501
502/**============================================================================
503 @brief hdd_dhcp_pkt_info() -
504 Function to log DHCP pkt info
505
506 @param skb : [in] pointer to OS packet (sk_buff)
507 @return : None
508 ===========================================================================*/
509
510void hdd_dhcp_pkt_info(struct sk_buff *skb)
511{
512 /* port no 67 (0x43) or 68 (0x44) */
513
514 if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_REQUEST_MSG)
515 hddLog(VOS_TRACE_LEVEL_INFO, FL("Request"));
516 else if (*((u8*)skb->data + BOOTP_MSG_OFFSET) == BOOTP_RESPONSE_MSG)
517 hddLog(VOS_TRACE_LEVEL_INFO, FL("Response"));
518 else
519 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP invalid"));
520
521 hddLog(VOS_TRACE_LEVEL_INFO,
522 FL("DHCP Dest Addr: %pM Src Addr %pM "
523 " source port : %d, dest port : %d"),
524 skb->data, (skb->data + 6),
525 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))),
526 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))));
527
528 if ((skb->data[DHCP_OPTION53_OFFSET] == DHCP_OPTION53) &&
529 (skb->data[DHCP_OPTION53_LENGTH_OFFSET] == DHCP_OPTION53_LENGTH)) {
530
531 switch (skb->data[DHCP_OPTION53_STATUS_OFFSET]) {
532 case DHCPDISCOVER:
533 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP DISCOVER"));
534 break;
535 case DHCPREQUEST:
536 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP REQUEST"));
537 break;
538 case DHCPOFFER:
539 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP OFFER"));
540 break;
541 case DHCPACK:
542 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP ACK"));
543 break;
544 case DHCPNAK:
545 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP NACK"));
546 break;
547 case DHCPRELEASE:
548 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP RELEASE"));
549 break;
550 case DHCPINFORM:
551 hddLog(VOS_TRACE_LEVEL_INFO,FL("DHCP INFORM"));
552 break;
553
554 default:
555 hddLog(VOS_TRACE_LEVEL_INFO,
556 "%s: DHCP Not Defined OPTION53 : %d", __func__,
557 skb->data[DHCP_OPTION53_STATUS_OFFSET]);
558 }
559 }
560}
561
562/**============================================================================
563 @brief hdd_dump_dhcp_pkt() -
564 Function to dump DHCP packets in TX and RX path.
565
566 @param skb : [in] pointer to OS packet (sk_buff)
567 @param path : [in] bool indicating TX/RX path
568 @return : None
569 ===========================================================================*/
570void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path)
571{
572
573 if ((ntohs(*((u16*)((u8*)skb->data + ETH_TYPE_OFFSET)))
574 == ETH_TYPE_IP_PKT) ||
575 (ntohs(*((u8*)skb->data + PROTOCOL_OFFSET)) == UDP_PROTOCOL)) {
576
577 /* IP protocol 12 bytes of mac addresses in 802.3 header */
578 if ( ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
579 BOOTP_SERVER_PORT ||
580 ntohs(*((u16*)((u8*)skb->data + UDP_DEST_PORT_OFFSET))) ==
581 BOOTP_CLIENT_PORT ||
582 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
583 BOOTP_SERVER_PORT ||
584 ntohs(*((u16*)((u8*)skb->data + UDP_SRC_PORT_OFFSET))) ==
585 BOOTP_CLIENT_PORT ) {
586
587 if (path == TX_PATH) {
588 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP TX PATH"));
589 } else {
590 hddLog(VOS_TRACE_LEVEL_INFO, FL("DHCP RX PATH"));
591 }
592
593 hdd_dhcp_pkt_info(skb);
594 }
595 }
596}
597
Jeff Johnson295189b2012-06-20 16:38:30 -0700598/**============================================================================
Katya Nigam77fcf582015-02-09 16:48:24 +0530599 @brief hdd_ibss_hard_start_xmit() - Function registered with the Linux OS for
600 transmitting packets in case of IBSS. There are 2 versions of this function.
601 One that uses locked queue and other that uses lockless queues. Both have been
602 retained to do some performance testing
603
604 @param skb : [in] pointer to OS packet (sk_buff)
605 @param dev : [in] pointer to network device
606
607 @return : NET_XMIT_DROP if packets are dropped
608 : NET_XMIT_SUCCESS if packet is enqueued succesfully
609 ===========================================================================*/
610 int hdd_ibss_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
611 {
612 VOS_STATUS status;
613 WLANTL_ACEnumType ac;
614 sme_QosWmmUpType up;
615 skb_list_node_t *pktNode = NULL;
616 hdd_list_node_t *anchor = NULL;
617 v_SIZE_t pktListSize = 0;
618 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
619 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
620 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
621 hdd_ibss_peer_info_t * pPeerInfo;
622 v_U8_t STAId = WLAN_MAX_STA_COUNT;
623 v_BOOL_t txSuspended = VOS_FALSE;
624 struct sk_buff *skb1;
625 v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
626
627 if (NULL == pHddCtx || NULL == pHddStaCtx) {
628 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
629 "%s HDD context is NULL", __func__);
630 return NETDEV_TX_BUSY;
631 }
632 pPeerInfo = &pHddStaCtx->ibss_peer_info;
633 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
634
635 //Get TL AC corresponding to Qdisc queue index/AC.
636 ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
637
638 if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState)
639 {
640 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
641 "%s: Tx frame in disconnected state in IBSS mode", __func__);
642 ++pAdapter->stats.tx_dropped;
643 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
644 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
645 kfree_skb(skb);
646 return NETDEV_TX_OK;
647 }
648
Nirav Shah7e3c8132015-06-22 23:51:42 +0530649 STAId = hdd_sta_id_find_from_mac_addr(pAdapter, pDestMacAddress);
Katya Nigam77fcf582015-02-09 16:48:24 +0530650 if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
651 (vos_is_macaddr_broadcast( pDestMacAddress ) ||
652 vos_is_macaddr_group(pDestMacAddress)))
653 {
654 STAId = IBSS_BROADCAST_STAID;
655 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
656 "%s: BC/MC packet", __func__);
657 }
658 else if (STAId >= HDD_MAX_NUM_IBSS_STA)
659 {
660 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
661 "%s: Received Unicast frame with invalid staID", __func__);
662 ++pAdapter->stats.tx_dropped;
663 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
664 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
665 kfree_skb(skb);
666 return NETDEV_TX_OK;
667 }
668
669 //user priority from IP header, which is already extracted and set from
670 //select_queue call back function
671 up = skb->priority;
672 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
673
674 VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
675 "%s: Classified as ac %d up %d", __func__, ac, up);
676
677 if ( pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP )
678 {
679 hdd_dump_dhcp_pkt(skb, TX_PATH);
680 }
681
682 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
683 hdd_list_size(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &pktListSize);
684 if(pktListSize >= pAdapter->aTxQueueLimit[ac])
685 {
686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
687 "%s: station %d ac %d queue over limit %d", __func__, STAId, ac, pktListSize);
688 pPeerInfo->ibssStaInfo[STAId].txSuspended[ac] = VOS_TRUE;
689 netif_stop_subqueue(dev, skb_get_queue_mapping(skb));
690 txSuspended = VOS_TRUE;
691 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
692 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
693 "%s: TX queue full for AC=%d Disable OS TX queue",
694 __func__, ac );
695 return NETDEV_TX_BUSY;
696 }
697
698 /* If 3/4th of the max queue size is used then enable the flag.
699 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
700 if (WLANTL_AC_BE == ac)
701 {
702 if (pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
703 {
704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
705 "%s: TX queue for Best Effort AC is 3/4th full", __func__);
706 pAdapter->isVosLowResource = VOS_TRUE;
707 }
708 else
709 {
710 pAdapter->isVosLowResource = VOS_FALSE;
711 }
712 }
713
714 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
715
716 //Use the skb->cb field to hold the list node information
717 pktNode = (skb_list_node_t *)&skb->cb;
718
719 //Stick the OS packet inside this node.
720 pktNode->skb = skb;
721
722 //Stick the User Priority inside this node
723 pktNode->userPriority = up;
724
725 INIT_LIST_HEAD(&pktNode->anchor);
726
727 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
728 status = hdd_list_insert_back_size( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac],
729 &pktNode->anchor, &pktListSize );
730 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
731 if ( !VOS_IS_STATUS_SUCCESS( status ) )
732 {
733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
734 "%s:Insert Tx queue failed. Pkt dropped", __func__);
735 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
736 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
737 ++pAdapter->stats.tx_dropped;
738 kfree_skb(skb);
739 return NETDEV_TX_OK;
740 }
741
742 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
743 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
744 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
745
746 if (1 == pktListSize)
747 {
748 //Let TL know we have a packet to send for this AC
749 status = WLANTL_STAPktPending( pHddCtx->pvosContext, STAId, ac );
750
751 if ( !VOS_IS_STATUS_SUCCESS( status ) )
752 {
753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
754 "%s: Failed to signal TL for AC=%d STAId =%d",
755 __func__, ac, STAId );
756
757 /* Remove the packet from queue. It must be at the back of the queue, as TX thread
758 * cannot preempt us in the middle as we are in a soft irq context.
759 * Also it must be the same packet that we just allocated.
760 */
761 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
762 status = hdd_list_remove_back( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &anchor);
763 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
764 /* Free the skb only if we are able to remove it from the list.
765 * If we are not able to retrieve it from the list it means that
766 * the skb was pulled by TX Thread and is use so we should not free
767 * it here
768 */
769 if (VOS_IS_STATUS_SUCCESS(status))
770 {
771 pktNode = list_entry(anchor, skb_list_node_t, anchor);
772 skb1 = pktNode->skb;
773 kfree_skb(skb1);
774 }
775 ++pAdapter->stats.tx_dropped;
776 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
777 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
778 return NETDEV_TX_OK;
779 }
780 }
781
782 dev->trans_start = jiffies;
783
784 return NETDEV_TX_OK;
785 }
786
787/**============================================================================
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530788 @brief hdd_hard_start_xmit() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -0700789 transmitting packets. There are 2 versions of this function. One that uses
790 locked queue and other that uses lockless queues. Both have been retained to
791 do some performance testing
792
793 @param skb : [in] pointer to OS packet (sk_buff)
794 @param dev : [in] pointer to Libra network device
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530795
Jeff Johnson295189b2012-06-20 16:38:30 -0700796 @return : NET_XMIT_DROP if packets are dropped
797 : NET_XMIT_SUCCESS if packet is enqueued succesfully
798 ===========================================================================*/
799int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
800{
801 VOS_STATUS status;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530802 WLANTL_ACEnumType qid, ac;
Jeff Johnson295189b2012-06-20 16:38:30 -0700803 sme_QosWmmUpType up;
804 skb_list_node_t *pktNode = NULL;
805 hdd_list_node_t *anchor = NULL;
806 v_SIZE_t pktListSize = 0;
807 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
808 v_BOOL_t granted;
Shailender Karmuchia734f332013-04-19 14:02:48 -0700809 v_U8_t STAId = WLAN_MAX_STA_COUNT;
Jeff Johnson295189b2012-06-20 16:38:30 -0700810 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Dino Mycled9b7cc12014-09-04 18:43:07 +0530811 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700812 v_BOOL_t txSuspended = VOS_FALSE;
Mihir Shetef8f74532014-12-04 11:53:34 +0530813 struct sk_buff *skb1;
Jeff Johnson295189b2012-06-20 16:38:30 -0700814
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530815 if (NULL == pHddCtx) {
816 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
817 "%s HDD context is NULL", __func__);
818 return NETDEV_TX_BUSY;
819 }
820
Jeff Johnson295189b2012-06-20 16:38:30 -0700821 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
822
Ravi Joshif9520d62013-10-18 04:11:46 -0700823 if (unlikely(netif_subqueue_stopped(dev, skb))) {
c_hpothu32490782014-03-14 19:14:34 +0530824 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshif9520d62013-10-18 04:11:46 -0700825 "%s is called when netif TX %d is disabled",
826 __func__, skb->queue_mapping);
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530827 return NETDEV_TX_BUSY;
828 }
829
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530830 //Get TL Q index corresponding to Qdisc queue index/AC.
831 qid = hdd_QdiscAcToTlAC[skb->queue_mapping];
832 ac = qid;
833
834 if (qid == WLANTL_AC_HIGH_PRIO)
835 {
836 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
837 "%s It must be a Eapol/Wapi/DHCP packet device_mode:%d",
838 __func__, pAdapter->device_mode);
839 ac = hddWmmUpToAcMap[skb->priority];
840 }
Ravi Joshicc57ed42013-10-12 16:31:25 -0700841
c_hpothu851d9862015-01-19 18:39:06 +0530842 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
843 {
844 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
845 FL("Tx frame in not associated state in %d context"),
846 pAdapter->device_mode);
847 ++pAdapter->stats.tx_dropped;
848 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530849 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
c_hpothu851d9862015-01-19 18:39:06 +0530850 kfree_skb(skb);
851 return NETDEV_TX_OK;
852 }
Shailender Karmuchia734f332013-04-19 14:02:48 -0700853 STAId = pHddStaCtx->conn_info.staId[0];
Jeff Johnson295189b2012-06-20 16:38:30 -0700854
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530855 //user priority from IP header, which is already extracted and set from
Jeff Johnson295189b2012-06-20 16:38:30 -0700856 //select_queue call back function
857 up = skb->priority;
858
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530859 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -0700860
861#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +0530862 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700863 "%s: Classified as ac %d up %d", __func__, ac, up);
Jeff Johnson295189b2012-06-20 16:38:30 -0700864#endif // HDD_WMM_DEBUG
865
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530866 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
Mukul Sharma84f27252014-07-14 18:11:42 +0530867 {
Girish Gowlibf0e1ab2015-01-19 16:05:16 +0530868 vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
Mukul Sharma84f27252014-07-14 18:11:42 +0530869 }
Mukul Sharma84f27252014-07-14 18:11:42 +0530870
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530871 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700872 /*CR 463598,384996*/
873 /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
874 *We check for +1 in the logic,to take care of Zero count which
875 *occurs very frequently in low traffic cases */
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530876 if((pAdapter->wmm_tx_queue[qid].count + 1) % 10 == 0)
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700877 {
Shailender Karmuchia734f332013-04-19 14:02:48 -0700878 /* 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 -0700879 * 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 +0530880 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 -0700881
Ravi Joshi8a934352013-09-25 16:46:58 -0700882 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530883 STAId, qid
Ravi Joshi8a934352013-09-25 16:46:58 -0700884 );
885 if ( !VOS_IS_STATUS_SUCCESS( status ) )
886 {
c_hpothu32490782014-03-14 19:14:34 +0530887 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshi8a934352013-09-25 16:46:58 -0700888 "%s: WLANTL_STAPktPending() returned error code %d",
889 __func__, status);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700890 ++pAdapter->stats.tx_dropped;
891 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530892 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Ravi Joshi8a934352013-09-25 16:46:58 -0700893 kfree_skb(skb);
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530894 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Ravi Joshi8a934352013-09-25 16:46:58 -0700895 return NETDEV_TX_OK;
896 }
Varun Reddy Yeturu5ba69222013-04-01 18:22:20 -0700897 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700898 //If we have already reached the max queue size, disable the TX queue
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530899 if ( pAdapter->wmm_tx_queue[qid].count == pAdapter->wmm_tx_queue[qid].max_size)
Jeff Johnson295189b2012-06-20 16:38:30 -0700900 {
Ravi Joshicc57ed42013-10-12 16:31:25 -0700901 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530902 ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[qid];
903 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for QId %d"), qid);
Ravi Joshicc57ed42013-10-12 16:31:25 -0700904 netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530905 pAdapter->isTxSuspended[qid] = VOS_TRUE;
Ravi Joshicc57ed42013-10-12 16:31:25 -0700906 txSuspended = VOS_TRUE;
Mihir Shete5d148f12014-12-16 17:54:49 +0530907 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_NETDEV,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530908 pAdapter->sessionId, qid));
Jeff Johnson295189b2012-06-20 16:38:30 -0700909 }
910
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530911 /* If 3/4th of the max queue size is used then enable the flag.
912 * This flag indicates to place the DHCP packets in VOICE AC queue.*/
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530913 if (WLANTL_AC_BE == qid)
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530914 {
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530915 if (pAdapter->wmm_tx_queue[qid].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530916 {
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +0530917 pAdapter->isVosLowResource = VOS_TRUE;
918 }
919 else
920 {
921 pAdapter->isVosLowResource = VOS_FALSE;
922 }
923 }
924
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530925 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Dino Mycled9b7cc12014-09-04 18:43:07 +0530926
Sachin Ahuja8c65f382014-12-12 15:34:21 +0530927 if (( NULL != pHddCtx ) &&
928 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +0530929 {
930 hdd_dump_dhcp_pkt(skb, TX_PATH);
931 }
932
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 if (VOS_TRUE == txSuspended)
934 {
c_hpothu32490782014-03-14 19:14:34 +0530935 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530936 "%s: TX queue full for QId=%d Disable OS TX queue",
937 __func__, qid );
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530938 return NETDEV_TX_BUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700939 }
940
941 //Use the skb->cb field to hold the list node information
942 pktNode = (skb_list_node_t *)&skb->cb;
943
944 //Stick the OS packet inside this node.
945 pktNode->skb = skb;
946
Madan Mohan Koyyalamudi0dab1ad2013-08-28 16:19:18 +0530947 //Stick the User Priority inside this node
Jeff Johnson295189b2012-06-20 16:38:30 -0700948 pktNode->userPriority = up;
949
950
951 INIT_LIST_HEAD(&pktNode->anchor);
952
953 //Insert the OS packet into the appropriate AC queue
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530954 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
955 status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[qid], &pktNode->anchor, &pktListSize );
956 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700957
958 if ( !VOS_IS_STATUS_SUCCESS( status ) )
959 {
c_hpothu32490782014-03-14 19:14:34 +0530960 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 -0700961 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530962 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -0700963 ++pAdapter->stats.tx_dropped;
964 kfree_skb(skb);
965 return NETDEV_TX_OK;
966 }
967
968 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530969 ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[qid];
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700970 ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -0700971
Kiet Lamf040f472013-11-20 21:15:23 +0530972 if (HDD_PSB_CHANGED == pAdapter->psbChanged)
973 {
974 /* Function which will determine acquire admittance for a
975 * WMM AC is required or not based on psb configuration done
976 * in the framework
977 */
978 hdd_wmm_acquire_access_required(pAdapter, ac);
979 }
980
Jeff Johnson295189b2012-06-20 16:38:30 -0700981 //Make sure we have access to this access category
Kiet Lamf040f472013-11-20 21:15:23 +0530982 if (((pAdapter->psbChanged & (1 << ac)) && likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) ||
983 (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700984 {
985 granted = VOS_TRUE;
986 }
987 else
988 {
989 status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
Kiet Lamf040f472013-11-20 21:15:23 +0530990 pAdapter->psbChanged |= (1 << ac);
Jeff Johnson295189b2012-06-20 16:38:30 -0700991 }
Nirav Shah4f765af2015-01-21 19:51:30 +0530992
993 if ( (granted && ( pktListSize == 1 )) ||
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +0530994 (qid == WLANTL_AC_HIGH_PRIO))
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 {
996 //Let TL know we have a packet to send for this AC
c_hpothu32490782014-03-14 19:14:34 +0530997 //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
Shailender Karmuchia734f332013-04-19 14:02:48 -0700998 status = WLANTL_STAPktPending(
999 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301000 STAId, qid );
Jeff Johnson295189b2012-06-20 16:38:30 -07001001 if ( !VOS_IS_STATUS_SUCCESS( status ) )
1002 {
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301003 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
1004 "%s: Failed to signal TL for QId=%d", __func__, qid );
Jeff Johnson295189b2012-06-20 16:38:30 -07001005
1006 //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
1007 //as we are in a soft irq context. Also it must be the same packet that we just allocated.
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301008 spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
1009 status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[qid], &anchor );
1010 spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
Mihir Shetef8f74532014-12-04 11:53:34 +05301011 /* Free the skb only if we are able to remove it from the list.
1012 * If we are not able to retrieve it from the list it means that
1013 * the skb was pulled by TX Thread and is use so we should not free
1014 * it here
1015 */
1016 if (VOS_IS_STATUS_SUCCESS(status))
1017 {
1018 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1019 skb1 = pktNode->skb;
1020 kfree_skb(skb1);
1021 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001022 ++pAdapter->stats.tx_dropped;
1023 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301024 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
Jeff Johnson295189b2012-06-20 16:38:30 -07001025 return NETDEV_TX_OK;
1026 }
1027 }
1028
1029 dev->trans_start = jiffies;
1030
1031 return NETDEV_TX_OK;
1032}
1033
1034/**============================================================================
Shailender Karmuchia734f332013-04-19 14:02:48 -07001035 @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address
1036
1037 @param pHddStaCtx : [in] pointer to HDD Station Context
1038 pMacAddress [in] pointer to Peer Mac address
1039 staID [out] pointer to Station Index
1040 @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE
1041 ===========================================================================*/
1042
1043VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId)
1044{
1045 v_U8_t idx;
1046
1047 for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
1048 {
1049 if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ],
1050 pMacAddress, sizeof(v_MACADDR_t)))
1051 {
1052 *staId = pHddStaCtx->conn_info.staId[idx];
1053 return VOS_STATUS_SUCCESS;
1054 }
1055 }
1056
1057 return VOS_STATUS_E_FAILURE;
1058}
1059
1060/**============================================================================
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301061 @brief __hdd_tx_timeout() - Function handles timeout during transmission.
Jeff Johnson295189b2012-06-20 16:38:30 -07001062
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301063 @param dev : [in] pointer to network device
Jeff Johnson295189b2012-06-20 16:38:30 -07001064 @return : None
1065 ===========================================================================*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301066void __hdd_tx_timeout(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001067{
Ravi Joshicc57ed42013-10-12 16:31:25 -07001068 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mihir Shete0be28772015-02-17 18:42:14 +05301069 hdd_context_t *pHddCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001070 struct netdev_queue *txq;
Mihir Shete0be28772015-02-17 18:42:14 +05301071 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001072 int i = 0;
Mukul Sharma4b322632015-02-28 20:21:43 +05301073 int status = 0;
Mukul Sharma42b3d432014-10-16 16:13:40 +05301074 v_ULONG_t diff_in_jiffies = 0;
Ravi Joshicc57ed42013-10-12 16:31:25 -07001075
Mihir Shetef3473692014-06-27 15:13:20 +05301076 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301077 "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu",
1078 __func__,jiffies,dev->trans_start);
Mihir Shetef3473692014-06-27 15:13:20 +05301079
c_hpothub8245442013-11-20 23:41:09 +05301080 if ( NULL == pAdapter )
1081 {
c_hpothu32490782014-03-14 19:14:34 +05301082 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301083 FL("pAdapter is NULL"));
1084 VOS_ASSERT(0);
1085 return;
1086 }
1087
Mihir Shete0be28772015-02-17 18:42:14 +05301088 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Mukul Sharma4b322632015-02-28 20:21:43 +05301089 status = wlan_hdd_validate_context(pHddCtx);
1090 if (status !=0 )
Mihir Shete0be28772015-02-17 18:42:14 +05301091 {
Mukul Sharma4b322632015-02-28 20:21:43 +05301092 return;
Mihir Shete0be28772015-02-17 18:42:14 +05301093 }
1094
Mihir Shetef3473692014-06-27 15:13:20 +05301095 ++pAdapter->hdd_stats.hddTxRxStats.txTimeoutCount;
1096
Jeff Johnson295189b2012-06-20 16:38:30 -07001097 //Getting here implies we disabled the TX queues for too long. Queues are
1098 //disabled either because of disassociation or low resource scenarios. In
1099 //case of disassociation it is ok to ignore this. But if associated, we have
1100 //do possible recovery here
Ravi Joshicc57ed42013-10-12 16:31:25 -07001101
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301102 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001103 "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d",
1104 pAdapter->wmm_tx_queue[0].count,
1105 pAdapter->wmm_tx_queue[1].count,
1106 pAdapter->wmm_tx_queue[2].count,
1107 pAdapter->wmm_tx_queue[3].count);
1108
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301109 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001110 "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d",
1111 pAdapter->isTxSuspended[0],
1112 pAdapter->isTxSuspended[1],
1113 pAdapter->isTxSuspended[2],
1114 pAdapter->isTxSuspended[3]);
1115
Mihir Shete0be28772015-02-17 18:42:14 +05301116 for (i = 0; i < dev->num_tx_queues; i++)
Ravi Joshicc57ed42013-10-12 16:31:25 -07001117 {
1118 txq = netdev_get_tx_queue(dev, i);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301119 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Padma, Santhosh Kumarce7aef82014-12-17 17:31:49 +05301120 "Queue%d status: %d txq->trans_start %lu",
1121 i, netif_tx_queue_stopped(txq),txq->trans_start);
Ravi Joshicc57ed42013-10-12 16:31:25 -07001122 }
1123
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301124 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Ravi Joshicc57ed42013-10-12 16:31:25 -07001125 "carrier state: %d", netif_carrier_ok(dev));
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301126
Mihir Shetef3473692014-06-27 15:13:20 +05301127 /* continuousTxTimeoutCount will be reset whenever TL fetches packet
1128 * from HDD
1129 */
1130 ++pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount;
1131
Mukul Sharma42b3d432014-10-16 16:13:40 +05301132 diff_in_jiffies = jiffies - pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut;
1133 if((pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount > 1)&&
1134 ((diff_in_jiffies) > (HDD_TX_TIMEOUT * 2 ))
1135 )
1136 {
1137 /*
1138 * In Open security case when there is no traffic is running, it may possible
1139 * tx time-out may once happen and later we recovered then we need to
1140 * reset the continuousTxTimeoutCount because it is only getting modified
1141 * when traffic is running. So if over a period of time if this count reaches
1142 * to HDD_TX_STALL_SSR_THRESHOLD then host is triggering false subsystem restart.
1143 * so in genuine Tx Time out case kernel will call the tx time-out back to back at
1144 * interval of HDD_TX_TIMEOUT.So now we are checking if previous TX TIME out was
1145 * occurred more then twice of HDD_TX_TIMEOUT back then we may recovered here.
1146 */
1147 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1148 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1149 FL("This is false alarm so resetting the continuousTxTimeoutCount"));
1150 }
1151
1152 //update last jiffies after the check
1153 pAdapter->hdd_stats.hddTxRxStats.jiffiesLastTxTimeOut = jiffies;
1154
Karthick S79bbe822015-07-14 15:28:08 +05301155 if (WLANTL_IsEAPOLPending(pHddCtx->pvosContext) == VOS_STATUS_SUCCESS) {
1156 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1157 goto print_log;
1158 }
Mihir Shete327c2ab2014-11-13 15:17:02 +05301159 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount ==
1160 HDD_TX_STALL_RECOVERY_THRESHOLD)
1161 {
1162 VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
1163 "%s: Request firmware for recovery",__func__);
1164 WLANTL_TLDebugMessage(WLANTL_DEBUG_FW_CLEANUP);
1165 }
1166
Mihir Shete0be28772015-02-17 18:42:14 +05301167 pRemainChanCtx = hdd_get_remain_on_channel_ctx(pHddCtx);
1168 if (!pRemainChanCtx)
Mihir Shetef3473692014-06-27 15:13:20 +05301169 {
Mihir Shete0be28772015-02-17 18:42:14 +05301170 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1171 HDD_TX_STALL_SSR_THRESHOLD)
1172 {
1173 // Driver could not recover, issue SSR
1174 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1175 "%s: Cannot recover from Data stall Issue SSR",
1176 __func__);
1177 WLANTL_FatalError();
1178 return;
1179 }
1180 }
1181 else
1182 {
1183 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1184 "Remain on channel in progress");
1185 /* The supplicant can retry "P2P Invitation Request" for 120 times
1186 * and so there is a possbility that we can remain off channel for
1187 * the entire duration of these retries(which can be max 60sec).
1188 * If we encounter such a case, let us not trigger SSR after 30sec
1189 * but wait for 60sec to let the device go on home channel and start
1190 * tx. If tx does not start within 70sec we will issue SSR.
1191 */
1192 if (pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount >
1193 HDD_TX_STALL_SSR_THRESHOLD_HIGH)
1194 {
1195 // Driver could not recover, issue SSR
1196 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1197 "%s: Cannot recover from Data stall Issue SSR",
1198 __func__);
1199 WLANTL_FatalError();
1200 return;
1201 }
Mihir Shetef3473692014-06-27 15:13:20 +05301202 }
1203
Karthick S79bbe822015-07-14 15:28:08 +05301204print_log:
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301205 /* If Tx stalled for a long time then *hdd_tx_timeout* is called
1206 * every 5sec. The TL debug spits out a lot of information on the
1207 * serial console, if it is called every time *hdd_tx_timeout* is
1208 * called then we may get a watchdog bite on the Application
1209 * processor, so ratelimit the TL debug logs.
1210 */
1211 if (__ratelimit(&hdd_tx_timeout_rs))
1212 {
1213 hdd_wmm_tx_snapshot(pAdapter);
Mihir Shete327c2ab2014-11-13 15:17:02 +05301214 WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301215 }
Mihir Shetef3473692014-06-27 15:13:20 +05301216
Mihir Shetec8fe71b2014-06-16 15:32:59 +05301217}
Jeff Johnson295189b2012-06-20 16:38:30 -07001218
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05301219/**============================================================================
1220 @brief hdd_tx_timeout() - Function called by OS if there is any
1221 timeout during transmission. Since HDD simply enqueues packet
1222 and returns control to OS right away, this would never be invoked
1223
1224 @param dev : [in] pointer to network device
1225 @return : None
1226 ===========================================================================*/
1227void hdd_tx_timeout(struct net_device *dev)
1228{
1229 vos_ssr_protect(__func__);
1230 __hdd_tx_timeout(dev);
1231 vos_ssr_unprotect(__func__);
1232}
Jeff Johnson295189b2012-06-20 16:38:30 -07001233
1234/**============================================================================
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301235 @brief __hdd_stats() - Function registered with the Linux OS for
Jeff Johnson295189b2012-06-20 16:38:30 -07001236 device TX/RX statistic
1237
1238 @param dev : [in] pointer to Libra network device
1239
1240 @return : pointer to net_device_stats structure
1241 ===========================================================================*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301242struct net_device_stats* __hdd_stats(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07001243{
1244 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
c_hpothub8245442013-11-20 23:41:09 +05301245
1246 if ( NULL == pAdapter )
1247 {
c_hpothu32490782014-03-14 19:14:34 +05301248 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301249 FL("pAdapter is NULL"));
1250 VOS_ASSERT(0);
1251 return NULL;
1252 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001253
1254 return &pAdapter->stats;
1255}
1256
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05301257struct net_device_stats* hdd_stats(struct net_device *dev)
1258{
1259 struct net_device_stats* dev_stats;
1260
1261 vos_ssr_protect(__func__);
1262 dev_stats = __hdd_stats(dev);
1263 vos_ssr_unprotect(__func__);
1264
1265 return dev_stats;
1266}
Jeff Johnson295189b2012-06-20 16:38:30 -07001267
1268/**============================================================================
Katya Nigam1fd24402015-02-16 14:52:19 +05301269 @brief hdd_ibss_init_tx_rx() - Init function to initialize Tx/RX
1270 modules in HDD
1271
1272 @param pAdapter : [in] pointer to adapter context
1273 @return : VOS_STATUS_E_FAILURE if any errors encountered
1274 : VOS_STATUS_SUCCESS otherwise
1275 ===========================================================================*/
1276void hdd_ibss_init_tx_rx( hdd_adapter_t *pAdapter )
1277{
1278 v_U8_t i;
1279 v_U8_t STAId = 0;
1280 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1281 hdd_ibss_peer_info_t *pPeerInfo = &pHddStaCtx->ibss_peer_info;
1282 v_U8_t pACWeights[] = {
1283 HDD_SOFTAP_BK_WEIGHT_DEFAULT,
1284 HDD_SOFTAP_BE_WEIGHT_DEFAULT,
1285 HDD_SOFTAP_VI_WEIGHT_DEFAULT,
1286 HDD_SOFTAP_VO_WEIGHT_DEFAULT
1287 };
1288
1289 pAdapter->isVosOutOfResource = VOS_FALSE;
1290 pAdapter->isVosLowResource = VOS_FALSE;
1291
1292 // Since SAP model is used for IBSS also. Using same queue length as in SAP.
1293 pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN;
1294 pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN;
1295 pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN;
1296 pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN;
1297
1298 for (STAId = 0; STAId < HDD_MAX_NUM_IBSS_STA; STAId++)
1299 {
1300 vos_mem_zero(&pPeerInfo->ibssStaInfo[STAId], sizeof(hdd_ibss_station_info_t));
1301 for (i = 0; i < NUM_TX_QUEUES; i ++)
1302 {
1303 hdd_list_init(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1304 }
1305 }
1306
1307 /* Update the AC weights suitable for SoftAP mode of operation */
1308 WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights);
1309}
1310
1311/**============================================================================
1312 @brief hdd_ibss_deinit_tx_rx() - Deinit function to clean up Tx/RX
1313 modules in HDD
1314
1315 @param pAdapter : [in] pointer to adapter context..
1316 @return : VOS_STATUS_E_FAILURE if any errors encountered.
1317 : VOS_STATUS_SUCCESS otherwise
1318 ===========================================================================*/
1319VOS_STATUS hdd_ibss_deinit_tx_rx( hdd_adapter_t *pAdapter )
1320{
1321 VOS_STATUS status = VOS_STATUS_SUCCESS;
1322 v_U8_t STAId = 0;
1323 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1324 hdd_ibss_peer_info_t * pPeerInfo = &pHddStaCtx->ibss_peer_info;
1325 hdd_list_node_t *anchor = NULL;
1326 skb_list_node_t *pktNode = NULL;
1327 struct sk_buff *skb = NULL;
1328 v_SINT_t i = -1;
1329
1330 for (STAId = 0; STAId < HDD_MAX_NUM_IBSS_STA; STAId++)
1331 {
1332 if (VOS_FALSE == pPeerInfo->ibssStaInfo[STAId].isUsed)
1333 {
1334 continue;
1335 }
1336 for (i = 0; i < NUM_TX_QUEUES; i ++)
1337 {
1338 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
1339 while (true)
1340 {
1341 status = hdd_list_remove_front ( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i], &anchor);
1342
1343 if (VOS_STATUS_E_EMPTY != status)
1344 {
1345 //If success then we got a valid packet from some AC
1346 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1347 skb = pktNode->skb;
1348 ++pAdapter->stats.tx_dropped;
1349 ++pAdapter->hdd_stats.hddTxRxStats.txFlushed;
1350 ++pAdapter->hdd_stats.hddTxRxStats.txFlushedAC[i];
1351 kfree_skb(skb);
1352 continue;
1353 }
1354
1355 //current list is empty
1356 break;
1357 }
1358 pPeerInfo->ibssStaInfo[STAId].txSuspended[i] = VOS_FALSE;
1359 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[i].lock);
1360 }
1361 }
1362 pAdapter->isVosLowResource = VOS_FALSE;
1363
1364 return status;
1365}
1366
1367/**============================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -07001368 @brief hdd_init_tx_rx() - Init function to initialize Tx/RX
1369 modules in HDD
1370
1371 @param pAdapter : [in] pointer to adapter context
1372 @return : VOS_STATUS_E_FAILURE if any errors encountered
1373 : VOS_STATUS_SUCCESS otherwise
1374 ===========================================================================*/
1375VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter )
1376{
1377 VOS_STATUS status = VOS_STATUS_SUCCESS;
1378 v_SINT_t i = -1;
1379
c_hpothub8245442013-11-20 23:41:09 +05301380 if ( NULL == pAdapter )
1381 {
c_hpothu32490782014-03-14 19:14:34 +05301382 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301383 FL("pAdapter is NULL"));
1384 VOS_ASSERT(0);
1385 return VOS_STATUS_E_FAILURE;
1386 }
1387
Jeff Johnson295189b2012-06-20 16:38:30 -07001388 pAdapter->isVosOutOfResource = VOS_FALSE;
Madan Mohan Koyyalamudifd3b7a92013-10-10 15:02:58 +05301389 pAdapter->isVosLowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001390
1391 //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
1392 //Will be zeroed out during alloc
1393
1394 while (++i != NUM_TX_QUEUES)
1395 {
1396 pAdapter->isTxSuspended[i] = VOS_FALSE;
1397 hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN);
1398 }
1399
1400 return status;
1401}
1402
1403
1404/**============================================================================
1405 @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX
1406 modules in HDD
1407
1408 @param pAdapter : [in] pointer to adapter context
1409 @return : VOS_STATUS_E_FAILURE if any errors encountered
1410 : VOS_STATUS_SUCCESS otherwise
1411 ===========================================================================*/
1412VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter )
1413{
1414 VOS_STATUS status = VOS_STATUS_SUCCESS;
1415 v_SINT_t i = -1;
1416
c_hpothub8245442013-11-20 23:41:09 +05301417 if ( NULL == pAdapter )
1418 {
c_hpothu32490782014-03-14 19:14:34 +05301419 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
c_hpothub8245442013-11-20 23:41:09 +05301420 FL("pAdapter is NULL"));
1421 VOS_ASSERT(0);
1422 return VOS_STATUS_E_FAILURE;
1423 }
1424
Jeff Johnson295189b2012-06-20 16:38:30 -07001425 status = hdd_flush_tx_queues(pAdapter);
c_hpothub8245442013-11-20 23:41:09 +05301426 if (VOS_STATUS_SUCCESS != status)
c_hpothu32490782014-03-14 19:14:34 +05301427 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
c_hpothub8245442013-11-20 23:41:09 +05301428 FL("failed to flush tx queues"));
1429
Jeff Johnson295189b2012-06-20 16:38:30 -07001430 while (++i != NUM_TX_QUEUES)
1431 {
1432 //Free up actual list elements in the Tx queue
1433 hdd_list_destroy( &pAdapter->wmm_tx_queue[i] );
1434 }
1435
1436 return status;
1437}
1438
1439
1440/**============================================================================
1441 @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX
1442 modules in HDD
1443
1444 @param pAdapter : [in] pointer to adapter context
1445 @return : VOS_STATUS_E_FAILURE if any errors encountered
1446 : VOS_STATUS_SUCCESS otherwise
1447 ===========================================================================*/
1448VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter )
1449{
1450 return hdd_flush_tx_queues(pAdapter);
1451}
1452
1453
1454/**============================================================================
1455 @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not.
1456
1457 @param pVosPacket : [in] pointer to vos packet
1458 @return : VOS_TRUE if the packet is EAPOL
1459 : VOS_FALSE otherwise
1460 ===========================================================================*/
1461
1462v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket )
1463{
1464 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1465 v_BOOL_t fEAPOL = VOS_FALSE;
1466 void *pBuffer = NULL;
1467
1468
1469 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1470 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
Abhishek Singhfa011222014-04-14 10:57:08 +05301471 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301473 if ( pBuffer && *(unsigned short*)pBuffer ==
1474 vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001475 {
1476 fEAPOL = VOS_TRUE;
1477 }
1478 }
1479
1480 return fEAPOL;
1481}
1482
Abhishek Singhfa011222014-04-14 10:57:08 +05301483/**============================================================================
1484 @brief hdd_IsARP() - Checks the packet is ARP or not.
1485
1486 @param pVosPacket : [in] pointer to vos packet
1487 @return : VOS_TRUE if the packet is ARP
1488 : VOS_FALSE otherwise
1489 ===========================================================================*/
1490
1491v_BOOL_t hdd_IsARP( vos_pkt_t *pVosPacket )
1492{
1493 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1494 v_BOOL_t fIsARP = VOS_FALSE;
1495 void *pBuffer = NULL;
1496
1497
1498 vosStatus = vos_pkt_peek_data( pVosPacket,
1499 (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1500 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1501 if ( VOS_IS_STATUS_SUCCESS( vosStatus ) )
1502 {
1503 if ( pBuffer && *(unsigned short*)pBuffer ==
1504 vos_cpu_to_be16(HDD_ETHERTYPE_ARP) )
1505 {
1506 fIsARP = VOS_TRUE;
1507 }
1508 }
1509
1510 return fIsARP;
1511}
Jeff Johnson295189b2012-06-20 16:38:30 -07001512
1513#ifdef FEATURE_WLAN_WAPI // Need to update this function
1514/**============================================================================
1515 @brief hdd_IsWAIPacket() - Checks the packet is WAI or not.
1516
1517 @param pVosPacket : [in] pointer to vos packet
1518 @return : VOS_TRUE if the packet is WAI
1519 : VOS_FALSE otherwise
1520 ===========================================================================*/
1521
1522v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket )
1523{
1524 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1525 v_BOOL_t fIsWAI = VOS_FALSE;
1526 void *pBuffer = NULL;
1527
1528 // Need to update this function
1529 vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET,
1530 &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE );
1531
1532 if (VOS_IS_STATUS_SUCCESS( vosStatus ) )
1533 {
Abhishek Singhfa011222014-04-14 10:57:08 +05301534 if ( pBuffer && *(unsigned short*)pBuffer ==
1535 vos_cpu_to_be16(HDD_ETHERTYPE_WAI) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001536 {
1537 fIsWAI = VOS_TRUE;
1538 }
1539 }
1540
1541 return fIsWAI;
1542}
1543#endif /* FEATURE_WLAN_WAPI */
1544
1545/**============================================================================
1546 @brief hdd_tx_complete_cbk() - Callback function invoked by TL
1547 to indicate that a packet has been transmitted across the SDIO bus
1548 succesfully. OS packet resources can be released after this cbk.
1549
1550 @param vosContext : [in] pointer to VOS context
1551 @param pVosPacket : [in] pointer to VOS packet (containing skb)
1552 @param vosStatusIn : [in] status of the transmission
1553
1554 @return : VOS_STATUS_E_FAILURE if any errors encountered
1555 : VOS_STATUS_SUCCESS otherwise
1556 ===========================================================================*/
1557VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext,
1558 vos_pkt_t *pVosPacket,
1559 VOS_STATUS vosStatusIn )
1560{
1561 VOS_STATUS status = VOS_STATUS_SUCCESS;
1562 hdd_adapter_t *pAdapter = NULL;
1563 hdd_context_t *pHddCtx = NULL;
1564 void* pOsPkt = NULL;
1565
1566 if( ( NULL == vosContext ) || ( NULL == pVosPacket ) )
1567 {
c_hpothu32490782014-03-14 19:14:34 +05301568 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301569 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001570 return VOS_STATUS_E_FAILURE;
1571 }
1572
1573 //Return the skb to the OS
1574 status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301575 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001576 {
1577 //This is bad but still try to free the VOSS resources if we can
c_hpothu32490782014-03-14 19:14:34 +05301578 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301579 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001580 vos_pkt_return_packet( pVosPacket );
1581 return VOS_STATUS_E_FAILURE;
1582 }
1583
1584 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001585 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001586 //Get the Adapter context.
1587 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301588 if (pAdapter == NULL || WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301590 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1591 "%s: Invalid adapter %p", __func__, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 }
1593 else
1594 {
1595 ++pAdapter->hdd_stats.hddTxRxStats.txCompleted;
1596 }
1597
1598 kfree_skb((struct sk_buff *)pOsPkt);
1599
1600 //Return the VOS packet resources.
1601 status = vos_pkt_return_packet( pVosPacket );
Agarwal Ashish971c2882013-10-30 20:11:12 +05301602 if (!VOS_IS_STATUS_SUCCESS( status ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001603 {
c_hpothu32490782014-03-14 19:14:34 +05301604 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301605 "%s: Could not return VOS packet to the pool", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001606 }
1607
1608 return status;
1609}
1610
Katya Nigamf944e5e2015-02-10 15:05:43 +05301611/**============================================================================
1612 @brief hdd_ibss_tx_fetch_packet_cbk() - Callback function invoked by TL to
1613 fetch a packet for transmission.
1614
1615 @param vosContext : [in] pointer to VOS context
1616 @param staId : [in] Station for which TL is requesting a pkt
1617 @param ac : [in] access category requested by TL
1618 @param pVosPacket : [out] pointer to VOS packet packet pointer
1619 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1620
1621 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1622 : VOS_STATUS_E_FAILURE if any errors encountered
1623 : VOS_STATUS_SUCCESS otherwise
1624 ===========================================================================*/
1625VOS_STATUS hdd_ibss_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1626 v_U8_t *pStaId,
1627 WLANTL_ACEnumType ac,
1628 vos_pkt_t **ppVosPacket,
1629 WLANTL_MetaInfoType *pPktMetaInfo )
1630{
1631 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1632 hdd_adapter_t *pAdapter = NULL;
1633 hdd_list_node_t *anchor = NULL;
1634 skb_list_node_t *pktNode = NULL;
1635 struct sk_buff *skb = NULL;
1636 vos_pkt_t *pVosPacket = NULL;
1637 v_MACADDR_t* pDestMacAddress = NULL;
1638 v_TIME_t timestamp;
1639 v_SIZE_t size = 0;
1640 v_U8_t STAId = WLAN_MAX_STA_COUNT;
1641 hdd_context_t *pHddCtx = NULL;
1642 hdd_station_ctx_t *pHddStaCtx = NULL;
1643 hdd_ibss_peer_info_t *pPeerInfo = NULL;
1644 v_U8_t proto_type = 0;
Abhishek Singh99f725a2015-05-15 17:50:26 +05301645 v_U16_t packet_size;
Katya Nigamf944e5e2015-02-10 15:05:43 +05301646
1647 //Sanity check on inputs
1648 if ( ( NULL == vosContext ) ||
1649 ( NULL == pStaId ) ||
1650 ( NULL == ppVosPacket ) ||
1651 ( NULL == pPktMetaInfo ) )
1652 {
1653 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1654 "%s: Null Params being passed", __func__);
1655 return VOS_STATUS_E_FAILURE;
1656 }
1657
1658 //Get the HDD context.
1659 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
1660 if ( NULL == pHddCtx )
1661 {
1662 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1663 "%s: HDD adapter context is Null", __func__);
1664 return VOS_STATUS_E_FAILURE;
1665 }
1666
1667 STAId = *pStaId;
1668 pAdapter = pHddCtx->sta_to_adapter[STAId];
1669 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1670 {
1671 VOS_ASSERT(0);
1672 return VOS_STATUS_E_FAILURE;
1673 }
1674
1675 pHddStaCtx = &pAdapter->sessionCtx.station;
1676 pPeerInfo = &pHddStaCtx->ibss_peer_info;
1677
1678 if (FALSE == pPeerInfo->ibssStaInfo[STAId].isUsed )
1679 {
1680 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1681 "%s: Unregistered STAId %d passed by TL", __func__, STAId);
1682 return VOS_STATUS_E_FAILURE;
1683 }
1684
1685 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1686
1687 *ppVosPacket = NULL;
1688
1689 //Make sure the AC being asked for is sane
1690 if( ac > WLANTL_MAX_AC || ac < 0)
1691 {
1692 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1693 "%s: Invalid AC %d passed by TL", __func__, ac);
1694 return VOS_STATUS_E_FAILURE;
1695 }
1696
1697 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1698
Katya Nigamf944e5e2015-02-10 15:05:43 +05301699 //Get the vos packet before so that we are prepare for VOS low reseurce condition
1700 //This simplifies the locking and unlocking of Tx queue
1701 status = vos_pkt_wrap_data_packet( &pVosPacket,
1702 VOS_PKT_TYPE_TX_802_3_DATA,
1703 NULL, //OS Pkt is not being passed
1704 hdd_tx_low_resource_cbk,
1705 pAdapter );
1706
1707 if ((status == VOS_STATUS_E_ALREADY) || (status == VOS_STATUS_E_RESOURCES))
1708 {
1709 //Remember VOS is in a low resource situation
1710 pAdapter->isVosOutOfResource = VOS_TRUE;
1711 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
1712 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
1713 "%s: VOSS in Low Resource scenario", __func__);
1714 //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty.
1715 return VOS_STATUS_E_FAILURE;
1716 }
1717
1718 /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there.
1719 Do not get next AC as the other branch does.
1720 */
1721 spin_lock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1722 hdd_list_size(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &size);
1723
1724 if (0 == size)
1725 {
1726 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1727 vos_pkt_return_packet(pVosPacket);
1728 return VOS_STATUS_E_EMPTY;
1729 }
1730
1731 status = hdd_list_remove_front( &pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac], &anchor );
1732 spin_unlock_bh(&pPeerInfo->ibssStaInfo[STAId].wmm_tx_queue[ac].lock);
1733
1734 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1735 "%s: AC %d has packets pending", __func__, ac);
1736
1737 if(VOS_STATUS_SUCCESS == status)
1738 {
1739 //If success then we got a valid packet from some AC
1740 pktNode = list_entry(anchor, skb_list_node_t, anchor);
1741 skb = pktNode->skb;
1742 }
1743 else
1744 {
1745 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1746 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1747 "%s: Error in de-queuing skb from Tx queue status = %d",
1748 __func__, status );
1749 vos_pkt_return_packet(pVosPacket);
1750 return VOS_STATUS_E_FAILURE;
1751 }
1752
1753 //Attach skb to VOS packet.
1754 status = vos_pkt_set_os_packet( pVosPacket, skb );
1755 if (status != VOS_STATUS_SUCCESS)
1756 {
1757 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
1758 "%s: Error attaching skb", __func__);
1759 vos_pkt_return_packet(pVosPacket);
1760 ++pAdapter->stats.tx_dropped;
1761 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
1762 kfree_skb(skb);
1763 return VOS_STATUS_E_FAILURE;
1764 }
1765
1766 //Return VOS packet to TL;
1767 *ppVosPacket = pVosPacket;
1768
1769 //Fill out the meta information needed by TL
1770 vos_pkt_get_timestamp( pVosPacket, &timestamp );
1771 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
1772 if ( 1 < size )
1773 {
1774 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
1775 }
1776 else
1777 {
1778 pPktMetaInfo->bMorePackets = 0;
1779 }
1780
1781 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
1782 pPktMetaInfo->ucIsEapol = 0;
1783 else
1784 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
1785
1786 if ((NULL != pHddCtx) &&
1787 (pHddCtx->cfg_ini->gEnableDebugLog))
1788 {
1789 proto_type = vos_pkt_get_proto_type(skb,
1790 pHddCtx->cfg_ini->gEnableDebugLog);
1791 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
1792 {
1793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1794 "IBSS STA TX EAPOL");
1795 }
1796 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
1797 {
1798 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1799 "IBSS STA TX DHCP");
1800 }
Mihir Shete39f7c752015-06-11 15:40:09 +05301801 else if (VOS_PKT_PROTO_TYPE_ARP & proto_type)
1802 {
1803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1804 "IBSS STA TX ARP");
1805 }
Katya Nigamf944e5e2015-02-10 15:05:43 +05301806 }
1807
Abhishek Singh99f725a2015-05-15 17:50:26 +05301808 vos_pkt_get_packet_length( pVosPacket,&packet_size );
1809 if ( HDD_ETHERTYPE_ARP_SIZE == packet_size )
1810 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
1811
Katya Nigamf944e5e2015-02-10 15:05:43 +05301812 pPktMetaInfo->ucUP = pktNode->userPriority;
1813 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
1814 pPktMetaInfo->ucType = 0;
1815
1816 //Extract the destination address from ethernet frame
1817 pDestMacAddress = (v_MACADDR_t*)skb->data;
1818
1819 // we need 802.3 to 802.11 frame translation
1820 // (note that Bcast/Mcast will be translated in SW, unicast in HW)
1821 pPktMetaInfo->ucDisableFrmXtl = 0;
1822 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
1823 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
1824
1825 if ( (pPeerInfo->ibssStaInfo[STAId].txSuspended[ac]) &&
1826 (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) ))
1827 {
1828 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1829 "%s: TX queue re-enabled", __func__);
1830 pPeerInfo->ibssStaInfo[STAId].txSuspended[ac] = VOS_FALSE;
1831 netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb));
1832 }
1833
1834 // We're giving the packet to TL so consider it transmitted from
1835 // a statistics perspective. We account for it here instead of
1836 // when the packet is returned for two reasons. First, TL will
1837 // manipulate the skb to the point where the len field is not
1838 // accurate, leading to inaccurate byte counts if we account for
1839 // it later. Second, TL does not provide any feedback as to
1840 // whether or not the packet was successfully sent over the air,
1841 // so the packet counts will be the same regardless of where we
1842 // account for them
1843 pAdapter->stats.tx_bytes += skb->len;
1844 ++pAdapter->stats.tx_packets;
1845 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
1846 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
1847 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
1848
1849 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
1850 "%s: Valid VOS PKT returned to TL", __func__);
1851
1852 return status;
1853}
Jeff Johnson295189b2012-06-20 16:38:30 -07001854
1855/**============================================================================
1856 @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to
1857 fetch a packet for transmission.
1858
1859 @param vosContext : [in] pointer to VOS context
1860 @param staId : [in] Station for which TL is requesting a pkt
1861 @param ac : [in] access category requested by TL
1862 @param pVosPacket : [out] pointer to VOS packet packet pointer
1863 @param pPktMetaInfo : [out] pointer to meta info for the pkt
1864
1865 @return : VOS_STATUS_E_EMPTY if no packets to transmit
1866 : VOS_STATUS_E_FAILURE if any errors encountered
1867 : VOS_STATUS_SUCCESS otherwise
1868 ===========================================================================*/
1869VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext,
1870 v_U8_t *pStaId,
1871 WLANTL_ACEnumType ac,
1872 vos_pkt_t **ppVosPacket,
1873 WLANTL_MetaInfoType *pPktMetaInfo )
1874{
1875 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1876 hdd_adapter_t *pAdapter = NULL;
1877 hdd_context_t *pHddCtx = NULL;
1878 hdd_list_node_t *anchor = NULL;
1879 skb_list_node_t *pktNode = NULL;
1880 struct sk_buff *skb = NULL;
1881 vos_pkt_t *pVosPacket = NULL;
1882 v_MACADDR_t* pDestMacAddress = NULL;
1883 v_TIME_t timestamp;
1884 WLANTL_ACEnumType newAc;
1885 v_SIZE_t size = 0;
Abhishek Singhfa011222014-04-14 10:57:08 +05301886 v_U16_t packet_size;
Jeff Johnson295189b2012-06-20 16:38:30 -07001887 tANI_U8 acAdmitted, i;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08001888 v_U8_t proto_type = 0;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301889 WLANTL_ACEnumType actualAC;
Jeff Johnson295189b2012-06-20 16:38:30 -07001890
1891 //Sanity check on inputs
1892 if ( ( NULL == vosContext ) ||
1893 ( NULL == pStaId ) ||
1894 ( NULL == ppVosPacket ) ||
1895 ( NULL == pPktMetaInfo ) )
1896 {
c_hpothu32490782014-03-14 19:14:34 +05301897 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301898 "%s: Null Params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001899 return VOS_STATUS_E_FAILURE;
1900 }
1901
1902 //Get the HDD context.
Kiet Lam3c2ee302014-03-23 23:23:22 -07001903 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07001904 if(pHddCtx == NULL)
1905 {
c_hpothu32490782014-03-14 19:14:34 +05301906 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301907 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001908 return VOS_STATUS_E_FAILURE;
1909 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 pAdapter = pHddCtx->sta_to_adapter[*pStaId];
Jeff Johnsonb156c922013-12-05 17:19:46 -08001911 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Jeff Johnson295189b2012-06-20 16:38:30 -07001912 {
c_hpothu32490782014-03-14 19:14:34 +05301913 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05301914 FL("invalid adapter:%p for staId:%u"), pAdapter, *pStaId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001915 VOS_ASSERT(0);
1916 return VOS_STATUS_E_FAILURE;
1917 }
1918
1919 ++pAdapter->hdd_stats.hddTxRxStats.txFetched;
1920
1921 *ppVosPacket = NULL;
1922
1923 //Make sure the AC being asked for is sane
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301924 if (ac > WLANTL_AC_HIGH_PRIO || ac < 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001925 {
c_hpothu32490782014-03-14 19:14:34 +05301926 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301927 "%s: Invalid QId %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001928 return VOS_STATUS_E_FAILURE;
1929 }
1930
1931 ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac];
1932
1933#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301934 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301935 "%s: AC %d passed by TL", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001936#endif // HDD_WMM_DEBUG
1937
Jeff Johnson295189b2012-06-20 16:38:30 -07001938 // do we have any packets pending in this AC?
1939 hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size );
1940 if( size > 0 )
1941 {
1942 // yes, so process it
1943#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301944 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001945 "%s: AC %d has packets pending", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07001946#endif // HDD_WMM_DEBUG
1947 }
1948 else
1949 {
1950 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1951#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05301952 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001953 "%s: no packets pending", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001954#endif // HDD_WMM_DEBUG
1955 return VOS_STATUS_E_FAILURE;
1956 }
1957
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05301958 // Note here that we are not checking "wmmAcAccessAllowed" for packets
1959 // in new queue since there is no one AC associated to the new queue.
1960 // Since there will be either eapol or dhcp pkts in new queue overlooking
1961 // this should be okay from implicit QoS perspective.
1962 if (ac != WLANTL_AC_HIGH_PRIO)
1963 {
1964 // We find an AC with packets
1965 // or we determine we have no more packets to send
1966 // HDD is not allowed to change AC.
1967
1968 // has this AC been admitted? or
1969 // To allow EAPOL packets when not authenticated
1970 if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
1971 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
1972 {
1973 ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
1974#ifdef HDD_WMM_DEBUG
1975 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
1976 "%s: no packets pending", __func__);
1977#endif // HDD_WMM_DEBUG
1978 return VOS_STATUS_E_FAILURE;
1979 }
1980 }
1981
Jeff Johnson295189b2012-06-20 16:38:30 -07001982 //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources
1983 //This simplifies the locking and unlocking of Tx queue
1984 status = vos_pkt_wrap_data_packet( &pVosPacket,
1985 VOS_PKT_TYPE_TX_802_3_DATA,
1986 NULL, //OS Pkt is not being passed
1987 hdd_tx_low_resource_cbk,
1988 pAdapter );
1989
1990 if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES)
1991 {
1992 //Remember VOS is in a low resource situation
1993 pAdapter->isVosOutOfResource = VOS_TRUE;
1994 ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources;
c_hpothu32490782014-03-14 19:14:34 +05301995 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 -07001996 //TL will now think we have no more packets in this AC
1997 return VOS_STATUS_E_FAILURE;
1998 }
1999
2000 //Remove the packet from the queue
2001 spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock);
2002 status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor );
2003 spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock);
2004
2005 if(VOS_STATUS_SUCCESS == status)
2006 {
2007 //If success then we got a valid packet from some AC
2008 pktNode = list_entry(anchor, skb_list_node_t, anchor);
2009 skb = pktNode->skb;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302010 actualAC = hddWmmUpToAcMap[pktNode->userPriority];
2011 if (actualAC >= WLANTL_MAX_AC)
2012 {
2013 /* To fix klocwork */
2014 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
2015 "%s: Invalid AC for packet:%d", __func__, actualAC);
2016 actualAC = WLANTL_AC_BE;
2017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002018 }
2019 else
2020 {
2021 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
c_hpothu32490782014-03-14 19:14:34 +05302022 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing "
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002023 "skb from Tx queue status = %d", __func__, status );
Jeff Johnson295189b2012-06-20 16:38:30 -07002024 vos_pkt_return_packet(pVosPacket);
2025 return VOS_STATUS_E_FAILURE;
2026 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 //Attach skb to VOS packet.
2028 status = vos_pkt_set_os_packet( pVosPacket, skb );
2029 if (status != VOS_STATUS_SUCCESS)
2030 {
c_hpothu32490782014-03-14 19:14:34 +05302031 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002032 vos_pkt_return_packet(pVosPacket);
2033 ++pAdapter->stats.tx_dropped;
2034 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
2035 kfree_skb(skb);
2036 return VOS_STATUS_E_FAILURE;
2037 }
2038
2039 //Just being paranoid. To be removed later
2040 if(pVosPacket == NULL)
2041 {
c_hpothu32490782014-03-14 19:14:34 +05302042 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 -07002043 ++pAdapter->stats.tx_dropped;
2044 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
2045 kfree_skb(skb);
2046 return VOS_STATUS_E_FAILURE;
2047 }
2048
Dino Mycle3b9536d2014-07-09 22:05:24 +05302049#ifdef WLAN_FEATURE_LINK_LAYER_STATS
Srinivas Dasaridab36fe2015-07-21 12:10:56 +05302050 if (vos_is_macaddr_multicast((v_MACADDR_t*)skb->data))
Dino Mycle3b9536d2014-07-09 22:05:24 +05302051 {
Srinivas Dasaridab36fe2015-07-21 12:10:56 +05302052 pAdapter->hdd_stats.hddTxRxStats.txMcast[actualAC]++;
Dino Mycle3b9536d2014-07-09 22:05:24 +05302053 }
2054
2055#endif
2056
Chilam NG571c65a2013-01-19 12:27:36 +05302057#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002058 if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode)
Chilam NG571c65a2013-01-19 12:27:36 +05302059 {
2060 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam NG571c65a2013-01-19 12:27:36 +05302061 u8 mac[6];
2062
Hoonki Lee387663d2013-02-05 18:08:43 -08002063 wlan_hdd_tdls_extract_da(skb, mac);
Chilam NG571c65a2013-01-19 12:27:36 +05302064
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002065 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302066 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05302067 "broadcast packet, not adding to peer list");
2068 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2069 mac, 6) != 0) {
c_hpothu32490782014-03-14 19:14:34 +05302070 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002071 "extract mac: " MAC_ADDRESS_STR,
2072 MAC_ADDR_ARRAY(mac) );
Chilam NG571c65a2013-01-19 12:27:36 +05302073
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002074 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1);
Chilam NG571c65a2013-01-19 12:27:36 +05302075 } else {
c_hpothu32490782014-03-14 19:14:34 +05302076 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam NG571c65a2013-01-19 12:27:36 +05302077 "packet da is bssid, not adding to peer list");
2078 }
2079 }
2080#endif
2081
Jeff Johnson295189b2012-06-20 16:38:30 -07002082 //Return VOS packet to TL;
2083 *ppVosPacket = pVosPacket;
2084
2085 //Fill out the meta information needed by TL
2086 //FIXME This timestamp is really the time stamp of wrap_data_packet
2087 vos_pkt_get_timestamp( pVosPacket, &timestamp );
2088 pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp;
2089
2090 if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE)
2091 pPktMetaInfo->ucIsEapol = 0;
Nirav Shah4f765af2015-01-21 19:51:30 +05302092 else
Jeff Johnson295189b2012-06-20 16:38:30 -07002093 pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0;
2094
Sushant Kaushika8073312015-05-04 17:33:52 +05302095 if (pPktMetaInfo->ucIsEapol)
2096 wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED);
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302097 if ((NULL != pHddCtx) &&
2098 (pHddCtx->cfg_ini->gEnableDebugLog))
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002099 {
2100 proto_type = vos_pkt_get_proto_type(skb,
2101 pHddCtx->cfg_ini->gEnableDebugLog);
2102 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2103 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4b53d4b2015-05-08 05:35:00 -07002105 "STA TX EAPOL");
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002106 }
2107 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2108 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302109 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002110 "STA TX DHCP");
2111 }
Mihir Shete39f7c752015-06-11 15:40:09 +05302112 else if (VOS_PKT_PROTO_TYPE_ARP & proto_type)
2113 {
2114 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2115 "STA TX ARP");
2116 }
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002117 }
2118
Abhishek Singhfa011222014-04-14 10:57:08 +05302119 vos_pkt_get_packet_length( pVosPacket,&packet_size );
2120 if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
2121 pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
2122
Jeff Johnson295189b2012-06-20 16:38:30 -07002123#ifdef FEATURE_WLAN_WAPI
2124 // Override usIsEapol value when its zero for WAPI case
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302125 pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002126#endif /* FEATURE_WLAN_WAPI */
2127
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302128 /* 1. Check if ACM is set for this AC
2129 * 2. If set, check if this AC had already admitted
2130 * 3. If not already admitted, downgrade the UP to next best UP
2131 * 4. Allow only when medium time is non zero when Addts accepted
2132 * else downgrade traffic. we opted downgrading over Delts when
2133 * medium time is zero because while doing downgradig driver is not
2134 * clearing the wmm context so consider in subsequent roaming
2135 * if AP (new or same AP) accept the Addts with valid medium time
2136 * no application support is required where if we have opted
2137 * delts Applications have to again do Addts or STA will never
2138 * go for Addts.
2139 */
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302140 pPktMetaInfo->ac = actualAC;
2141 if(!pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcAccessRequired ||
2142 (pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid &&
2143 pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecInfo.medium_time))
Jeff Johnson295189b2012-06-20 16:38:30 -07002144 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302145 pPktMetaInfo->ucUP = pktNode->userPriority;
2146 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07002147 }
2148 else
2149 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302150 //Downgrade the UP
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302151 acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid;
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302152 newAc = WLANTL_AC_BK;
Kanchanapally, Vidyullathaed969c62015-02-18 11:39:11 +05302153 for (i=actualAC-1; i>0; i--)
Jeff Johnson295189b2012-06-20 16:38:30 -07002154 {
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302155 if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
2156 {
2157 newAc = i;
2158 break;
2159 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002160 }
Agarwal Ashish8b343f12015-01-08 20:06:44 +05302161 pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc];
2162 pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
2163 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,
2164 "Downgrading UP %d to UP %d ",
2165 pktNode->userPriority, pPktMetaInfo->ucUP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002166 }
2167
Girish Gowlibf0e1ab2015-01-19 16:05:16 +05302168 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
2169 {
2170 vos_record_roam_event(e_TL_FIRST_XMIT_TIME, NULL, 0);
2171 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302172
Jeff Johnson295189b2012-06-20 16:38:30 -07002173 pPktMetaInfo->ucType = 0; //FIXME Don't know what this is
2174 pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate
2175 if ( 1 < size )
2176 {
2177 pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send
2178 }
2179 else
2180 {
2181 pPktMetaInfo->bMorePackets = 0;
2182 }
2183
2184 //Extract the destination address from ethernet frame
2185 pDestMacAddress = (v_MACADDR_t*)skb->data;
2186 pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0;
2187 pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0;
2188
2189
2190
2191 // if we are in a backpressure situation see if we can turn the hose back on
2192 if ( (pAdapter->isTxSuspended[ac]) &&
2193 (size <= HDD_TX_QUEUE_LOW_WATER_MARK) )
2194 {
2195 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured;
2196 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac];
c_hpothu32490782014-03-14 19:14:34 +05302197 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002198 "%s: TX queue[%d] re-enabled", __func__, ac);
Jeff Johnson295189b2012-06-20 16:38:30 -07002199 pAdapter->isTxSuspended[ac] = VOS_FALSE;
2200 netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev,
2201 skb_get_queue_mapping(skb) ));
Mihir Shete5d148f12014-12-16 17:54:49 +05302202 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_WAKE_NETDEV,
2203 pAdapter->sessionId, ac));
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 }
2205
2206
2207 // We're giving the packet to TL so consider it transmitted from
2208 // a statistics perspective. We account for it here instead of
2209 // when the packet is returned for two reasons. First, TL will
2210 // manipulate the skb to the point where the len field is not
2211 // accurate, leading to inaccurate byte counts if we account for
2212 // it later. Second, TL does not provide any feedback as to
2213 // whether or not the packet was successfully sent over the air,
2214 // so the packet counts will be the same regardless of where we
2215 // account for them
2216 pAdapter->stats.tx_bytes += skb->len;
2217 ++pAdapter->stats.tx_packets;
2218 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued;
2219 ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac];
Mihir Shetef3473692014-06-27 15:13:20 +05302220 pAdapter->hdd_stats.hddTxRxStats.continuousTxTimeoutCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002221
Leo Chang50bbd252013-04-25 14:58:01 -07002222 if((pHddCtx->cfg_ini->thermalMitigationEnable) &&
2223 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07002224 {
2225 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
2226 {
c_hpothu32490782014-03-14 19:14:34 +05302227 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002228 "%s: Tm Lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 return VOS_STATUS_E_FAILURE;
2230 }
2231 if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel)
2232 {
2233 if(0 == pHddCtx->tmInfo.txFrameCount)
2234 {
2235 /* Just recovered from sleep timeout */
2236 pHddCtx->tmInfo.lastOpenTs = timestamp;
2237 }
2238
Leo Chang50bbd252013-04-25 14:58:01 -07002239 if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) &&
2240 ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002241 (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
2242 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002243 /* During TX open duration, TX frame count is larger than threshold
2244 * Block TX during Sleep time */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302245 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002246 netif_tx_stop_all_queues(pAdapter->dev);
Leo Chang50bbd252013-04-25 14:58:01 -07002247 pHddCtx->tmInfo.qBlocked = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002248 pHddCtx->tmInfo.lastblockTs = timestamp;
2249 if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
2250 {
2251 vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration);
2252 }
2253 }
2254 else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) &&
2255 (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold))
2256 {
2257 /* During TX open duration, TX frame count is less than threshold
2258 * Reset count and timestamp to prepare next cycle */
2259 pHddCtx->tmInfo.lastOpenTs = timestamp;
2260 pHddCtx->tmInfo.txFrameCount = 0;
2261 }
2262 else
2263 {
2264 /* Do Nothing */
2265 }
2266 pHddCtx->tmInfo.txFrameCount++;
2267 }
2268 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
2269 }
2270
2271
2272#ifdef HDD_WMM_DEBUG
c_hpothu32490782014-03-14 19:14:34 +05302273 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 -07002274#endif // HDD_WMM_DEBUG
2275
2276 return status;
2277}
2278
2279
2280/**============================================================================
2281 @brief hdd_tx_low_resource_cbk() - Callback function invoked in the
2282 case where VOS packets are not available at the time of the call to get
2283 packets. This callback function is invoked by VOS when packets are
2284 available.
2285
2286 @param pVosPacket : [in] pointer to VOS packet
2287 @param userData : [in] opaque user data that was passed initially
2288
2289 @return : VOS_STATUS_E_FAILURE if any errors encountered,
2290 : VOS_STATUS_SUCCESS otherwise
2291 =============================================================================*/
2292VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket,
2293 v_VOID_t *userData )
2294{
2295 VOS_STATUS status;
2296 v_SINT_t i = 0;
2297 v_SIZE_t size = 0;
2298 hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
2299
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302300 if (NULL == pAdapter || WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
Jeff Johnson295189b2012-06-20 16:38:30 -07002301 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302302 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2303 FL("Invalid adapter %p"), pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002304 return VOS_STATUS_E_FAILURE;
2305 }
2306
2307 //Return the packet to VOS. We just needed to know that VOS is out of low resource
2308 //situation. Here we will only signal TL that there is a pending data for a STA.
2309 //VOS packet will be requested (if needed) when TL comes back to fetch data.
2310 vos_pkt_return_packet( pVosPacket );
2311
2312 pAdapter->isVosOutOfResource = VOS_FALSE;
2313
2314 //Indicate to TL that there is pending data if a queue is non empty
2315 for( i=NUM_TX_QUEUES-1; i>=0; --i )
2316 {
2317 size = 0;
2318 hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
2319 if ( size > 0 )
2320 {
2321 status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
2322 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0],
2323 (WLANTL_ACEnumType)i );
2324 if( !VOS_IS_STATUS_SUCCESS( status ) )
2325 {
c_hpothu32490782014-03-14 19:14:34 +05302326 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302327 "%s: Failure in indicating pkt to TL for ac=%d", __func__, i);
Jeff Johnson295189b2012-06-20 16:38:30 -07002328 }
2329 }
2330 }
2331
2332 return VOS_STATUS_SUCCESS;
2333}
2334
Katya Nigame7b69a82015-04-28 15:24:06 +05302335static void hdd_mon_add_rx_radiotap_hdr (struct sk_buff *skb,
2336 int rtap_len, v_PVOID_t pRxPacket, hdd_mon_ctx_t *pMonCtx)
2337{
2338 u8 rtap_temp[20] = {0};
2339 struct ieee80211_radiotap_header *rthdr;
2340 unsigned char *pos;
2341 u16 rx_flags = 0;
2342 u16 rateIdx;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302343 s8 currentRSSI, currentRSSI0, currentRSSI1;
Katya Nigame7b69a82015-04-28 15:24:06 +05302344
2345 rateIdx = WDA_GET_RX_MAC_RATE_IDX(pRxPacket);
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302346 if( rateIdx >= 210 && rateIdx <= 217)
2347 rateIdx-=202;
2348 if( rateIdx >= 218 && rateIdx <= 225 )
2349 rateIdx-=210;
2350 currentRSSI0 = WDA_GETRSSI0(pRxPacket) - 100;
2351 currentRSSI1 = WDA_GETRSSI1(pRxPacket) - 100;
2352 currentRSSI = (currentRSSI0 > currentRSSI1) ? currentRSSI0 : currentRSSI1;
Katya Nigame7b69a82015-04-28 15:24:06 +05302353
2354 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2355
2356 /* radiotap header, set always present flags */
2357 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2358 (1 << IEEE80211_RADIOTAP_CHANNEL) |
2359 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2360 rthdr->it_len = cpu_to_le16(rtap_len);
2361
2362 pos = (unsigned char *) (rthdr + 1);
2363
2364 /* IEEE80211_RADIOTAP_FLAGS */
2365 *pos = 0;
2366 pos++;
2367
2368 /* IEEE80211_RADIOTAP_RATE */
2369 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
2370 *pos = gRatefromIdx[rateIdx]/5;
2371
2372 pos++;
2373
2374 /* IEEE80211_RADIOTAP_CHANNEL */
2375 put_unaligned_le16(pMonCtx->ChannelNo, pos);
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302376 pos += 4;
2377
2378 /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
2379 *pos = currentRSSI;
2380 rthdr->it_present |=cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
2381 pos++;
Katya Nigame7b69a82015-04-28 15:24:06 +05302382
2383 if ((pos - (u8 *)rthdr) & 1)
2384 pos++;
2385 put_unaligned_le16(rx_flags, pos);
2386 pos += 2;
2387
2388 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2389}
2390
2391
2392VOS_STATUS hdd_rx_packet_monitor_cbk(v_VOID_t *vosContext,vos_pkt_t *pVosPacket, int conversion)
2393{
2394 struct sk_buff *skb = NULL;
2395 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2396 hdd_adapter_t *pAdapter = NULL;
2397 hdd_context_t *pHddCtx = NULL;
2398 hdd_mon_ctx_t *pMonCtx = NULL;
2399 v_PVOID_t pvBDHeader = NULL;
2400 int rxstat;
2401 int needed_headroom = 0;
2402
2403
2404 //Sanity check on inputs
2405 if ( ( NULL == vosContext ) ||
2406 ( NULL == pVosPacket ) )
2407 {
2408 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2409 "%s: Null params being passed", __func__);
2410 return VOS_STATUS_E_FAILURE;
2411 }
2412
2413 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
2414 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
2415 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
2416 {
2417 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2418 FL("Invalid adapter %p for MONITOR MODE"), pAdapter);
2419 vos_pkt_return_packet( pVosPacket );
2420 return VOS_STATUS_E_FAILURE;
2421 }
2422
2423 status = WDA_DS_PeekRxPacketInfo( pVosPacket, (v_PVOID_t)&pvBDHeader, 1/*Swap BD*/ );
2424 if ( NULL == pvBDHeader )
2425 {
2426 VOS_TRACE( VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
2427 "Cannot extract BD header");
2428 /* Drop packet */
2429 vos_pkt_return_packet(pVosPacket);
2430 return VOS_STATUS_E_FAILURE;
2431 }
2432
2433 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
2434 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
2435 if(!VOS_IS_STATUS_SUCCESS( status ))
2436 {
2437 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
2438 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2439 "%s: Failure extracting skb from vos pkt", __func__);
2440 vos_pkt_return_packet( pVosPacket );
2441 return VOS_STATUS_E_FAILURE;
2442 }
2443
2444 if(!conversion)
2445 {
2446 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05302447 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 10;
Katya Nigame7b69a82015-04-28 15:24:06 +05302448 hdd_mon_add_rx_radiotap_hdr( skb, needed_headroom, pvBDHeader, pMonCtx );
2449 }
2450
2451 skb_reset_mac_header( skb );
2452 skb->dev = pAdapter->dev;
2453 skb->pkt_type = PACKET_OTHERHOST;
2454 skb->protocol = htons(ETH_P_802_2);
2455 skb->ip_summed = CHECKSUM_NONE;
2456 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2457 ++pAdapter->stats.rx_packets;
2458 pAdapter->stats.rx_bytes += skb->len;
2459
2460 rxstat = netif_rx_ni(skb);
2461 if (NET_RX_SUCCESS == rxstat)
2462 {
2463 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
2464 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
2465 }
2466 else
2467 {
2468 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2469 }
2470
2471 status = vos_pkt_return_packet( pVosPacket );
2472 if(!VOS_IS_STATUS_SUCCESS( status ))
2473 {
2474 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
2475 }
2476 pAdapter->dev->last_rx = jiffies;
2477
2478return status;
2479}
Jeff Johnson295189b2012-06-20 16:38:30 -07002480
2481/**============================================================================
2482 @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
2483 TL will call this to notify the HDD when one or more packets were
2484 received for a registered STA.
2485
2486 @param vosContext : [in] pointer to VOS context
2487 @param pVosPacketChain : [in] pointer to VOS packet chain
2488 @param staId : [in] Station Id
2489 @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s)
2490
2491 @return : VOS_STATUS_E_FAILURE if any errors encountered,
2492 : VOS_STATUS_SUCCESS otherwise
2493 ===========================================================================*/
2494VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext,
2495 vos_pkt_t *pVosPacketChain,
2496 v_U8_t staId,
2497 WLANTL_RxMetaInfoType* pRxMetaInfo )
2498{
2499 hdd_adapter_t *pAdapter = NULL;
2500 hdd_context_t *pHddCtx = NULL;
2501 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2502 int rxstat;
2503 struct sk_buff *skb = NULL;
2504 vos_pkt_t* pVosPacket;
2505 vos_pkt_t* pNextVosPacket;
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002506 v_U8_t proto_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002507
2508 //Sanity check on inputs
2509 if ( ( NULL == vosContext ) ||
2510 ( NULL == pVosPacketChain ) ||
2511 ( NULL == pRxMetaInfo ) )
2512 {
c_hpothu32490782014-03-14 19:14:34 +05302513 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302514 "%s: Null params being passed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002515 return VOS_STATUS_E_FAILURE;
2516 }
2517
Kiet Lam3c2ee302014-03-23 23:23:22 -07002518 pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
Jeff Johnson295189b2012-06-20 16:38:30 -07002519 if ( NULL == pHddCtx )
2520 {
c_hpothu32490782014-03-14 19:14:34 +05302521 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302522 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002523 return VOS_STATUS_E_FAILURE;
2524 }
2525
2526 pAdapter = pHddCtx->sta_to_adapter[staId];
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302527 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002528 {
Hanumantha Reddy Pothula4ba27c52015-03-12 14:31:10 +05302529 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2530 FL("Invalid adapter %p for staId %u"), pAdapter, staId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 return VOS_STATUS_E_FAILURE;
2532 }
2533
2534 ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
2535
2536 // walk the chain until all are processed
2537 pVosPacket = pVosPacketChain;
2538 do
2539 {
2540 // get the pointer to the next packet in the chain
2541 // (but don't unlink the packet since we free the entire chain later)
2542 status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);
2543
2544 // both "success" and "empty" are acceptable results
2545 if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
2546 {
2547 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302548 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302549 "%s: Failure walking packet chain", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002550 return VOS_STATUS_E_FAILURE;
2551 }
2552
2553 // Extract the OS packet (skb).
Sushant Kaushikd43987b2015-06-05 12:18:34 +05302554 status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07002555 if(!VOS_IS_STATUS_SUCCESS( status ))
2556 {
2557 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
c_hpothu32490782014-03-14 19:14:34 +05302558 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Agarwal Ashish971c2882013-10-30 20:11:12 +05302559 "%s: Failure extracting skb from vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 return VOS_STATUS_E_FAILURE;
2561 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002562
Sushant Kaushikd43987b2015-06-05 12:18:34 +05302563 if (TRUE == hdd_IsEAPOLPacket( pVosPacket ))
2564 wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
2565
2566 pVosPacket->pSkb = NULL;
2567
Jeff Johnsone7245742012-09-05 17:12:55 -07002568 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2569 {
c_hpothu32490782014-03-14 19:14:34 +05302570 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsone7245742012-09-05 17:12:55 -07002571 "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
2572 return eHAL_STATUS_FAILURE;
2573 }
2574
Chilam Ng1279e232013-01-25 15:06:52 -08002575#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4ddf0192013-03-27 13:41:20 -07002576 if ((eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) &&
2577 0 != pHddCtx->connected_peer_count)
Chilam Ng1279e232013-01-25 15:06:52 -08002578 {
2579 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Chilam Ng1279e232013-01-25 15:06:52 -08002580 u8 mac[6];
2581
Hoonki Lee387663d2013-02-05 18:08:43 -08002582 wlan_hdd_tdls_extract_sa(skb, mac);
Chilam Ng1279e232013-01-25 15:06:52 -08002583
Hoonki Lee5fcc4582013-02-05 20:28:26 -08002584 if (vos_is_macaddr_group((v_MACADDR_t *)mac)) {
c_hpothu32490782014-03-14 19:14:34 +05302585 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002586 "rx broadcast packet, not adding to peer list");
2587 } else if (memcmp(pHddStaCtx->conn_info.bssId,
2588 mac, 6) != 0) {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002589 hddTdlsPeer_t *curr_peer;
c_hpothu32490782014-03-14 19:14:34 +05302590 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002591 "rx extract mac:" MAC_ADDRESS_STR,
2592 MAC_ADDR_ARRAY(mac) );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302593 curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkala4a2fc1a2013-05-17 16:59:39 +05302594 if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)
2595 && (TRUE == pRxMetaInfo->isStaTdls))
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002596 {
2597 wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0);
c_hpothu32490782014-03-14 19:14:34 +05302598 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg);
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002599 wlan_hdd_tdls_set_rssi (pAdapter, mac, pRxMetaInfo->rssiAvg);
2600 }
Chilam Ng1279e232013-01-25 15:06:52 -08002601 } else {
c_hpothu32490782014-03-14 19:14:34 +05302602 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED,
Chilam Ng1279e232013-01-25 15:06:52 -08002603 "rx packet sa is bssid, not adding to peer list");
2604 }
2605 }
2606#endif
2607
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002608 if (pHddCtx->cfg_ini->gEnableDebugLog)
2609 {
2610 proto_type = vos_pkt_get_proto_type(skb,
2611 pHddCtx->cfg_ini->gEnableDebugLog);
2612 if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
2613 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302614 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Nirav Shah4b53d4b2015-05-08 05:35:00 -07002615 "STA RX EAPOL");
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002616 }
2617 else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
2618 {
Padma, Santhosh Kumar2d258f72014-12-22 19:55:59 +05302619 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002620 "STA RX DHCP");
2621 }
Mihir Shete39f7c752015-06-11 15:40:09 +05302622 else if (VOS_PKT_PROTO_TYPE_ARP & proto_type)
2623 {
2624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2625 "STA RX ARP");
2626 }
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08002627 }
2628
Girish Gowli8a7bc042015-01-19 16:20:20 +05302629 if (pHddCtx->cfg_ini->gEnableRoamDelayStats)
2630 {
2631 vos_record_roam_event(e_HDD_RX_PKT_CBK_TIME, (void *)skb, 0);
2632 }
Sachin Ahuja8c65f382014-12-12 15:34:21 +05302633 if (( NULL != pHddCtx ) &&
2634 (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
Dino Mycled9b7cc12014-09-04 18:43:07 +05302635 {
2636 hdd_dump_dhcp_pkt(skb, RX_PATH);
2637 }
Mukul Sharma84f27252014-07-14 18:11:42 +05302638
Jeff Johnson295189b2012-06-20 16:38:30 -07002639 skb->dev = pAdapter->dev;
2640 skb->protocol = eth_type_trans(skb, skb->dev);
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002641 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
2643 ++pAdapter->stats.rx_packets;
2644 pAdapter->stats.rx_bytes += skb->len;
Jeff Johnsone7245742012-09-05 17:12:55 -07002645#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302646 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2647 HDD_WAKE_LOCK_DURATION,
2648 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002649#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002650 rxstat = netif_rx_ni(skb);
2651 if (NET_RX_SUCCESS == rxstat)
2652 {
2653 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002654 ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07002655 }
2656 else
2657 {
2658 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
2659 }
2660 // now process the next packet in the chain
2661 pVosPacket = pNextVosPacket;
2662
2663 } while (pVosPacket);
2664
2665 //Return the entire VOS packet chain to the resource pool
2666 status = vos_pkt_return_packet( pVosPacketChain );
2667 if(!VOS_IS_STATUS_SUCCESS( status ))
2668 {
c_hpothu32490782014-03-14 19:14:34 +05302669 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002670 }
2671
2672 pAdapter->dev->last_rx = jiffies;
2673
2674 return status;
2675}
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002676/**============================================================================
2677 @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() -
2678 Enable/Disable split scan based on TX and RX traffic.
2679 @param HddContext : [in] pointer to Hdd context
2680 @return : None
2681 ===========================================================================*/
2682void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx)
2683{
2684 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2685 hdd_adapter_t *pAdapter = NULL;
2686 hdd_station_ctx_t *pHddStaCtx = NULL;
2687 hdd_context_t *pHddCtx = (hdd_context_t *)phddctx;
2688 hdd_config_t *cfg_param = pHddCtx->cfg_ini;
2689 VOS_STATUS status;
2690 v_U8_t staId = 0;
2691 v_U8_t fconnected = 0;
2692
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +05302693 ENTER();
2694 if (0 != (wlan_hdd_validate_context(pHddCtx)))
2695 {
2696 return;
2697 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002698 if (!cfg_param->dynSplitscan)
2699 {
c_hpothu32490782014-03-14 19:14:34 +05302700 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002701 "%s: Error : Dynamic split scan is not Enabled : %d",
2702 __func__, pHddCtx->cfg_ini->dynSplitscan);
2703 return;
2704 }
2705
2706 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2707 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2708 {
2709 pAdapter = pAdapterNode->pAdapter;
2710
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +05302711 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002712 {
c_hpothu32490782014-03-14 19:14:34 +05302713 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002714 "%s: Adapter with device mode %d exists",
2715 __func__, pAdapter->device_mode);
2716
2717 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2718 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
2719 {
2720 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2721 if ((eConnectionState_Associated ==
2722 pHddStaCtx->conn_info.connState) &&
2723 (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated))
2724 {
2725 fconnected = TRUE;
2726 }
2727 }
2728 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2729 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
2730 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302731 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2732 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
2733 if(pSapCtx == NULL){
2734 VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
2735 FL("psapCtx is NULL"));
2736 return;
2737 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002738 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
2739 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302740 if ((pSapCtx->aStaInfo[staId].isUsed) &&
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002741 (WLANTL_STA_AUTHENTICATED ==
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05302742 pSapCtx->aStaInfo[staId].tlSTAState))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002743 {
2744 fconnected = TRUE;
2745 }
2746 }
2747 }
2748 if ( fconnected )
2749 {
c_hpothu32490782014-03-14 19:14:34 +05302750 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002751 "%s: One of the interface is connected check for scan",
2752 __func__);
c_hpothu32490782014-03-14 19:14:34 +05302753 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
Abhishek Singh90485302014-05-15 16:36:57 +05302754 "%s: pkt_tx_count: %d, pkt_rx_count: %d "
2755 "miracast = %d", __func__,
2756 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count,
2757 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count,
2758 pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002759
2760 vos_timer_start(&pHddCtx->tx_rx_trafficTmr,
2761 cfg_param->trafficMntrTmrForSplitScan);
2762 //Check for the previous statistics count
2763 if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count >
2764 cfg_param->txRxThresholdForSplitScan) ||
2765 (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count >
2766 cfg_param->txRxThresholdForSplitScan) ||
Abhishek Singh90485302014-05-15 16:36:57 +05302767 pHddCtx->drvr_miracast ||
2768 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002769 {
2770 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2771 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2772
2773 if (!pHddCtx->issplitscan_enabled)
2774 {
2775 pHddCtx->issplitscan_enabled = TRUE;
2776 sme_enable_disable_split_scan(
2777 WLAN_HDD_GET_HAL_CTX(pAdapter),
2778 cfg_param->nNumStaChanCombinedConc,
2779 cfg_param->nNumP2PChanCombinedConc);
2780 }
2781 return;
2782 }
2783 else
2784 {
2785 pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0;
2786 pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0;
2787 }
2788 fconnected = FALSE;
2789 }
2790 }
2791 status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext);
2792 pAdapterNode = pNext;
2793 }
2794
Pradeep Reddy POTTETIedaeb5f2014-05-22 23:34:41 +05302795 /* If TDLSScanCoexistence is enabled, then the TDLS module shall take care
2796 * of disabling the split scan and thus do not disable the same when the
2797 * low TXRX condition is met.
2798 */
2799 if ((pHddCtx->isTdlsScanCoexistence == FALSE) && (pHddCtx->issplitscan_enabled))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002800 {
c_hpothu32490782014-03-14 19:14:34 +05302801 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002802 "%s: Disable split scan", __func__);
2803 pHddCtx->issplitscan_enabled = FALSE;
2804 sme_enable_disable_split_scan(
2805 pHddCtx->hHal,
2806 SME_DISABLE_SPLIT_SCAN,
2807 SME_DISABLE_SPLIT_SCAN);
2808 }
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +05302809 EXIT();
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002810 return;
2811}
Jeff Johnson295189b2012-06-20 16:38:30 -07002812
Sushant Kaushika8073312015-05-04 17:33:52 +05302813#ifdef FEATURE_WLAN_DIAG_SUPPORT
2814/*
2815 * wlan_hdd_get_eapol_params() - Function to extract EAPOL params
2816 * @skb: skb data
2817 * @eapol_params: Pointer to hold the parsed EAPOL params
2818 * @event_type: Event type to indicate Tx/Rx
2819 *
2820 * This function parses the input skb data to get the EAPOL params,if the
2821 * packet is EAPOL and store it in the pointer passed as input
2822 *
2823 */
2824void wlan_hdd_get_eapol_params(struct sk_buff *skb,
2825 struct vos_event_wlan_eapol *eapol_params,
2826 uint8_t event_type)
2827{
2828 uint8_t packet_type=0;
2829
2830 packet_type = (uint8_t)(*(uint8_t *)
2831 (skb->data + HDD_EAPOL_PACKET_TYPE_OFFSET));
2832
2833 /* EAPOL msg type i.e. whether EAPOL-Start or
2834 * EAPOL-Key etc. messages Present at 15 offset.
2835 */
2836 eapol_params->eapol_packet_type = packet_type;
2837
2838 /* This tells if its a M1/M2/M3/M4 packet.
2839 * Present at 19th offset in EAPOL frame.
2840 */
2841 eapol_params->eapol_key_info = (uint16_t)(*(uint16_t *)
2842 (skb->data + HDD_EAPOL_KEY_INFO_OFFSET));
2843 /* This tells if EAPOL packet is in RX or TX
2844 * direction.
2845 */
2846 eapol_params->event_sub_type = event_type;
2847
2848 /* This tells the rate at which EAPOL packet
2849 * is send or received.
2850 */
2851 //TODO fill data rate for rx packet.
2852 eapol_params->eapol_rate = 0;/* As of now, zero */
2853
2854 vos_mem_copy(eapol_params->dest_addr,
2855 (skb->data + HDD_EAPOL_DEST_MAC_OFFSET),
2856 sizeof(eapol_params->dest_addr));
2857 vos_mem_copy(eapol_params->src_addr,
2858 (skb->data + HDD_EAPOL_SRC_MAC_OFFSET),
2859 sizeof(eapol_params->src_addr));
2860 return;
2861}
2862/*
2863 * wlan_hdd_event_eapol_log() - Function to log EAPOL events
2864 * @eapol_params: Structure containing EAPOL params
2865 *
2866 * This function logs the parsed EAPOL params
2867 *
2868 * Return: None
2869 *
2870 */
2871
2872static void wlan_hdd_event_eapol_log(struct vos_event_wlan_eapol eapol_params)
2873{
2874 WLAN_VOS_DIAG_EVENT_DEF(wlan_diag_event, struct vos_event_wlan_eapol);
2875
2876 wlan_diag_event.event_sub_type = eapol_params.event_sub_type;
2877 wlan_diag_event.eapol_packet_type = eapol_params.eapol_packet_type;
2878 wlan_diag_event.eapol_key_info = eapol_params.eapol_key_info;
2879 wlan_diag_event.eapol_rate = eapol_params.eapol_rate;
2880 vos_mem_copy(wlan_diag_event.dest_addr,
2881 eapol_params.dest_addr,
2882 sizeof (wlan_diag_event.dest_addr));
2883 vos_mem_copy(wlan_diag_event.src_addr,
2884 eapol_params.src_addr,
2885 sizeof (wlan_diag_event.src_addr));
2886 WLAN_VOS_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL);
2887}
2888
2889/*
2890 * wlan_hdd_log_eapol() - Function to check and extract EAPOL params
2891 * @skb: skb data
2892 * @event_type: One of enum wifi_connectivity_events to indicate Tx/Rx
2893 *
2894 * This function parses the input skb data to get the EAPOL params,if the
2895 * packet is EAPOL and store it in the pointer passed as input
2896 *
2897 * Return: None
2898 *
2899 */
2900void wlan_hdd_log_eapol(struct sk_buff *skb,
2901 uint8_t event_type)
2902{
2903 struct vos_event_wlan_eapol eapol_params;
2904
2905 wlan_hdd_get_eapol_params(skb, &eapol_params, event_type);
2906 wlan_hdd_event_eapol_log(eapol_params);
2907 VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
2908 "Eapol subtype is %d and key info is %d\n",
2909 eapol_params.event_sub_type,eapol_params.eapol_key_info);
2910}
2911#endif /* FEATURE_WLAN_DIAG_SUPPORT */