blob: 93283605640c4e309c80a1521599db51c9cdfe3e [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Orhan K AKYILDIZ4f20db52015-12-30 12:35:44 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -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.
20 */
21
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
28/**
29 * DOC: wlan_hdd_tx_rx.c
30 *
31 * Linux HDD Tx/RX APIs
32 */
33
34#include <wlan_hdd_tx_rx.h>
35#include <wlan_hdd_softap_tx_rx.h>
36#include <wlan_hdd_napi.h>
37#include <linux/netdevice.h>
38#include <linux/skbuff.h>
39#include <linux/etherdevice.h>
Ravi Joshibb8d4512016-08-22 10:14:52 -070040#include <linux/if_ether.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080041#include <cds_sched.h>
Manjunathappa Prakash779e4862016-09-12 17:00:11 -070042#include <cds_utils.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043
44#include <wlan_hdd_p2p.h>
45#include <linux/wireless.h>
46#include <net/cfg80211.h>
47#include <net/ieee80211_radiotap.h>
48#include "sap_api.h"
49#include "wlan_hdd_wmm.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050#include "wlan_hdd_tdls.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051#include <wlan_hdd_ipa.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080052#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_lro.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080054#include "cdp_txrx_peer_ops.h"
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070055#include "ol_txrx.h"
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -070056#include "wlan_hdd_nan_datapath.h"
Ravi Joshib89e7f72016-09-07 13:43:15 -070057#include "pld_common.h"
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -070058
Poddar, Siddarth4acb30a2016-09-22 20:07:53 +053059#ifdef QCA_LL_TX_FLOW_CONTROL_V2
60/*
61 * Mapping Linux AC interpretation to SME AC.
62 * Host has 5 tx queues, 4 flow-controlled queues for regular traffic and
63 * one non-flow-controlled queue for high priority control traffic(EOPOL, DHCP).
64 * The fifth queue is mapped to AC_VO to allow for proper prioritization.
65 */
66const uint8_t hdd_qdisc_ac_to_tl_ac[] = {
67 SME_AC_VO,
68 SME_AC_VI,
69 SME_AC_BE,
70 SME_AC_BK,
71 SME_AC_VO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072};
73
Poddar, Siddarth4acb30a2016-09-22 20:07:53 +053074#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075const uint8_t hdd_qdisc_ac_to_tl_ac[] = {
76 SME_AC_VO,
77 SME_AC_VI,
78 SME_AC_BE,
79 SME_AC_BK,
80};
81
Poddar, Siddarth4acb30a2016-09-22 20:07:53 +053082#endif
83
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
85/**
86 * hdd_tx_resume_timer_expired_handler() - TX Q resume timer handler
87 * @adapter_context: pointer to vdev adapter
88 *
89 * If Blocked OS Q is not resumed during timeout period, to prevent
90 * permanent stall, resume OS Q forcefully.
91 *
92 * Return: None
93 */
94void hdd_tx_resume_timer_expired_handler(void *adapter_context)
95{
96 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
97
98 if (!pAdapter) {
99 /* INVALID ARG */
100 return;
101 }
102
103 hddLog(LOG1, FL("Enabling queues"));
104 wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE,
105 WLAN_CONTROL_PATH);
106 return;
107}
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530108#if defined(CONFIG_PER_VDEV_TX_DESC_POOL)
109
110/**
111 * hdd_tx_resume_false() - Resume OS TX Q false leads to queue disabling
112 * @pAdapter: pointer to hdd adapter
113 * @tx_resume: TX Q resume trigger
114 *
115 *
116 * Return: None
117 */
118static void
119hdd_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
120{
121 if (true == tx_resume)
122 return;
123
124 /* Pause TX */
125 hdd_notice("Disabling queues");
126 wlan_hdd_netif_queue_control(pAdapter, WLAN_STOP_ALL_NETIF_QUEUE,
127 WLAN_DATA_FLOW_CONTROL);
128
129 if (QDF_TIMER_STATE_STOPPED ==
130 qdf_mc_timer_get_current_state(&pAdapter->
131 tx_flow_control_timer)) {
132 QDF_STATUS status;
133 status = qdf_mc_timer_start(&pAdapter->tx_flow_control_timer,
134 WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
135
136 if (!QDF_IS_STATUS_SUCCESS(status))
137 hdd_err("Failed to start tx_flow_control_timer");
138 else
139 pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++;
140 }
141
142 pAdapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++;
143 pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = true;
144
145 return;
146}
147#else
148
149static inline void
150hdd_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
151{
152 return;
153}
154#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155
156/**
157 * hdd_tx_resume_cb() - Resume OS TX Q.
158 * @adapter_context: pointer to vdev apdapter
159 * @tx_resume: TX Q resume trigger
160 *
161 * Q was stopped due to WLAN TX path low resource condition
162 *
163 * Return: None
164 */
165void hdd_tx_resume_cb(void *adapter_context, bool tx_resume)
166{
167 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
168 hdd_station_ctx_t *hdd_sta_ctx = NULL;
169
170 if (!pAdapter) {
171 /* INVALID ARG */
172 return;
173 }
174
175 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
176
177 /* Resume TX */
178 if (true == tx_resume) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530179 if (QDF_TIMER_STATE_STOPPED !=
180 qdf_mc_timer_get_current_state(&pAdapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800181 tx_flow_control_timer)) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530182 qdf_mc_timer_stop(&pAdapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800183 }
Anurag Chouhanc5548422016-02-24 18:33:27 +0530184 if (qdf_unlikely(hdd_sta_ctx->hdd_ReassocScenario)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185 hddLog(LOGW,
186 FL("flow control, tx queues un-pause avoided as we are in REASSOCIATING state"));
187 return;
188 }
189 hddLog(LOG1, FL("Enabling queues"));
190 wlan_hdd_netif_queue_control(pAdapter,
191 WLAN_WAKE_ALL_NETIF_QUEUE,
192 WLAN_DATA_FLOW_CONTROL);
193 }
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530194 hdd_tx_resume_false(pAdapter, tx_resume);
195
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196 return;
197}
198
199/**
200 * hdd_register_tx_flow_control() - Register TX Flow control
201 * @adapter: adapter handle
202 * @timer_callback: timer callback
203 * @flow_control_fp: txrx flow control
204 *
205 * Return: none
206 */
207void hdd_register_tx_flow_control(hdd_adapter_t *adapter,
Anurag Chouhan210db072016-02-22 18:42:15 +0530208 qdf_mc_timer_callback_t timer_callback,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 ol_txrx_tx_flow_control_fp flow_control_fp)
210{
211 if (adapter->tx_flow_timer_initialized == false) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530212 qdf_mc_timer_init(&adapter->tx_flow_control_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530213 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214 timer_callback,
215 adapter);
216 adapter->tx_flow_timer_initialized = true;
217 }
218 ol_txrx_register_tx_flow_control(adapter->sessionId,
219 flow_control_fp,
220 adapter);
221
222}
223
224/**
225 * hdd_deregister_tx_flow_control() - Deregister TX Flow control
226 * @adapter: adapter handle
227 *
228 * Return: none
229 */
230void hdd_deregister_tx_flow_control(hdd_adapter_t *adapter)
231{
232 ol_txrx_deregister_tx_flow_control_cb(adapter->sessionId);
233 if (adapter->tx_flow_timer_initialized == true) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530234 qdf_mc_timer_stop(&adapter->tx_flow_control_timer);
235 qdf_mc_timer_destroy(&adapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236 adapter->tx_flow_timer_initialized = false;
237 }
238}
239
240/**
241 * hdd_get_tx_resource() - check tx resources and take action
242 * @adapter: adapter handle
243 * @STAId: station id
244 * @timer_value: timer value
245 *
246 * Return: none
247 */
248void hdd_get_tx_resource(hdd_adapter_t *adapter,
249 uint8_t STAId, uint16_t timer_value)
250{
251 if (false ==
252 ol_txrx_get_tx_resource(STAId,
253 adapter->tx_flow_low_watermark,
254 adapter->tx_flow_high_watermark_offset)) {
255 hdd_info("Disabling queues lwm %d hwm offset %d",
256 adapter->tx_flow_low_watermark,
257 adapter->tx_flow_high_watermark_offset);
258 wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE,
259 WLAN_DATA_FLOW_CONTROL);
260 if ((adapter->tx_flow_timer_initialized == true) &&
Anurag Chouhan210db072016-02-22 18:42:15 +0530261 (QDF_TIMER_STATE_STOPPED ==
262 qdf_mc_timer_get_current_state(&adapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800263 tx_flow_control_timer))) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530264 qdf_mc_timer_start(&adapter->tx_flow_control_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800265 timer_value);
266 adapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++;
267 adapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++;
268 adapter->hdd_stats.hddTxRxStats.is_txflow_paused = true;
269 }
270 }
271}
272
273#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
274
Nirav Shah5e74bb82016-07-20 16:01:27 +0530275/**
276 * qdf_event_eapol_log() - send event to wlan diag
277 * @skb: skb ptr
278 * @dir: direction
279 * @eapol_key_info: eapol key info
280 *
281 * Return: None
282 */
283void hdd_event_eapol_log(struct sk_buff *skb, enum qdf_proto_dir dir)
284{
285 int16_t eapol_key_info;
286
287 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct host_event_wlan_eapol);
288
289 if ((dir == QDF_TX &&
290 (QDF_NBUF_CB_PACKET_TYPE_EAPOL !=
291 QDF_NBUF_CB_GET_PACKET_TYPE(skb))))
292 return;
293 else if (!qdf_nbuf_is_ipv4_eapol_pkt(skb))
294 return;
295
296 eapol_key_info = (uint16_t)(*(uint16_t *)
297 (skb->data + EAPOL_KEY_INFO_OFFSET));
298
299 wlan_diag_event.event_sub_type =
300 (dir == QDF_TX ?
301 WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED :
302 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
303 wlan_diag_event.eapol_packet_type = (uint8_t)(*(uint8_t *)
304 (skb->data + EAPOL_PACKET_TYPE_OFFSET));
305 wlan_diag_event.eapol_key_info = eapol_key_info;
306 wlan_diag_event.eapol_rate = 0;
307 qdf_mem_copy(wlan_diag_event.dest_addr,
308 (skb->data + QDF_NBUF_DEST_MAC_OFFSET),
309 sizeof(wlan_diag_event.dest_addr));
310 qdf_mem_copy(wlan_diag_event.src_addr,
311 (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
312 sizeof(wlan_diag_event.src_addr));
313
314 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL);
315}
316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800317
318/**
Nirav Shah5e74bb82016-07-20 16:01:27 +0530319 * wlan_hdd_classify_pkt() - classify packet
320 * @skb - sk buff
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321 *
Nirav Shah5e74bb82016-07-20 16:01:27 +0530322 * Return: none
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800323 */
Nirav Shah5e74bb82016-07-20 16:01:27 +0530324void wlan_hdd_classify_pkt(struct sk_buff *skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800325{
Nirav Shah5e74bb82016-07-20 16:01:27 +0530326 struct ethhdr *eh = (struct ethhdr *)skb->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800327
Nirav Shah5e74bb82016-07-20 16:01:27 +0530328 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800329
Nirav Shah5e74bb82016-07-20 16:01:27 +0530330 /* check destination mac address is broadcast/multicast */
331 if (is_broadcast_ether_addr((uint8_t *)eh))
332 QDF_NBUF_CB_GET_IS_BCAST(skb) = true;
333 else if (is_multicast_ether_addr((uint8_t *)eh))
334 QDF_NBUF_CB_GET_IS_MCAST(skb) = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800335
Nirav Shah5e74bb82016-07-20 16:01:27 +0530336 if (qdf_nbuf_is_ipv4_arp_pkt(skb))
337 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
338 QDF_NBUF_CB_PACKET_TYPE_ARP;
339 else if (qdf_nbuf_is_ipv4_dhcp_pkt(skb))
340 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
341 QDF_NBUF_CB_PACKET_TYPE_DHCP;
342 else if (qdf_nbuf_is_ipv4_eapol_pkt(skb))
343 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
344 QDF_NBUF_CB_PACKET_TYPE_EAPOL;
345 else if (qdf_nbuf_is_ipv4_wapi_pkt(skb))
346 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
347 QDF_NBUF_CB_PACKET_TYPE_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800348
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800349}
350
351/**
Ravi Joshi24477b72016-07-19 15:45:09 -0700352 * hdd_get_transmit_sta_id() - function to retrieve station id to be used for
353 * sending traffic towards a particular destination address. The destination
354 * address can be unicast, multicast or broadcast
355 *
356 * @adapter: Handle to adapter context
357 * @dst_addr: Destination address
358 * @station_id: station id
359 *
360 * Returns: None
361 */
362static void hdd_get_transmit_sta_id(hdd_adapter_t *adapter,
Nirav Shah5e74bb82016-07-20 16:01:27 +0530363 struct sk_buff *skb, uint8_t *station_id)
Ravi Joshi24477b72016-07-19 15:45:09 -0700364{
365 bool mcbc_addr = false;
366 hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Nirav Shah5e74bb82016-07-20 16:01:27 +0530367 struct qdf_mac_addr *dst_addr = NULL;
Ravi Joshi24477b72016-07-19 15:45:09 -0700368
Nirav Shah5e74bb82016-07-20 16:01:27 +0530369 dst_addr = (struct qdf_mac_addr *)skb->data;
Ravi Joshi24477b72016-07-19 15:45:09 -0700370 hdd_get_peer_sta_id(sta_ctx, dst_addr, station_id);
371 if (*station_id == HDD_WLAN_INVALID_STA_ID) {
Nirav Shah5e74bb82016-07-20 16:01:27 +0530372 if (QDF_NBUF_CB_GET_IS_BCAST(skb) ||
373 QDF_NBUF_CB_GET_IS_MCAST(skb)) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700374 hdd_info("Received MC/BC packet for transmission");
375 mcbc_addr = true;
Ravi Joshi24477b72016-07-19 15:45:09 -0700376 }
377 }
378
Rakesh Sunkicf1c9ab2016-08-25 14:11:25 -0700379 if (adapter->device_mode == QDF_IBSS_MODE ||
380 adapter->device_mode == QDF_NDI_MODE) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700381 /*
382 * This check is necessary to make sure station id is not
Rakesh Sunkicf1c9ab2016-08-25 14:11:25 -0700383 * overwritten for UC traffic in IBSS or NDI mode
Ravi Joshi24477b72016-07-19 15:45:09 -0700384 */
385 if (mcbc_addr)
Rakesh Sunkicf1c9ab2016-08-25 14:11:25 -0700386 *station_id = sta_ctx->broadcast_staid;
Ravi Joshi24477b72016-07-19 15:45:09 -0700387 } else {
388 /* For the rest, traffic is directed to AP/P2P GO */
389 if (eConnectionState_Associated == sta_ctx->conn_info.connState)
390 *station_id = sta_ctx->conn_info.staId[0];
391 }
392}
393
394/**
Mukul Sharmac4de4ef2016-09-12 15:39:00 +0530395 * __hdd_hard_start_xmit() - Transmit a frame
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800396 * @skb: pointer to OS packet (sk_buff)
397 * @dev: pointer to network device
398 *
399 * Function registered with the Linux OS for transmitting
400 * packets. This version of the function directly passes
401 * the packet to Transport Layer.
402 *
403 * Return: Always returns NETDEV_TX_OK
404 */
Jeff Johnson3ae708d2016-10-05 15:45:00 -0700405static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800406{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530407 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 sme_ac_enum_type ac;
409 sme_QosWmmUpType up;
410 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
411 bool granted;
Nirav Shah5e74bb82016-07-20 16:01:27 +0530412 uint8_t STAId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700414#ifdef QCA_PKT_PROTO_TRACE
415 uint8_t proto_type = 0;
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700416 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Kabilan Kannan32eb5022016-10-04 12:24:50 -0700417#endif /* QCA_PKT_PROTO_TRACE */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418
419#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +0530420 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 kfree_skb(skb);
422 return NETDEV_TX_OK;
423 }
424#endif
425
426 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800427 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530428 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800429 "Recovery in progress, dropping the packet");
Nirav Shahdf3659e2016-06-27 12:26:28 +0530430 goto drop_pkt;
Govind Singhede435f2015-12-01 16:16:36 +0530431 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432
Nirav Shah5e74bb82016-07-20 16:01:27 +0530433 wlan_hdd_classify_pkt(skb);
434
Ravi Joshi24477b72016-07-19 15:45:09 -0700435 STAId = HDD_WLAN_INVALID_STA_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800436
Nirav Shah5e74bb82016-07-20 16:01:27 +0530437 hdd_get_transmit_sta_id(pAdapter, skb, &STAId);
Naveen Rawat209d0932016-08-03 15:07:23 -0700438 if (STAId >= WLAN_MAX_STA_COUNT) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700439 hddLog(LOGE, "Invalid station id, transmit operation suspended");
440 goto drop_pkt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 }
442
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 hdd_get_tx_resource(pAdapter, STAId,
444 WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
445
446 /* Get TL AC corresponding to Qdisc queue index/AC. */
447 ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
448
Nirav Shahcbc6d722016-03-01 16:24:53 +0530449 if (!qdf_nbuf_ipa_owned_get(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800450 /* Check if the buffer has enough header room */
451 skb = skb_unshare(skb, GFP_ATOMIC);
452 if (!skb)
Nirav Shahdf3659e2016-06-27 12:26:28 +0530453 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 }
455
Ravi Joshi24477b72016-07-19 15:45:09 -0700456 /*
457 * user priority from IP header, which is already extracted and set from
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 * select_queue call back function
459 */
460 up = skb->priority;
461
462 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
463#ifdef HDD_WMM_DEBUG
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530464 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465 "%s: Classified as ac %d up %d", __func__, ac, up);
466#endif /* HDD_WMM_DEBUG */
467
468 if (HDD_PSB_CHANGED == pAdapter->psbChanged) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700469 /*
470 * Function which will determine acquire admittance for a
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471 * WMM AC is required or not based on psb configuration done
472 * in the framework
473 */
474 hdd_wmm_acquire_access_required(pAdapter, ac);
475 }
476 /*
477 * Make sure we already have access to this access category
478 * or it is EAPOL or WAPI frame during initial authentication which
479 * can have artifically boosted higher qos priority.
480 */
481
482 if (((pAdapter->psbChanged & (1 << ac)) &&
483 likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].
484 wmmAcAccessAllowed)) ||
485 ((pHddStaCtx->conn_info.uIsAuthenticated == false) &&
Nirav Shah5e74bb82016-07-20 16:01:27 +0530486 (QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
487 QDF_NBUF_CB_GET_PACKET_TYPE(skb) ||
488 QDF_NBUF_CB_PACKET_TYPE_WAPI ==
489 QDF_NBUF_CB_GET_PACKET_TYPE(skb)))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490 granted = true;
491 } else {
492 status = hdd_wmm_acquire_access(pAdapter, ac, &granted);
493 pAdapter->psbChanged |= (1 << ac);
494 }
495
496 if (!granted) {
497 bool isDefaultAc = false;
Ravi Joshi24477b72016-07-19 15:45:09 -0700498 /*
499 * ADDTS request for this AC is sent, for now
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 * send this packet through next avaiable lower
501 * Access category until ADDTS negotiation completes.
502 */
503 while (!likely
504 (pAdapter->hddWmmStatus.wmmAcStatus[ac].
505 wmmAcAccessAllowed)) {
506 switch (ac) {
507 case SME_AC_VO:
508 ac = SME_AC_VI;
509 up = SME_QOS_WMM_UP_VI;
510 break;
511 case SME_AC_VI:
512 ac = SME_AC_BE;
513 up = SME_QOS_WMM_UP_BE;
514 break;
515 case SME_AC_BE:
516 ac = SME_AC_BK;
517 up = SME_QOS_WMM_UP_BK;
518 break;
519 default:
520 ac = SME_AC_BK;
521 up = SME_QOS_WMM_UP_BK;
522 isDefaultAc = true;
523 break;
524 }
525 if (isDefaultAc)
526 break;
527 }
528 skb->priority = up;
529 skb->queue_mapping = hdd_linux_up_to_ac_map[up];
530 }
531
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700532#ifdef QCA_PKT_PROTO_TRACE
533 if ((hdd_ctx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
534 (hdd_ctx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
535 proto_type = cds_pkt_get_proto_type(skb,
536 hdd_ctx->config->gEnableDebugLog,
537 0);
538 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
539 cds_pkt_trace_buf_update("ST:T:EPL");
540 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
541 cds_pkt_trace_buf_update("ST:T:DHC");
542 }
543 }
544#endif /* QCA_PKT_PROTO_TRACE */
545
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546 pAdapter->stats.tx_bytes += skb->len;
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700547
Kabilan Kannan32eb5022016-10-04 12:24:50 -0700548 wlan_hdd_tdls_update_tx_pkt_cnt(pAdapter, skb);
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 ++pAdapter->stats.tx_packets;
551
Nirav Shah5e74bb82016-07-20 16:01:27 +0530552 hdd_event_eapol_log(skb, QDF_TX);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530553 qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530554 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
555 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530557 qdf_dp_trace_set_track(skb, QDF_TX);
558 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
559 (uint8_t *)&skb->data, sizeof(skb->data), QDF_TX));
560 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
561 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shah07e39a62016-04-25 17:46:40 +0530562 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE) {
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530563 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
564 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
565 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Nirav Shah07e39a62016-04-25 17:46:40 +0530566 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800568 /* Check if station is connected */
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800569 if (OL_TXRX_PEER_STATE_CONN ==
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800570 pAdapter->aStaInfo[STAId].tlSTAState) {
571 QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
572 QDF_TRACE_LEVEL_WARN,
573 "%s: station is not connected..dropping pkt",
574 __func__);
Nirav Shahdf3659e2016-06-27 12:26:28 +0530575 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
576 goto drop_pkt;
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800577 }
578
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800579 /*
Ravi Joshi24477b72016-07-19 15:45:09 -0700580 * If a transmit function is not registered, drop packet
581 */
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800582 if (!pAdapter->tx_fn) {
583 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
584 "%s: TX function not registered by the data path",
585 __func__);
Nirav Shahdf3659e2016-06-27 12:26:28 +0530586 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800587 goto drop_pkt;
588 }
589
590 if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId),
591 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530592 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593 "%s: Failed to send packet to txrx for staid:%d",
594 __func__, STAId);
Nirav Shahdf3659e2016-06-27 12:26:28 +0530595 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596 goto drop_pkt;
597 }
Dustin Browne0024fa2016-10-14 16:29:21 -0700598 netif_trans_update(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599
600 return NETDEV_TX_OK;
601
602drop_pkt:
603
Nirav Shahdf3659e2016-06-27 12:26:28 +0530604 if (skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530605 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shahdf3659e2016-06-27 12:26:28 +0530606 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
607 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
608 DPTRACE(qdf_dp_trace(skb,
609 QDF_DP_TRACE_DROP_PACKET_RECORD,
610 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
611 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE),
612 QDF_TX));
613
614 kfree_skb(skb);
615 }
616
617drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618
619 ++pAdapter->stats.tx_dropped;
620 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Nirav Shahdf3659e2016-06-27 12:26:28 +0530621
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622 return NETDEV_TX_OK;
623}
624
625/**
Mukul Sharmac4de4ef2016-09-12 15:39:00 +0530626 * hdd_hard_start_xmit() - Wrapper function to protect
627 * __hdd_hard_start_xmit from SSR
628 * @skb: pointer to OS packet
629 * @dev: pointer to net_device structure
630 *
631 * Function called by OS if any packet needs to transmit.
632 *
633 * Return: Always returns NETDEV_TX_OK
634 */
635int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
636{
637 int ret;
638
639 cds_ssr_protect(__func__);
640 ret = __hdd_hard_start_xmit(skb, dev);
641 cds_ssr_unprotect(__func__);
642
643 return ret;
644}
645
646/**
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -0700647 * hdd_get_peer_sta_id() - Get the StationID using the Peer Mac address
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 * @pHddStaCtx: pointer to HDD Station Context
649 * @pMacAddress: pointer to Peer Mac address
650 * @staID: pointer to returned Station Index
651 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530652 * Return: QDF_STATUS_SUCCESS/QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 */
654
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -0700655QDF_STATUS hdd_get_peer_sta_id(hdd_station_ctx_t *pHddStaCtx,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530656 struct qdf_mac_addr *pMacAddress, uint8_t *staId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657{
658 uint8_t idx;
659
Naveen Rawatc45d1622016-07-05 12:20:09 -0700660 for (idx = 0; idx < MAX_PEERS; idx++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530661 if (!qdf_mem_cmp(&pHddStaCtx->conn_info.peerMacAddress[idx],
Anurag Chouhan6d760662016-02-20 16:05:43 +0530662 pMacAddress, QDF_MAC_ADDR_SIZE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 *staId = pHddStaCtx->conn_info.staId[idx];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530664 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 }
666 }
667
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530668 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669}
670
671/**
672 * __hdd_tx_timeout() - TX timeout handler
673 * @dev: pointer to network device
674 *
675 * This function is registered as a netdev ndo_tx_timeout method, and
676 * is invoked by the kernel if the driver takes too long to transmit a
677 * frame.
678 *
679 * Return: None
680 */
681static void __hdd_tx_timeout(struct net_device *dev)
682{
Nirav Shah89223f72016-03-01 18:10:38 +0530683 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
684 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 struct netdev_queue *txq;
686 int i = 0;
687
Dustin Browne0024fa2016-10-14 16:29:21 -0700688 TX_TIMEOUT_TRACE(dev, QDF_MODULE_ID_HDD_DATA);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530689 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_TX_TIMEOUT,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530690 NULL, 0, QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691
692 /* Getting here implies we disabled the TX queues for too
693 * long. Queues are disabled either because of disassociation
694 * or low resource scenarios. In case of disassociation it is
695 * ok to ignore this. But if associated, we have do possible
696 * recovery here
697 */
698
699 for (i = 0; i < NUM_TX_QUEUES; i++) {
700 txq = netdev_get_tx_queue(dev, i);
Nirav Shah89223f72016-03-01 18:10:38 +0530701 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 "Queue%d status: %d txq->trans_start %lu",
703 i, netif_tx_queue_stopped(txq), txq->trans_start);
704 }
705
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530706 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 "carrier state: %d", netif_carrier_ok(dev));
Nirav Shah89223f72016-03-01 18:10:38 +0530708 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
709 wlan_hdd_display_netif_queue_history(hdd_ctx);
710 ol_tx_dump_flow_pool_info();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711}
712
713/**
714 * hdd_tx_timeout() - Wrapper function to protect __hdd_tx_timeout from SSR
715 * @dev: pointer to net_device structure
716 *
717 * Function called by OS if there is any timeout during transmission.
718 * Since HDD simply enqueues packet and returns control to OS right away,
719 * this would never be invoked
720 *
721 * Return: none
722 */
723void hdd_tx_timeout(struct net_device *dev)
724{
725 cds_ssr_protect(__func__);
726 __hdd_tx_timeout(dev);
727 cds_ssr_unprotect(__func__);
728}
729
730/**
731 * @hdd_init_tx_rx() - Initialize Tx/RX module
732 * @pAdapter: pointer to adapter context
733 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530734 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
735 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530737QDF_STATUS hdd_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530739 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800740
741 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530742 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743 FL("pAdapter is NULL"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530744 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530745 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800746 }
747
748 return status;
749}
750
751/**
752 * @hdd_deinit_tx_rx() - Deinitialize Tx/RX module
753 * @pAdapter: pointer to adapter context
754 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530755 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
756 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800757 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530758QDF_STATUS hdd_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530760 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761
762 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530763 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 FL("pAdapter is NULL"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530765 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 }
768
769 return status;
770}
771
772/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700773 * hdd_mon_rx_packet_cbk() - Receive callback registered with OL layer.
774 * @context: [in] pointer to qdf context
775 * @rxBuf: [in] pointer to rx qdf_nbuf
776 *
777 * TL will call this to notify the HDD when one or more packets were
778 * received for a registered STA.
779 *
780 * Return: QDF_STATUS_E_FAILURE if any errors encountered, QDF_STATUS_SUCCESS
781 * otherwise
782 */
783static QDF_STATUS hdd_mon_rx_packet_cbk(void *context, qdf_nbuf_t rxbuf)
784{
785 hdd_adapter_t *adapter;
786 int rxstat;
787 struct sk_buff *skb;
788 struct sk_buff *skb_next;
789 unsigned int cpu_index;
790
791 /* Sanity check on inputs */
792 if ((NULL == context) || (NULL == rxbuf)) {
793 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
794 "%s: Null params being passed", __func__);
795 return QDF_STATUS_E_FAILURE;
796 }
797
798 adapter = (hdd_adapter_t *)context;
799 if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
800 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
801 "invalid adapter %p", adapter);
802 return QDF_STATUS_E_FAILURE;
803 }
804
805 cpu_index = wlan_hdd_get_cpu();
806
807 /* walk the chain until all are processed */
808 skb = (struct sk_buff *) rxbuf;
809 while (NULL != skb) {
810 skb_next = skb->next;
811 skb->dev = adapter->dev;
812
813 ++adapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
814 ++adapter->stats.rx_packets;
815 adapter->stats.rx_bytes += skb->len;
816
817 /* Remove SKB from internal tracking table before submitting
818 * it to stack
819 */
820 qdf_net_buf_debug_release_skb(skb);
821
822 /*
823 * If this is not a last packet on the chain
824 * Just put packet into backlog queue, not scheduling RX sirq
825 */
826 if (skb->next) {
827 rxstat = netif_rx(skb);
828 } else {
829 /*
830 * This is the last packet on the chain
831 * Scheduling rx sirq
832 */
833 rxstat = netif_rx_ni(skb);
834 }
835
836 if (NET_RX_SUCCESS == rxstat)
837 ++adapter->
838 hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
839 else
840 ++adapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];
841
842 skb = skb_next;
843 }
844
845 adapter->dev->last_rx = jiffies;
846
847 return QDF_STATUS_SUCCESS;
848}
849
850/**
Naveen Rawatf28315c2016-06-29 18:06:02 -0700851 * hdd_get_peer_idx() - Get the idx for given address in peer table
852 * @sta_ctx: pointer to HDD Station Context
853 * @addr: pointer to Peer Mac address
854 *
855 * Return: index when success else INVALID_PEER_IDX
856 */
857int hdd_get_peer_idx(hdd_station_ctx_t *sta_ctx, struct qdf_mac_addr *addr)
858{
859 uint8_t idx;
860
Naveen Rawatc45d1622016-07-05 12:20:09 -0700861 for (idx = 0; idx < MAX_PEERS; idx++) {
Naveen Rawatf28315c2016-06-29 18:06:02 -0700862 if (sta_ctx->conn_info.staId[idx] == 0)
863 continue;
864 if (qdf_mem_cmp(&sta_ctx->conn_info.peerMacAddress[idx],
865 addr, sizeof(struct qdf_mac_addr)))
866 continue;
867 return idx;
868 }
869
870 return INVALID_PEER_IDX;
871}
872
Ravi Joshibb8d4512016-08-22 10:14:52 -0700873/*
874 * hdd_is_mcast_replay() - checks if pkt is multicast replay
875 * @skb: packet skb
876 *
877 * Return: true if replayed multicast pkt, false otherwise
878 */
879static bool hdd_is_mcast_replay(struct sk_buff *skb)
880{
881 struct ethhdr *eth;
882
883 eth = eth_hdr(skb);
884 if (unlikely(skb->pkt_type == PACKET_MULTICAST)) {
885 if (unlikely(ether_addr_equal(eth->h_source,
886 skb->dev->dev_addr)))
887 return true;
888 }
889 return false;
890}
891
Naveen Rawatf28315c2016-06-29 18:06:02 -0700892/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893 * hdd_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800894 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530895 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896 *
897 * Receive callback registered with TL. TL will call this to notify
898 * the HDD when one or more packets were received for a registered
899 * STA.
900 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530901 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
902 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800904QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800905{
906 hdd_adapter_t *pAdapter = NULL;
907 hdd_context_t *pHddCtx = NULL;
908 int rxstat;
909 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800910 hdd_station_ctx_t *pHddStaCtx = NULL;
911 unsigned int cpu_index;
912
913 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800914 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530915 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530917 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800918 }
919
Dhanashri Atre182b0272016-02-17 15:35:07 -0800920 pAdapter = (hdd_adapter_t *)context;
921 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530922 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 "Magic cookie(%x) for adapter sanity verification is invalid",
924 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530925 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926 }
927
Dhanashri Atre182b0272016-02-17 15:35:07 -0800928 pHddCtx = pAdapter->pHddCtx;
929 if (unlikely(NULL == pHddCtx)) {
930 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
931 "%s: HDD context is Null", __func__);
932 return QDF_STATUS_E_FAILURE;
933 }
934
935 cpu_index = wlan_hdd_get_cpu();
936
937 skb = (struct sk_buff *)rxBuf;
938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
940 if ((pHddStaCtx->conn_info.proxyARPService) &&
941 cfg80211_is_gratuitous_arp_unsolicited_na(skb)) {
942 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index];
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530943 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944 "%s: Dropping HS 2.0 Gratuitous ARP or Unsolicited NA",
945 __func__);
946 /* Remove SKB from internal tracking table before submitting
947 * it to stack
948 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530949 qdf_nbuf_free(skb);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530950 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800951 }
952
Nirav Shah5e74bb82016-07-20 16:01:27 +0530953 hdd_event_eapol_log(skb, QDF_RX);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530954 DPTRACE(qdf_dp_trace(rxBuf,
955 QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
956 qdf_nbuf_data_addr(rxBuf),
957 sizeof(qdf_nbuf_data(rxBuf)), QDF_RX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800958
Kabilan Kannan32eb5022016-10-04 12:24:50 -0700959 wlan_hdd_tdls_update_rx_pkt_cnt(pAdapter, skb);
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700960
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961 skb->dev = pAdapter->dev;
962 skb->protocol = eth_type_trans(skb, skb->dev);
963 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
964 ++pAdapter->stats.rx_packets;
965 pAdapter->stats.rx_bytes += skb->len;
Ravi Joshibb8d4512016-08-22 10:14:52 -0700966
967 /* Check & drop replayed mcast packets (for IPV6) */
968 if (pHddCtx->config->multicast_replay_filter &&
969 hdd_is_mcast_replay(skb)) {
970 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index];
971 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
972 "%s: Dropping multicast replay pkt", __func__);
Govind Singh3fc3f412016-09-13 18:32:18 +0530973 qdf_nbuf_free(skb);
Ravi Joshibb8d4512016-08-22 10:14:52 -0700974 return QDF_STATUS_SUCCESS;
975 }
976
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +0530978 cds_host_diag_log_work(&pHddCtx->rx_wake_lock,
979 HDD_WAKE_LOCK_DURATION,
980 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530981 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +0530982 HDD_WAKE_LOCK_DURATION);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800983#endif
984
985 /* Remove SKB from internal tracking table before submitting
986 * it to stack
987 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530988 qdf_net_buf_debug_release_skb(rxBuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989
990 if (HDD_LRO_NO_RX ==
991 hdd_lro_rx(pHddCtx, pAdapter, skb)) {
Orhan K AKYILDIZ4f20db52015-12-30 12:35:44 -0800992 if (hdd_napi_enabled(HDD_NAPI_ANY) &&
Nirav Shahbd36b062016-07-18 11:12:59 +0530993 !pHddCtx->enableRxThread)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800994 rxstat = netif_receive_skb(skb);
995 else
996 rxstat = netif_rx_ni(skb);
997
998 if (NET_RX_SUCCESS == rxstat)
999 ++pAdapter->hdd_stats.hddTxRxStats.
1000 rxDelivered[cpu_index];
1001 else
1002 ++pAdapter->hdd_stats.hddTxRxStats.
1003 rxRefused[cpu_index];
1004
1005 } else {
1006 ++pAdapter->hdd_stats.hddTxRxStats.
1007 rxDelivered[cpu_index];
1008 }
1009
1010 pAdapter->dev->last_rx = jiffies;
1011
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301012 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001013}
1014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015/**
1016 * hdd_reason_type_to_string() - return string conversion of reason type
1017 * @reason: reason type
1018 *
1019 * This utility function helps log string conversion of reason type.
1020 *
1021 * Return: string conversion of device mode, if match found;
1022 * "Unknown" otherwise.
1023 */
1024const char *hdd_reason_type_to_string(enum netif_reason_type reason)
1025{
1026 switch (reason) {
1027 CASE_RETURN_STRING(WLAN_CONTROL_PATH);
1028 CASE_RETURN_STRING(WLAN_DATA_FLOW_CONTROL);
1029 CASE_RETURN_STRING(WLAN_FW_PAUSE);
1030 CASE_RETURN_STRING(WLAN_TX_ABORT);
1031 CASE_RETURN_STRING(WLAN_VDEV_STOP);
1032 CASE_RETURN_STRING(WLAN_PEER_UNAUTHORISED);
1033 CASE_RETURN_STRING(WLAN_THERMAL_MITIGATION);
1034 default:
Nirav Shah617cff92016-04-25 10:24:24 +05301035 return "Invalid";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001036 }
1037}
1038
1039/**
1040 * hdd_action_type_to_string() - return string conversion of action type
1041 * @action: action type
1042 *
1043 * This utility function helps log string conversion of action_type.
1044 *
1045 * Return: string conversion of device mode, if match found;
1046 * "Unknown" otherwise.
1047 */
1048const char *hdd_action_type_to_string(enum netif_action_type action)
1049{
1050
1051 switch (action) {
1052 CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE);
1053 CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE);
1054 CASE_RETURN_STRING(WLAN_WAKE_ALL_NETIF_QUEUE);
1055 CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER);
1056 CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE_N_CARRIER);
1057 CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE);
1058 CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE_N_CARRIER);
1059 CASE_RETURN_STRING(WLAN_NETIF_CARRIER_ON);
1060 CASE_RETURN_STRING(WLAN_NETIF_CARRIER_OFF);
1061 default:
Nirav Shah617cff92016-04-25 10:24:24 +05301062 return "Invalid";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 }
1064}
1065
1066/**
1067 * wlan_hdd_update_queue_oper_stats - update queue operation statistics
1068 * @adapter: adapter handle
1069 * @action: action type
1070 * @reason: reason type
1071 */
1072static void wlan_hdd_update_queue_oper_stats(hdd_adapter_t *adapter,
1073 enum netif_action_type action, enum netif_reason_type reason)
1074{
1075 switch (action) {
1076 case WLAN_STOP_ALL_NETIF_QUEUE:
1077 case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER:
1078 case WLAN_NETIF_TX_DISABLE:
1079 case WLAN_NETIF_TX_DISABLE_N_CARRIER:
1080 adapter->queue_oper_stats[reason].pause_count++;
1081 break;
1082 case WLAN_START_ALL_NETIF_QUEUE:
1083 case WLAN_WAKE_ALL_NETIF_QUEUE:
1084 case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER:
1085 adapter->queue_oper_stats[reason].unpause_count++;
1086 break;
1087 default:
1088 break;
1089 }
1090
1091 return;
1092}
1093
1094/**
Nirav Shah89223f72016-03-01 18:10:38 +05301095 * wlan_hdd_update_txq_timestamp() - update txq timestamp
1096 * @dev: net device
1097 *
1098 * Return: none
1099 */
Jeff Johnson3ae708d2016-10-05 15:45:00 -07001100static void wlan_hdd_update_txq_timestamp(struct net_device *dev)
Nirav Shah89223f72016-03-01 18:10:38 +05301101{
1102 struct netdev_queue *txq;
1103 int i;
1104 bool unlock;
1105
1106 for (i = 0; i < NUM_TX_QUEUES; i++) {
1107 txq = netdev_get_tx_queue(dev, i);
1108 unlock = __netif_tx_trylock(txq);
1109 txq_trans_update(txq);
1110 if (unlock == true)
1111 __netif_tx_unlock(txq);
1112 }
1113}
1114
1115/**
Nirav Shah617cff92016-04-25 10:24:24 +05301116 * wlan_hdd_update_unpause_time() - update unpause time
1117 * @adapter: adapter handle
1118 *
1119 * Return: none
1120 */
1121static void wlan_hdd_update_unpause_time(hdd_adapter_t *adapter)
1122{
1123 qdf_time_t curr_time = qdf_system_ticks();
1124
1125 adapter->total_unpause_time += curr_time - adapter->last_time;
1126 adapter->last_time = curr_time;
1127}
1128
1129/**
1130 * wlan_hdd_update_pause_time() - update pause time
1131 * @adapter: adapter handle
1132 *
1133 * Return: none
1134 */
Nirav Shahda008342016-05-17 18:50:40 +05301135static void wlan_hdd_update_pause_time(hdd_adapter_t *adapter,
1136 uint32_t temp_map)
Nirav Shah617cff92016-04-25 10:24:24 +05301137{
1138 qdf_time_t curr_time = qdf_system_ticks();
Nirav Shahda008342016-05-17 18:50:40 +05301139 uint8_t i;
1140 qdf_time_t pause_time;
Nirav Shah617cff92016-04-25 10:24:24 +05301141
Nirav Shahda008342016-05-17 18:50:40 +05301142 pause_time = curr_time - adapter->last_time;
1143 adapter->total_pause_time += pause_time;
Nirav Shah617cff92016-04-25 10:24:24 +05301144 adapter->last_time = curr_time;
Nirav Shahda008342016-05-17 18:50:40 +05301145
1146 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
1147 if (temp_map & (1 << i)) {
1148 adapter->queue_oper_stats[i].total_pause_time +=
1149 pause_time;
1150 break;
1151 }
1152 }
1153
Nirav Shah617cff92016-04-25 10:24:24 +05301154}
1155
1156/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157 * wlan_hdd_netif_queue_control() - Use for netif_queue related actions
1158 * @adapter: adapter handle
1159 * @action: action type
1160 * @reason: reason type
1161 *
1162 * This is single function which is used for netif_queue related
1163 * actions like start/stop of network queues and on/off carrier
1164 * option.
1165 *
1166 * Return: None
1167 */
1168void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
1169 enum netif_action_type action, enum netif_reason_type reason)
1170{
Nirav Shahda008342016-05-17 18:50:40 +05301171 uint32_t temp_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001172
1173 if ((!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) ||
1174 (!adapter->dev)) {
1175 hdd_err("adapter is invalid");
1176 return;
1177 }
1178
1179 switch (action) {
1180
1181 case WLAN_NETIF_CARRIER_ON:
1182 netif_carrier_on(adapter->dev);
1183 break;
1184
1185 case WLAN_NETIF_CARRIER_OFF:
1186 netif_carrier_off(adapter->dev);
1187 break;
1188
1189 case WLAN_STOP_ALL_NETIF_QUEUE:
1190 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301191 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 netif_tx_stop_all_queues(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301193 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301194 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301195 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196 adapter->pause_map |= (1 << reason);
1197 spin_unlock_bh(&adapter->pause_map_lock);
1198 break;
1199
1200 case WLAN_START_ALL_NETIF_QUEUE:
1201 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shahda008342016-05-17 18:50:40 +05301202 temp_map = adapter->pause_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203 adapter->pause_map &= ~(1 << reason);
Nirav Shah617cff92016-04-25 10:24:24 +05301204 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205 netif_tx_start_all_queues(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301206 wlan_hdd_update_pause_time(adapter, temp_map);
Nirav Shah617cff92016-04-25 10:24:24 +05301207 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001208 spin_unlock_bh(&adapter->pause_map_lock);
1209 break;
1210
1211 case WLAN_WAKE_ALL_NETIF_QUEUE:
1212 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shahda008342016-05-17 18:50:40 +05301213 temp_map = adapter->pause_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001214 adapter->pause_map &= ~(1 << reason);
Nirav Shah617cff92016-04-25 10:24:24 +05301215 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 netif_tx_wake_all_queues(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301217 wlan_hdd_update_pause_time(adapter, temp_map);
Nirav Shah617cff92016-04-25 10:24:24 +05301218 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 spin_unlock_bh(&adapter->pause_map_lock);
1220 break;
1221
1222 case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER:
1223 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301224 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 netif_tx_stop_all_queues(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301226 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301227 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301228 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 adapter->pause_map |= (1 << reason);
1230 netif_carrier_off(adapter->dev);
1231 spin_unlock_bh(&adapter->pause_map_lock);
1232 break;
1233
1234 case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER:
1235 spin_lock_bh(&adapter->pause_map_lock);
1236 netif_carrier_on(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301237 temp_map = adapter->pause_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 adapter->pause_map &= ~(1 << reason);
Nirav Shah617cff92016-04-25 10:24:24 +05301239 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 netif_tx_start_all_queues(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301241 wlan_hdd_update_pause_time(adapter, temp_map);
Nirav Shah617cff92016-04-25 10:24:24 +05301242 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243 spin_unlock_bh(&adapter->pause_map_lock);
1244 break;
1245
1246 case WLAN_NETIF_TX_DISABLE:
1247 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301248 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 netif_tx_disable(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301250 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301251 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301252 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 adapter->pause_map |= (1 << reason);
1254 spin_unlock_bh(&adapter->pause_map_lock);
1255 break;
1256
1257 case WLAN_NETIF_TX_DISABLE_N_CARRIER:
1258 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301259 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001260 netif_tx_disable(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301261 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301262 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301263 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 adapter->pause_map |= (1 << reason);
1265 netif_carrier_off(adapter->dev);
1266 spin_unlock_bh(&adapter->pause_map_lock);
1267 break;
1268
1269 default:
1270 hdd_err("unsupported action %d", action);
1271 }
1272
1273 spin_lock_bh(&adapter->pause_map_lock);
1274 if (adapter->pause_map & (1 << WLAN_PEER_UNAUTHORISED))
1275 wlan_hdd_process_peer_unauthorised_pause(adapter);
1276 spin_unlock_bh(&adapter->pause_map_lock);
1277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001278 wlan_hdd_update_queue_oper_stats(adapter, action, reason);
1279
1280 adapter->queue_oper_history[adapter->history_index].time =
Anurag Chouhan50220ce2016-02-18 20:11:33 +05301281 qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 adapter->queue_oper_history[adapter->history_index].netif_action =
1283 action;
1284 adapter->queue_oper_history[adapter->history_index].netif_reason =
1285 reason;
1286 adapter->queue_oper_history[adapter->history_index].pause_map =
1287 adapter->pause_map;
1288 if (++adapter->history_index == WLAN_HDD_MAX_HISTORY_ENTRY)
1289 adapter->history_index = 0;
1290
1291 return;
1292}
1293
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001294/**
1295 * hdd_set_mon_rx_cb() - Set Monitor mode Rx callback
1296 * @dev: Pointer to net_device structure
1297 *
1298 * Return: 0 for success; non-zero for failure
1299 */
1300int hdd_set_mon_rx_cb(struct net_device *dev)
1301{
1302 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1303 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1304 int ret;
1305 QDF_STATUS qdf_status;
1306 struct ol_txrx_desc_type sta_desc = {0};
1307 struct ol_txrx_ops txrx_ops;
1308
1309 ret = wlan_hdd_validate_context(hdd_ctx);
1310 if (0 != ret)
1311 return ret;
1312
1313 qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
1314 txrx_ops.rx.rx = hdd_mon_rx_packet_cbk;
1315 ol_txrx_vdev_register(
1316 ol_txrx_get_vdev_from_vdev_id(adapter->sessionId),
1317 adapter, &txrx_ops);
1318 /* peer is created wma_vdev_attach->wma_create_peer */
1319 qdf_status = ol_txrx_register_peer(&sta_desc);
1320 if (QDF_STATUS_SUCCESS != qdf_status) {
1321 hdd_err("WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]",
1322 qdf_status, qdf_status);
1323 goto exit;
1324 }
1325
1326 qdf_status = sme_create_mon_session(hdd_ctx->hHal,
1327 adapter->macAddressCurrent.bytes);
1328 if (QDF_STATUS_SUCCESS != qdf_status) {
1329 hdd_err("sme_create_mon_session() failed to register. Status= %d [0x%08X]",
1330 qdf_status, qdf_status);
1331 }
1332exit:
1333 ret = qdf_status_to_os_return(qdf_status);
1334 return ret;
1335}
Nirav Shahbd36b062016-07-18 11:12:59 +05301336
1337/**
1338 * hdd_send_rps_ind() - send rps indication to daemon
1339 * @adapter: adapter context
1340 *
1341 * If RPS feature enabled by INI, send RPS enable indication to daemon
1342 * Indication contents is the name of interface to find correct sysfs node
1343 * Should send all available interfaces
1344 *
1345 * Return: none
1346 */
1347void hdd_send_rps_ind(hdd_adapter_t *adapter)
1348{
1349 int i;
1350 uint8_t cpu_map_list_len = 0;
1351 hdd_context_t *hdd_ctxt = NULL;
1352 struct wlan_rps_data rps_data;
1353
1354 if (!adapter) {
1355 hdd_err("adapter is NULL");
1356 return;
1357 }
1358
1359 hdd_ctxt = WLAN_HDD_GET_CTX(adapter);
1360 rps_data.num_queues = NUM_TX_QUEUES;
1361
1362 hdd_info("cpu_map_list '%s'", hdd_ctxt->config->cpu_map_list);
1363
1364 /* in case no cpu map list is provided, simply return */
1365 if (!strlen(hdd_ctxt->config->cpu_map_list)) {
1366 hdd_err("no cpu map list found");
1367 goto err;
1368 }
1369
1370 if (QDF_STATUS_SUCCESS !=
1371 hdd_hex_string_to_u16_array(hdd_ctxt->config->cpu_map_list,
1372 rps_data.cpu_map_list,
1373 &cpu_map_list_len,
1374 WLAN_SVC_IFACE_NUM_QUEUES)) {
1375 hdd_err("invalid cpu map list");
1376 goto err;
1377 }
1378
1379 rps_data.num_queues =
1380 (cpu_map_list_len < rps_data.num_queues) ?
1381 cpu_map_list_len : rps_data.num_queues;
1382
1383 for (i = 0; i < rps_data.num_queues; i++) {
1384 hdd_info("cpu_map_list[%d] = 0x%x",
1385 i, rps_data.cpu_map_list[i]);
1386 }
1387
1388 strlcpy(rps_data.ifname, adapter->dev->name,
1389 sizeof(rps_data.ifname));
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05301390 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
1391 WLAN_SVC_RPS_ENABLE_IND,
Nirav Shahbd36b062016-07-18 11:12:59 +05301392 &rps_data, sizeof(rps_data));
1393
1394err:
1395 hdd_err("Wrong RPS configuration. enabling rx_thread");
1396 hdd_ctxt->rps = false;
1397 hdd_ctxt->enableRxThread = true;
1398}
1399
Ravi Joshib89e7f72016-09-07 13:43:15 -07001400#ifdef MSM_PLATFORM
1401/**
1402 * hdd_reset_tcp_delack() - Reset tcp delack value to default
1403 * @hdd_ctx: Handle to hdd context
1404 *
1405 * Function used to reset TCP delack value to its default value
1406 *
1407 * Return: None
1408 */
1409void hdd_reset_tcp_delack(hdd_context_t *hdd_ctx)
1410{
1411 enum pld_bus_width_type next_level = PLD_BUS_WIDTH_LOW;
Nirav Shahbd36b062016-07-18 11:12:59 +05301412
Ravi Joshib89e7f72016-09-07 13:43:15 -07001413 hdd_ctx->rx_high_ind_cnt = 0;
1414 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index, WLAN_SVC_WLAN_TP_IND,
1415 &next_level, sizeof(next_level));
1416}
1417#endif /* MSM_PLATFORM */