blob: 0ce649b5149e5b2e5956bb926489bfcf505cfa1c [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"
50
51#ifdef FEATURE_WLAN_TDLS
52#include "wlan_hdd_tdls.h"
53#endif
54#include <wlan_hdd_ipa.h>
55
56#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080057#include "wlan_hdd_lro.h"
58
Dhanashri Atreb08959a2016-03-01 17:28:03 -080059#include "cdp_txrx_peer_ops.h"
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070060#include "ol_txrx.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080061
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -070062#include "wlan_hdd_nan_datapath.h"
63
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080064const uint8_t hdd_wmm_ac_to_highest_up[] = {
65 SME_QOS_WMM_UP_RESV,
66 SME_QOS_WMM_UP_EE,
67 SME_QOS_WMM_UP_VI,
68 SME_QOS_WMM_UP_NC
69};
70
71/* Mapping Linux AC interpretation to SME AC. */
72const uint8_t hdd_qdisc_ac_to_tl_ac[] = {
73 SME_AC_VO,
74 SME_AC_VI,
75 SME_AC_BE,
76 SME_AC_BK,
77};
78
79#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
80/**
81 * hdd_tx_resume_timer_expired_handler() - TX Q resume timer handler
82 * @adapter_context: pointer to vdev adapter
83 *
84 * If Blocked OS Q is not resumed during timeout period, to prevent
85 * permanent stall, resume OS Q forcefully.
86 *
87 * Return: None
88 */
89void hdd_tx_resume_timer_expired_handler(void *adapter_context)
90{
91 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
92
93 if (!pAdapter) {
94 /* INVALID ARG */
95 return;
96 }
97
98 hddLog(LOG1, FL("Enabling queues"));
99 wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE,
100 WLAN_CONTROL_PATH);
101 return;
102}
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530103#if defined(CONFIG_PER_VDEV_TX_DESC_POOL)
104
105/**
106 * hdd_tx_resume_false() - Resume OS TX Q false leads to queue disabling
107 * @pAdapter: pointer to hdd adapter
108 * @tx_resume: TX Q resume trigger
109 *
110 *
111 * Return: None
112 */
113static void
114hdd_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
115{
116 if (true == tx_resume)
117 return;
118
119 /* Pause TX */
120 hdd_notice("Disabling queues");
121 wlan_hdd_netif_queue_control(pAdapter, WLAN_STOP_ALL_NETIF_QUEUE,
122 WLAN_DATA_FLOW_CONTROL);
123
124 if (QDF_TIMER_STATE_STOPPED ==
125 qdf_mc_timer_get_current_state(&pAdapter->
126 tx_flow_control_timer)) {
127 QDF_STATUS status;
128 status = qdf_mc_timer_start(&pAdapter->tx_flow_control_timer,
129 WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
130
131 if (!QDF_IS_STATUS_SUCCESS(status))
132 hdd_err("Failed to start tx_flow_control_timer");
133 else
134 pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++;
135 }
136
137 pAdapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++;
138 pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = true;
139
140 return;
141}
142#else
143
144static inline void
145hdd_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
146{
147 return;
148}
149#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150
151/**
152 * hdd_tx_resume_cb() - Resume OS TX Q.
153 * @adapter_context: pointer to vdev apdapter
154 * @tx_resume: TX Q resume trigger
155 *
156 * Q was stopped due to WLAN TX path low resource condition
157 *
158 * Return: None
159 */
160void hdd_tx_resume_cb(void *adapter_context, bool tx_resume)
161{
162 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
163 hdd_station_ctx_t *hdd_sta_ctx = NULL;
164
165 if (!pAdapter) {
166 /* INVALID ARG */
167 return;
168 }
169
170 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
171
172 /* Resume TX */
173 if (true == tx_resume) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530174 if (QDF_TIMER_STATE_STOPPED !=
175 qdf_mc_timer_get_current_state(&pAdapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176 tx_flow_control_timer)) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530177 qdf_mc_timer_stop(&pAdapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 }
Anurag Chouhanc5548422016-02-24 18:33:27 +0530179 if (qdf_unlikely(hdd_sta_ctx->hdd_ReassocScenario)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 hddLog(LOGW,
181 FL("flow control, tx queues un-pause avoided as we are in REASSOCIATING state"));
182 return;
183 }
184 hddLog(LOG1, FL("Enabling queues"));
185 wlan_hdd_netif_queue_control(pAdapter,
186 WLAN_WAKE_ALL_NETIF_QUEUE,
187 WLAN_DATA_FLOW_CONTROL);
188 }
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530189 hdd_tx_resume_false(pAdapter, tx_resume);
190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191 return;
192}
193
194/**
195 * hdd_register_tx_flow_control() - Register TX Flow control
196 * @adapter: adapter handle
197 * @timer_callback: timer callback
198 * @flow_control_fp: txrx flow control
199 *
200 * Return: none
201 */
202void hdd_register_tx_flow_control(hdd_adapter_t *adapter,
Anurag Chouhan210db072016-02-22 18:42:15 +0530203 qdf_mc_timer_callback_t timer_callback,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204 ol_txrx_tx_flow_control_fp flow_control_fp)
205{
206 if (adapter->tx_flow_timer_initialized == false) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530207 qdf_mc_timer_init(&adapter->tx_flow_control_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530208 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 timer_callback,
210 adapter);
211 adapter->tx_flow_timer_initialized = true;
212 }
213 ol_txrx_register_tx_flow_control(adapter->sessionId,
214 flow_control_fp,
215 adapter);
216
217}
218
219/**
220 * hdd_deregister_tx_flow_control() - Deregister TX Flow control
221 * @adapter: adapter handle
222 *
223 * Return: none
224 */
225void hdd_deregister_tx_flow_control(hdd_adapter_t *adapter)
226{
227 ol_txrx_deregister_tx_flow_control_cb(adapter->sessionId);
228 if (adapter->tx_flow_timer_initialized == true) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530229 qdf_mc_timer_stop(&adapter->tx_flow_control_timer);
230 qdf_mc_timer_destroy(&adapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 adapter->tx_flow_timer_initialized = false;
232 }
233}
234
235/**
236 * hdd_get_tx_resource() - check tx resources and take action
237 * @adapter: adapter handle
238 * @STAId: station id
239 * @timer_value: timer value
240 *
241 * Return: none
242 */
243void hdd_get_tx_resource(hdd_adapter_t *adapter,
244 uint8_t STAId, uint16_t timer_value)
245{
246 if (false ==
247 ol_txrx_get_tx_resource(STAId,
248 adapter->tx_flow_low_watermark,
249 adapter->tx_flow_high_watermark_offset)) {
250 hdd_info("Disabling queues lwm %d hwm offset %d",
251 adapter->tx_flow_low_watermark,
252 adapter->tx_flow_high_watermark_offset);
253 wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE,
254 WLAN_DATA_FLOW_CONTROL);
255 if ((adapter->tx_flow_timer_initialized == true) &&
Anurag Chouhan210db072016-02-22 18:42:15 +0530256 (QDF_TIMER_STATE_STOPPED ==
257 qdf_mc_timer_get_current_state(&adapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800258 tx_flow_control_timer))) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530259 qdf_mc_timer_start(&adapter->tx_flow_control_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 timer_value);
261 adapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++;
262 adapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++;
263 adapter->hdd_stats.hddTxRxStats.is_txflow_paused = true;
264 }
265 }
266}
267
268#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
269
Nirav Shah5e74bb82016-07-20 16:01:27 +0530270/**
271 * qdf_event_eapol_log() - send event to wlan diag
272 * @skb: skb ptr
273 * @dir: direction
274 * @eapol_key_info: eapol key info
275 *
276 * Return: None
277 */
278void hdd_event_eapol_log(struct sk_buff *skb, enum qdf_proto_dir dir)
279{
280 int16_t eapol_key_info;
281
282 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct host_event_wlan_eapol);
283
284 if ((dir == QDF_TX &&
285 (QDF_NBUF_CB_PACKET_TYPE_EAPOL !=
286 QDF_NBUF_CB_GET_PACKET_TYPE(skb))))
287 return;
288 else if (!qdf_nbuf_is_ipv4_eapol_pkt(skb))
289 return;
290
291 eapol_key_info = (uint16_t)(*(uint16_t *)
292 (skb->data + EAPOL_KEY_INFO_OFFSET));
293
294 wlan_diag_event.event_sub_type =
295 (dir == QDF_TX ?
296 WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED :
297 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
298 wlan_diag_event.eapol_packet_type = (uint8_t)(*(uint8_t *)
299 (skb->data + EAPOL_PACKET_TYPE_OFFSET));
300 wlan_diag_event.eapol_key_info = eapol_key_info;
301 wlan_diag_event.eapol_rate = 0;
302 qdf_mem_copy(wlan_diag_event.dest_addr,
303 (skb->data + QDF_NBUF_DEST_MAC_OFFSET),
304 sizeof(wlan_diag_event.dest_addr));
305 qdf_mem_copy(wlan_diag_event.src_addr,
306 (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
307 sizeof(wlan_diag_event.src_addr));
308
309 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL);
310}
311
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800312
313/**
Nirav Shah5e74bb82016-07-20 16:01:27 +0530314 * wlan_hdd_classify_pkt() - classify packet
315 * @skb - sk buff
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316 *
Nirav Shah5e74bb82016-07-20 16:01:27 +0530317 * Return: none
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318 */
Nirav Shah5e74bb82016-07-20 16:01:27 +0530319void wlan_hdd_classify_pkt(struct sk_buff *skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800320{
Nirav Shah5e74bb82016-07-20 16:01:27 +0530321 struct ethhdr *eh = (struct ethhdr *)skb->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322
Nirav Shah5e74bb82016-07-20 16:01:27 +0530323 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324
Nirav Shah5e74bb82016-07-20 16:01:27 +0530325 /* check destination mac address is broadcast/multicast */
326 if (is_broadcast_ether_addr((uint8_t *)eh))
327 QDF_NBUF_CB_GET_IS_BCAST(skb) = true;
328 else if (is_multicast_ether_addr((uint8_t *)eh))
329 QDF_NBUF_CB_GET_IS_MCAST(skb) = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800330
Nirav Shah5e74bb82016-07-20 16:01:27 +0530331 if (qdf_nbuf_is_ipv4_arp_pkt(skb))
332 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
333 QDF_NBUF_CB_PACKET_TYPE_ARP;
334 else if (qdf_nbuf_is_ipv4_dhcp_pkt(skb))
335 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
336 QDF_NBUF_CB_PACKET_TYPE_DHCP;
337 else if (qdf_nbuf_is_ipv4_eapol_pkt(skb))
338 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
339 QDF_NBUF_CB_PACKET_TYPE_EAPOL;
340 else if (qdf_nbuf_is_ipv4_wapi_pkt(skb))
341 QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
342 QDF_NBUF_CB_PACKET_TYPE_WAPI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800344}
345
346/**
Ravi Joshi24477b72016-07-19 15:45:09 -0700347 * hdd_get_transmit_sta_id() - function to retrieve station id to be used for
348 * sending traffic towards a particular destination address. The destination
349 * address can be unicast, multicast or broadcast
350 *
351 * @adapter: Handle to adapter context
352 * @dst_addr: Destination address
353 * @station_id: station id
354 *
355 * Returns: None
356 */
357static void hdd_get_transmit_sta_id(hdd_adapter_t *adapter,
Nirav Shah5e74bb82016-07-20 16:01:27 +0530358 struct sk_buff *skb, uint8_t *station_id)
Ravi Joshi24477b72016-07-19 15:45:09 -0700359{
360 bool mcbc_addr = false;
361 hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Nirav Shah5e74bb82016-07-20 16:01:27 +0530362 struct qdf_mac_addr *dst_addr = NULL;
Ravi Joshi24477b72016-07-19 15:45:09 -0700363
Nirav Shah5e74bb82016-07-20 16:01:27 +0530364 dst_addr = (struct qdf_mac_addr *)skb->data;
Ravi Joshi24477b72016-07-19 15:45:09 -0700365 hdd_get_peer_sta_id(sta_ctx, dst_addr, station_id);
366 if (*station_id == HDD_WLAN_INVALID_STA_ID) {
Nirav Shah5e74bb82016-07-20 16:01:27 +0530367 if (QDF_NBUF_CB_GET_IS_BCAST(skb) ||
368 QDF_NBUF_CB_GET_IS_MCAST(skb)) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700369 hdd_info("Received MC/BC packet for transmission");
370 mcbc_addr = true;
Ravi Joshi24477b72016-07-19 15:45:09 -0700371 }
372 }
373
Rakesh Sunkicf1c9ab2016-08-25 14:11:25 -0700374 if (adapter->device_mode == QDF_IBSS_MODE ||
375 adapter->device_mode == QDF_NDI_MODE) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700376 /*
377 * This check is necessary to make sure station id is not
Rakesh Sunkicf1c9ab2016-08-25 14:11:25 -0700378 * overwritten for UC traffic in IBSS or NDI mode
Ravi Joshi24477b72016-07-19 15:45:09 -0700379 */
380 if (mcbc_addr)
Rakesh Sunkicf1c9ab2016-08-25 14:11:25 -0700381 *station_id = sta_ctx->broadcast_staid;
Ravi Joshi24477b72016-07-19 15:45:09 -0700382 } else {
383 /* For the rest, traffic is directed to AP/P2P GO */
384 if (eConnectionState_Associated == sta_ctx->conn_info.connState)
385 *station_id = sta_ctx->conn_info.staId[0];
386 }
387}
388
389/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 * hdd_hard_start_xmit() - Transmit a frame
391 * @skb: pointer to OS packet (sk_buff)
392 * @dev: pointer to network device
393 *
394 * Function registered with the Linux OS for transmitting
395 * packets. This version of the function directly passes
396 * the packet to Transport Layer.
397 *
398 * Return: Always returns NETDEV_TX_OK
399 */
400int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
401{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530402 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800403 sme_ac_enum_type ac;
404 sme_QosWmmUpType up;
405 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
406 bool granted;
Nirav Shah5e74bb82016-07-20 16:01:27 +0530407 uint8_t STAId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700409#ifdef QCA_PKT_PROTO_TRACE
410 uint8_t proto_type = 0;
411#endif /* QCA_PKT_PROTO_TRACE */
412 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413
414#ifdef QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +0530415 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800416 kfree_skb(skb);
417 return NETDEV_TX_OK;
418 }
419#endif
420
421 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800422 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530423 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800424 "Recovery in progress, dropping the packet");
Nirav Shahdf3659e2016-06-27 12:26:28 +0530425 goto drop_pkt;
Govind Singhede435f2015-12-01 16:16:36 +0530426 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800427
Nirav Shah5e74bb82016-07-20 16:01:27 +0530428 wlan_hdd_classify_pkt(skb);
429
Ravi Joshi24477b72016-07-19 15:45:09 -0700430 STAId = HDD_WLAN_INVALID_STA_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431
Nirav Shah5e74bb82016-07-20 16:01:27 +0530432 hdd_get_transmit_sta_id(pAdapter, skb, &STAId);
Naveen Rawat209d0932016-08-03 15:07:23 -0700433 if (STAId >= WLAN_MAX_STA_COUNT) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700434 hddLog(LOGE, "Invalid station id, transmit operation suspended");
435 goto drop_pkt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800436 }
437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800438 hdd_get_tx_resource(pAdapter, STAId,
439 WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
440
441 /* Get TL AC corresponding to Qdisc queue index/AC. */
442 ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
443
Nirav Shahcbc6d722016-03-01 16:24:53 +0530444 if (!qdf_nbuf_ipa_owned_get(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800445 /* Check if the buffer has enough header room */
446 skb = skb_unshare(skb, GFP_ATOMIC);
447 if (!skb)
Nirav Shahdf3659e2016-06-27 12:26:28 +0530448 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800449 }
450
Ravi Joshi24477b72016-07-19 15:45:09 -0700451 /*
452 * user priority from IP header, which is already extracted and set from
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800453 * select_queue call back function
454 */
455 up = skb->priority;
456
457 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
458#ifdef HDD_WMM_DEBUG
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530459 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460 "%s: Classified as ac %d up %d", __func__, ac, up);
461#endif /* HDD_WMM_DEBUG */
462
463 if (HDD_PSB_CHANGED == pAdapter->psbChanged) {
Ravi Joshi24477b72016-07-19 15:45:09 -0700464 /*
465 * Function which will determine acquire admittance for a
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466 * WMM AC is required or not based on psb configuration done
467 * in the framework
468 */
469 hdd_wmm_acquire_access_required(pAdapter, ac);
470 }
471 /*
472 * Make sure we already have access to this access category
473 * or it is EAPOL or WAPI frame during initial authentication which
474 * can have artifically boosted higher qos priority.
475 */
476
477 if (((pAdapter->psbChanged & (1 << ac)) &&
478 likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].
479 wmmAcAccessAllowed)) ||
480 ((pHddStaCtx->conn_info.uIsAuthenticated == false) &&
Nirav Shah5e74bb82016-07-20 16:01:27 +0530481 (QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
482 QDF_NBUF_CB_GET_PACKET_TYPE(skb) ||
483 QDF_NBUF_CB_PACKET_TYPE_WAPI ==
484 QDF_NBUF_CB_GET_PACKET_TYPE(skb)))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485 granted = true;
486 } else {
487 status = hdd_wmm_acquire_access(pAdapter, ac, &granted);
488 pAdapter->psbChanged |= (1 << ac);
489 }
490
491 if (!granted) {
492 bool isDefaultAc = false;
Ravi Joshi24477b72016-07-19 15:45:09 -0700493 /*
494 * ADDTS request for this AC is sent, for now
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 * send this packet through next avaiable lower
496 * Access category until ADDTS negotiation completes.
497 */
498 while (!likely
499 (pAdapter->hddWmmStatus.wmmAcStatus[ac].
500 wmmAcAccessAllowed)) {
501 switch (ac) {
502 case SME_AC_VO:
503 ac = SME_AC_VI;
504 up = SME_QOS_WMM_UP_VI;
505 break;
506 case SME_AC_VI:
507 ac = SME_AC_BE;
508 up = SME_QOS_WMM_UP_BE;
509 break;
510 case SME_AC_BE:
511 ac = SME_AC_BK;
512 up = SME_QOS_WMM_UP_BK;
513 break;
514 default:
515 ac = SME_AC_BK;
516 up = SME_QOS_WMM_UP_BK;
517 isDefaultAc = true;
518 break;
519 }
520 if (isDefaultAc)
521 break;
522 }
523 skb->priority = up;
524 skb->queue_mapping = hdd_linux_up_to_ac_map[up];
525 }
526
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700527#ifdef QCA_PKT_PROTO_TRACE
528 if ((hdd_ctx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
529 (hdd_ctx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
530 proto_type = cds_pkt_get_proto_type(skb,
531 hdd_ctx->config->gEnableDebugLog,
532 0);
533 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
534 cds_pkt_trace_buf_update("ST:T:EPL");
535 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
536 cds_pkt_trace_buf_update("ST:T:DHC");
537 }
538 }
539#endif /* QCA_PKT_PROTO_TRACE */
540
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 pAdapter->stats.tx_bytes += skb->len;
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700542
543 if (hdd_ctx->enable_tdls_connection_tracker)
544 wlan_hdd_tdls_update_tx_pkt_cnt(pAdapter, skb);
545
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546 ++pAdapter->stats.tx_packets;
547
Nirav Shah5e74bb82016-07-20 16:01:27 +0530548 hdd_event_eapol_log(skb, QDF_TX);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530549 qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530550 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
551 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530553 qdf_dp_trace_set_track(skb, QDF_TX);
554 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
555 (uint8_t *)&skb->data, sizeof(skb->data), QDF_TX));
556 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
557 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shah07e39a62016-04-25 17:46:40 +0530558 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE) {
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530559 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
560 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
561 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Nirav Shah07e39a62016-04-25 17:46:40 +0530562 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800564 /* Check if station is connected */
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800565 if (OL_TXRX_PEER_STATE_CONN ==
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800566 pAdapter->aStaInfo[STAId].tlSTAState) {
567 QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
568 QDF_TRACE_LEVEL_WARN,
569 "%s: station is not connected..dropping pkt",
570 __func__);
Nirav Shahdf3659e2016-06-27 12:26:28 +0530571 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
572 goto drop_pkt;
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800573 }
574
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800575 /*
Ravi Joshi24477b72016-07-19 15:45:09 -0700576 * If a transmit function is not registered, drop packet
577 */
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800578 if (!pAdapter->tx_fn) {
579 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
580 "%s: TX function not registered by the data path",
581 __func__);
Nirav Shahdf3659e2016-06-27 12:26:28 +0530582 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800583 goto drop_pkt;
584 }
585
586 if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId),
587 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530588 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589 "%s: Failed to send packet to txrx for staid:%d",
590 __func__, STAId);
Nirav Shahdf3659e2016-06-27 12:26:28 +0530591 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592 goto drop_pkt;
593 }
594 dev->trans_start = jiffies;
595
596 return NETDEV_TX_OK;
597
598drop_pkt:
599
Nirav Shahdf3659e2016-06-27 12:26:28 +0530600 if (skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530601 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shahdf3659e2016-06-27 12:26:28 +0530602 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
603 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
604 DPTRACE(qdf_dp_trace(skb,
605 QDF_DP_TRACE_DROP_PACKET_RECORD,
606 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
607 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE),
608 QDF_TX));
609
610 kfree_skb(skb);
611 }
612
613drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800614
615 ++pAdapter->stats.tx_dropped;
616 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Nirav Shahdf3659e2016-06-27 12:26:28 +0530617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618 return NETDEV_TX_OK;
619}
620
621/**
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -0700622 * hdd_get_peer_sta_id() - Get the StationID using the Peer Mac address
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623 * @pHddStaCtx: pointer to HDD Station Context
624 * @pMacAddress: pointer to Peer Mac address
625 * @staID: pointer to returned Station Index
626 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530627 * Return: QDF_STATUS_SUCCESS/QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628 */
629
Deepak Dhamdhere5872c8c2016-06-02 15:51:47 -0700630QDF_STATUS hdd_get_peer_sta_id(hdd_station_ctx_t *pHddStaCtx,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530631 struct qdf_mac_addr *pMacAddress, uint8_t *staId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632{
633 uint8_t idx;
634
Naveen Rawatc45d1622016-07-05 12:20:09 -0700635 for (idx = 0; idx < MAX_PEERS; idx++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530636 if (!qdf_mem_cmp(&pHddStaCtx->conn_info.peerMacAddress[idx],
Anurag Chouhan6d760662016-02-20 16:05:43 +0530637 pMacAddress, QDF_MAC_ADDR_SIZE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 *staId = pHddStaCtx->conn_info.staId[idx];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530639 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640 }
641 }
642
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530643 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800644}
645
646/**
647 * __hdd_tx_timeout() - TX timeout handler
648 * @dev: pointer to network device
649 *
650 * This function is registered as a netdev ndo_tx_timeout method, and
651 * is invoked by the kernel if the driver takes too long to transmit a
652 * frame.
653 *
654 * Return: None
655 */
656static void __hdd_tx_timeout(struct net_device *dev)
657{
Nirav Shah89223f72016-03-01 18:10:38 +0530658 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
659 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660 struct netdev_queue *txq;
661 int i = 0;
662
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530663 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 "%s: Transmission timeout occurred jiffies %lu trans_start %lu",
665 __func__, jiffies, dev->trans_start);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530666 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_TX_TIMEOUT,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530667 NULL, 0, QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668
669 /* Getting here implies we disabled the TX queues for too
670 * long. Queues are disabled either because of disassociation
671 * or low resource scenarios. In case of disassociation it is
672 * ok to ignore this. But if associated, we have do possible
673 * recovery here
674 */
675
676 for (i = 0; i < NUM_TX_QUEUES; i++) {
677 txq = netdev_get_tx_queue(dev, i);
Nirav Shah89223f72016-03-01 18:10:38 +0530678 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 "Queue%d status: %d txq->trans_start %lu",
680 i, netif_tx_queue_stopped(txq), txq->trans_start);
681 }
682
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530683 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 "carrier state: %d", netif_carrier_ok(dev));
Nirav Shah89223f72016-03-01 18:10:38 +0530685 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
686 wlan_hdd_display_netif_queue_history(hdd_ctx);
687 ol_tx_dump_flow_pool_info();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688}
689
690/**
691 * hdd_tx_timeout() - Wrapper function to protect __hdd_tx_timeout from SSR
692 * @dev: pointer to net_device structure
693 *
694 * Function called by OS if there is any timeout during transmission.
695 * Since HDD simply enqueues packet and returns control to OS right away,
696 * this would never be invoked
697 *
698 * Return: none
699 */
700void hdd_tx_timeout(struct net_device *dev)
701{
702 cds_ssr_protect(__func__);
703 __hdd_tx_timeout(dev);
704 cds_ssr_unprotect(__func__);
705}
706
707/**
708 * @hdd_init_tx_rx() - Initialize Tx/RX module
709 * @pAdapter: pointer to adapter context
710 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530711 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
712 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530714QDF_STATUS hdd_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530716 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717
718 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530719 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720 FL("pAdapter is NULL"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530721 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530722 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800723 }
724
725 return status;
726}
727
728/**
729 * @hdd_deinit_tx_rx() - Deinitialize Tx/RX module
730 * @pAdapter: pointer to adapter context
731 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530732 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
733 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800734 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530735QDF_STATUS hdd_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530737 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738
739 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530740 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800741 FL("pAdapter is NULL"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530742 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530743 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744 }
745
746 return status;
747}
748
749/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700750 * hdd_mon_rx_packet_cbk() - Receive callback registered with OL layer.
751 * @context: [in] pointer to qdf context
752 * @rxBuf: [in] pointer to rx qdf_nbuf
753 *
754 * TL will call this to notify the HDD when one or more packets were
755 * received for a registered STA.
756 *
757 * Return: QDF_STATUS_E_FAILURE if any errors encountered, QDF_STATUS_SUCCESS
758 * otherwise
759 */
760static QDF_STATUS hdd_mon_rx_packet_cbk(void *context, qdf_nbuf_t rxbuf)
761{
762 hdd_adapter_t *adapter;
763 int rxstat;
764 struct sk_buff *skb;
765 struct sk_buff *skb_next;
766 unsigned int cpu_index;
767
768 /* Sanity check on inputs */
769 if ((NULL == context) || (NULL == rxbuf)) {
770 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
771 "%s: Null params being passed", __func__);
772 return QDF_STATUS_E_FAILURE;
773 }
774
775 adapter = (hdd_adapter_t *)context;
776 if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
777 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
778 "invalid adapter %p", adapter);
779 return QDF_STATUS_E_FAILURE;
780 }
781
782 cpu_index = wlan_hdd_get_cpu();
783
784 /* walk the chain until all are processed */
785 skb = (struct sk_buff *) rxbuf;
786 while (NULL != skb) {
787 skb_next = skb->next;
788 skb->dev = adapter->dev;
789
790 ++adapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
791 ++adapter->stats.rx_packets;
792 adapter->stats.rx_bytes += skb->len;
793
794 /* Remove SKB from internal tracking table before submitting
795 * it to stack
796 */
797 qdf_net_buf_debug_release_skb(skb);
798
799 /*
800 * If this is not a last packet on the chain
801 * Just put packet into backlog queue, not scheduling RX sirq
802 */
803 if (skb->next) {
804 rxstat = netif_rx(skb);
805 } else {
806 /*
807 * This is the last packet on the chain
808 * Scheduling rx sirq
809 */
810 rxstat = netif_rx_ni(skb);
811 }
812
813 if (NET_RX_SUCCESS == rxstat)
814 ++adapter->
815 hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
816 else
817 ++adapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];
818
819 skb = skb_next;
820 }
821
822 adapter->dev->last_rx = jiffies;
823
824 return QDF_STATUS_SUCCESS;
825}
826
827/**
Naveen Rawatf28315c2016-06-29 18:06:02 -0700828 * hdd_get_peer_idx() - Get the idx for given address in peer table
829 * @sta_ctx: pointer to HDD Station Context
830 * @addr: pointer to Peer Mac address
831 *
832 * Return: index when success else INVALID_PEER_IDX
833 */
834int hdd_get_peer_idx(hdd_station_ctx_t *sta_ctx, struct qdf_mac_addr *addr)
835{
836 uint8_t idx;
837
Naveen Rawatc45d1622016-07-05 12:20:09 -0700838 for (idx = 0; idx < MAX_PEERS; idx++) {
Naveen Rawatf28315c2016-06-29 18:06:02 -0700839 if (sta_ctx->conn_info.staId[idx] == 0)
840 continue;
841 if (qdf_mem_cmp(&sta_ctx->conn_info.peerMacAddress[idx],
842 addr, sizeof(struct qdf_mac_addr)))
843 continue;
844 return idx;
845 }
846
847 return INVALID_PEER_IDX;
848}
849
Ravi Joshibb8d4512016-08-22 10:14:52 -0700850/*
851 * hdd_is_mcast_replay() - checks if pkt is multicast replay
852 * @skb: packet skb
853 *
854 * Return: true if replayed multicast pkt, false otherwise
855 */
856static bool hdd_is_mcast_replay(struct sk_buff *skb)
857{
858 struct ethhdr *eth;
859
860 eth = eth_hdr(skb);
861 if (unlikely(skb->pkt_type == PACKET_MULTICAST)) {
862 if (unlikely(ether_addr_equal(eth->h_source,
863 skb->dev->dev_addr)))
864 return true;
865 }
866 return false;
867}
868
Naveen Rawatf28315c2016-06-29 18:06:02 -0700869/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800870 * hdd_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800871 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530872 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 *
874 * Receive callback registered with TL. TL will call this to notify
875 * the HDD when one or more packets were received for a registered
876 * STA.
877 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530878 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
879 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800880 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800881QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882{
883 hdd_adapter_t *pAdapter = NULL;
884 hdd_context_t *pHddCtx = NULL;
885 int rxstat;
886 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800887 hdd_station_ctx_t *pHddStaCtx = NULL;
888 unsigned int cpu_index;
889
890 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800891 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530892 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530894 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800895 }
896
Dhanashri Atre182b0272016-02-17 15:35:07 -0800897 pAdapter = (hdd_adapter_t *)context;
898 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530899 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900 "Magic cookie(%x) for adapter sanity verification is invalid",
901 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530902 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903 }
904
Dhanashri Atre182b0272016-02-17 15:35:07 -0800905 pHddCtx = pAdapter->pHddCtx;
906 if (unlikely(NULL == pHddCtx)) {
907 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
908 "%s: HDD context is Null", __func__);
909 return QDF_STATUS_E_FAILURE;
910 }
911
912 cpu_index = wlan_hdd_get_cpu();
913
914 skb = (struct sk_buff *)rxBuf;
915
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
917 if ((pHddStaCtx->conn_info.proxyARPService) &&
918 cfg80211_is_gratuitous_arp_unsolicited_na(skb)) {
919 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index];
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530920 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921 "%s: Dropping HS 2.0 Gratuitous ARP or Unsolicited NA",
922 __func__);
923 /* Remove SKB from internal tracking table before submitting
924 * it to stack
925 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530926 qdf_nbuf_free(skb);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530927 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800928 }
929
Nirav Shah5e74bb82016-07-20 16:01:27 +0530930 hdd_event_eapol_log(skb, QDF_RX);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530931 DPTRACE(qdf_dp_trace(rxBuf,
932 QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
933 qdf_nbuf_data_addr(rxBuf),
934 sizeof(qdf_nbuf_data(rxBuf)), QDF_RX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800935
Kabilan Kannan36090ce2016-05-03 19:28:44 -0700936 if (pHddCtx->enable_tdls_connection_tracker)
937 wlan_hdd_tdls_update_rx_pkt_cnt(pAdapter, skb);
938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 skb->dev = pAdapter->dev;
940 skb->protocol = eth_type_trans(skb, skb->dev);
941 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
942 ++pAdapter->stats.rx_packets;
943 pAdapter->stats.rx_bytes += skb->len;
Ravi Joshibb8d4512016-08-22 10:14:52 -0700944
945 /* Check & drop replayed mcast packets (for IPV6) */
946 if (pHddCtx->config->multicast_replay_filter &&
947 hdd_is_mcast_replay(skb)) {
948 ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index];
949 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
950 "%s: Dropping multicast replay pkt", __func__);
951 kfree_skb(skb);
952 return QDF_STATUS_SUCCESS;
953 }
954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +0530956 cds_host_diag_log_work(&pHddCtx->rx_wake_lock,
957 HDD_WAKE_LOCK_DURATION,
958 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530959 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +0530960 HDD_WAKE_LOCK_DURATION);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961#endif
962
963 /* Remove SKB from internal tracking table before submitting
964 * it to stack
965 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530966 qdf_net_buf_debug_release_skb(rxBuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967
968 if (HDD_LRO_NO_RX ==
969 hdd_lro_rx(pHddCtx, pAdapter, skb)) {
Orhan K AKYILDIZ4f20db52015-12-30 12:35:44 -0800970 if (hdd_napi_enabled(HDD_NAPI_ANY) &&
Nirav Shahbd36b062016-07-18 11:12:59 +0530971 !pHddCtx->enableRxThread)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972 rxstat = netif_receive_skb(skb);
973 else
974 rxstat = netif_rx_ni(skb);
975
976 if (NET_RX_SUCCESS == rxstat)
977 ++pAdapter->hdd_stats.hddTxRxStats.
978 rxDelivered[cpu_index];
979 else
980 ++pAdapter->hdd_stats.hddTxRxStats.
981 rxRefused[cpu_index];
982
983 } else {
984 ++pAdapter->hdd_stats.hddTxRxStats.
985 rxDelivered[cpu_index];
986 }
987
988 pAdapter->dev->last_rx = jiffies;
989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530990 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991}
992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993/**
994 * hdd_reason_type_to_string() - return string conversion of reason type
995 * @reason: reason type
996 *
997 * This utility function helps log string conversion of reason type.
998 *
999 * Return: string conversion of device mode, if match found;
1000 * "Unknown" otherwise.
1001 */
1002const char *hdd_reason_type_to_string(enum netif_reason_type reason)
1003{
1004 switch (reason) {
1005 CASE_RETURN_STRING(WLAN_CONTROL_PATH);
1006 CASE_RETURN_STRING(WLAN_DATA_FLOW_CONTROL);
1007 CASE_RETURN_STRING(WLAN_FW_PAUSE);
1008 CASE_RETURN_STRING(WLAN_TX_ABORT);
1009 CASE_RETURN_STRING(WLAN_VDEV_STOP);
1010 CASE_RETURN_STRING(WLAN_PEER_UNAUTHORISED);
1011 CASE_RETURN_STRING(WLAN_THERMAL_MITIGATION);
1012 default:
Nirav Shah617cff92016-04-25 10:24:24 +05301013 return "Invalid";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001014 }
1015}
1016
1017/**
1018 * hdd_action_type_to_string() - return string conversion of action type
1019 * @action: action type
1020 *
1021 * This utility function helps log string conversion of action_type.
1022 *
1023 * Return: string conversion of device mode, if match found;
1024 * "Unknown" otherwise.
1025 */
1026const char *hdd_action_type_to_string(enum netif_action_type action)
1027{
1028
1029 switch (action) {
1030 CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE);
1031 CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE);
1032 CASE_RETURN_STRING(WLAN_WAKE_ALL_NETIF_QUEUE);
1033 CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER);
1034 CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE_N_CARRIER);
1035 CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE);
1036 CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE_N_CARRIER);
1037 CASE_RETURN_STRING(WLAN_NETIF_CARRIER_ON);
1038 CASE_RETURN_STRING(WLAN_NETIF_CARRIER_OFF);
1039 default:
Nirav Shah617cff92016-04-25 10:24:24 +05301040 return "Invalid";
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001041 }
1042}
1043
1044/**
1045 * wlan_hdd_update_queue_oper_stats - update queue operation statistics
1046 * @adapter: adapter handle
1047 * @action: action type
1048 * @reason: reason type
1049 */
1050static void wlan_hdd_update_queue_oper_stats(hdd_adapter_t *adapter,
1051 enum netif_action_type action, enum netif_reason_type reason)
1052{
1053 switch (action) {
1054 case WLAN_STOP_ALL_NETIF_QUEUE:
1055 case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER:
1056 case WLAN_NETIF_TX_DISABLE:
1057 case WLAN_NETIF_TX_DISABLE_N_CARRIER:
1058 adapter->queue_oper_stats[reason].pause_count++;
1059 break;
1060 case WLAN_START_ALL_NETIF_QUEUE:
1061 case WLAN_WAKE_ALL_NETIF_QUEUE:
1062 case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER:
1063 adapter->queue_oper_stats[reason].unpause_count++;
1064 break;
1065 default:
1066 break;
1067 }
1068
1069 return;
1070}
1071
1072/**
Nirav Shah89223f72016-03-01 18:10:38 +05301073 * wlan_hdd_update_txq_timestamp() - update txq timestamp
1074 * @dev: net device
1075 *
1076 * Return: none
1077 */
1078void wlan_hdd_update_txq_timestamp(struct net_device *dev)
1079{
1080 struct netdev_queue *txq;
1081 int i;
1082 bool unlock;
1083
1084 for (i = 0; i < NUM_TX_QUEUES; i++) {
1085 txq = netdev_get_tx_queue(dev, i);
1086 unlock = __netif_tx_trylock(txq);
1087 txq_trans_update(txq);
1088 if (unlock == true)
1089 __netif_tx_unlock(txq);
1090 }
1091}
1092
1093/**
Nirav Shah617cff92016-04-25 10:24:24 +05301094 * wlan_hdd_update_unpause_time() - update unpause time
1095 * @adapter: adapter handle
1096 *
1097 * Return: none
1098 */
1099static void wlan_hdd_update_unpause_time(hdd_adapter_t *adapter)
1100{
1101 qdf_time_t curr_time = qdf_system_ticks();
1102
1103 adapter->total_unpause_time += curr_time - adapter->last_time;
1104 adapter->last_time = curr_time;
1105}
1106
1107/**
1108 * wlan_hdd_update_pause_time() - update pause time
1109 * @adapter: adapter handle
1110 *
1111 * Return: none
1112 */
Nirav Shahda008342016-05-17 18:50:40 +05301113static void wlan_hdd_update_pause_time(hdd_adapter_t *adapter,
1114 uint32_t temp_map)
Nirav Shah617cff92016-04-25 10:24:24 +05301115{
1116 qdf_time_t curr_time = qdf_system_ticks();
Nirav Shahda008342016-05-17 18:50:40 +05301117 uint8_t i;
1118 qdf_time_t pause_time;
Nirav Shah617cff92016-04-25 10:24:24 +05301119
Nirav Shahda008342016-05-17 18:50:40 +05301120 pause_time = curr_time - adapter->last_time;
1121 adapter->total_pause_time += pause_time;
Nirav Shah617cff92016-04-25 10:24:24 +05301122 adapter->last_time = curr_time;
Nirav Shahda008342016-05-17 18:50:40 +05301123
1124 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
1125 if (temp_map & (1 << i)) {
1126 adapter->queue_oper_stats[i].total_pause_time +=
1127 pause_time;
1128 break;
1129 }
1130 }
1131
Nirav Shah617cff92016-04-25 10:24:24 +05301132}
1133
1134/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135 * wlan_hdd_netif_queue_control() - Use for netif_queue related actions
1136 * @adapter: adapter handle
1137 * @action: action type
1138 * @reason: reason type
1139 *
1140 * This is single function which is used for netif_queue related
1141 * actions like start/stop of network queues and on/off carrier
1142 * option.
1143 *
1144 * Return: None
1145 */
1146void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
1147 enum netif_action_type action, enum netif_reason_type reason)
1148{
Nirav Shahda008342016-05-17 18:50:40 +05301149 uint32_t temp_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150
1151 if ((!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) ||
1152 (!adapter->dev)) {
1153 hdd_err("adapter is invalid");
1154 return;
1155 }
1156
1157 switch (action) {
1158
1159 case WLAN_NETIF_CARRIER_ON:
1160 netif_carrier_on(adapter->dev);
1161 break;
1162
1163 case WLAN_NETIF_CARRIER_OFF:
1164 netif_carrier_off(adapter->dev);
1165 break;
1166
1167 case WLAN_STOP_ALL_NETIF_QUEUE:
1168 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301169 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001170 netif_tx_stop_all_queues(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301171 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301172 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301173 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 adapter->pause_map |= (1 << reason);
1175 spin_unlock_bh(&adapter->pause_map_lock);
1176 break;
1177
1178 case WLAN_START_ALL_NETIF_QUEUE:
1179 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shahda008342016-05-17 18:50:40 +05301180 temp_map = adapter->pause_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001181 adapter->pause_map &= ~(1 << reason);
Nirav Shah617cff92016-04-25 10:24:24 +05301182 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001183 netif_tx_start_all_queues(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301184 wlan_hdd_update_pause_time(adapter, temp_map);
Nirav Shah617cff92016-04-25 10:24:24 +05301185 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186 spin_unlock_bh(&adapter->pause_map_lock);
1187 break;
1188
1189 case WLAN_WAKE_ALL_NETIF_QUEUE:
1190 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shahda008342016-05-17 18:50:40 +05301191 temp_map = adapter->pause_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 adapter->pause_map &= ~(1 << reason);
Nirav Shah617cff92016-04-25 10:24:24 +05301193 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001194 netif_tx_wake_all_queues(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301195 wlan_hdd_update_pause_time(adapter, temp_map);
Nirav Shah617cff92016-04-25 10:24:24 +05301196 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001197 spin_unlock_bh(&adapter->pause_map_lock);
1198 break;
1199
1200 case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER:
1201 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301202 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203 netif_tx_stop_all_queues(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301204 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301205 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301206 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207 adapter->pause_map |= (1 << reason);
1208 netif_carrier_off(adapter->dev);
1209 spin_unlock_bh(&adapter->pause_map_lock);
1210 break;
1211
1212 case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER:
1213 spin_lock_bh(&adapter->pause_map_lock);
1214 netif_carrier_on(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301215 temp_map = adapter->pause_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 adapter->pause_map &= ~(1 << reason);
Nirav Shah617cff92016-04-25 10:24:24 +05301217 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 netif_tx_start_all_queues(adapter->dev);
Nirav Shahda008342016-05-17 18:50:40 +05301219 wlan_hdd_update_pause_time(adapter, temp_map);
Nirav Shah617cff92016-04-25 10:24:24 +05301220 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 spin_unlock_bh(&adapter->pause_map_lock);
1222 break;
1223
1224 case WLAN_NETIF_TX_DISABLE:
1225 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301226 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 netif_tx_disable(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301228 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301229 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301230 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 adapter->pause_map |= (1 << reason);
1232 spin_unlock_bh(&adapter->pause_map_lock);
1233 break;
1234
1235 case WLAN_NETIF_TX_DISABLE_N_CARRIER:
1236 spin_lock_bh(&adapter->pause_map_lock);
Nirav Shah89223f72016-03-01 18:10:38 +05301237 if (!adapter->pause_map) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 netif_tx_disable(adapter->dev);
Nirav Shah89223f72016-03-01 18:10:38 +05301239 wlan_hdd_update_txq_timestamp(adapter->dev);
Nirav Shah617cff92016-04-25 10:24:24 +05301240 wlan_hdd_update_unpause_time(adapter);
Nirav Shah89223f72016-03-01 18:10:38 +05301241 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 adapter->pause_map |= (1 << reason);
1243 netif_carrier_off(adapter->dev);
1244 spin_unlock_bh(&adapter->pause_map_lock);
1245 break;
1246
1247 default:
1248 hdd_err("unsupported action %d", action);
1249 }
1250
1251 spin_lock_bh(&adapter->pause_map_lock);
1252 if (adapter->pause_map & (1 << WLAN_PEER_UNAUTHORISED))
1253 wlan_hdd_process_peer_unauthorised_pause(adapter);
1254 spin_unlock_bh(&adapter->pause_map_lock);
1255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256 wlan_hdd_update_queue_oper_stats(adapter, action, reason);
1257
1258 adapter->queue_oper_history[adapter->history_index].time =
Anurag Chouhan50220ce2016-02-18 20:11:33 +05301259 qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001260 adapter->queue_oper_history[adapter->history_index].netif_action =
1261 action;
1262 adapter->queue_oper_history[adapter->history_index].netif_reason =
1263 reason;
1264 adapter->queue_oper_history[adapter->history_index].pause_map =
1265 adapter->pause_map;
1266 if (++adapter->history_index == WLAN_HDD_MAX_HISTORY_ENTRY)
1267 adapter->history_index = 0;
1268
1269 return;
1270}
1271
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001272/**
1273 * hdd_set_mon_rx_cb() - Set Monitor mode Rx callback
1274 * @dev: Pointer to net_device structure
1275 *
1276 * Return: 0 for success; non-zero for failure
1277 */
1278int hdd_set_mon_rx_cb(struct net_device *dev)
1279{
1280 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1281 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1282 int ret;
1283 QDF_STATUS qdf_status;
1284 struct ol_txrx_desc_type sta_desc = {0};
1285 struct ol_txrx_ops txrx_ops;
1286
1287 ret = wlan_hdd_validate_context(hdd_ctx);
1288 if (0 != ret)
1289 return ret;
1290
1291 qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
1292 txrx_ops.rx.rx = hdd_mon_rx_packet_cbk;
1293 ol_txrx_vdev_register(
1294 ol_txrx_get_vdev_from_vdev_id(adapter->sessionId),
1295 adapter, &txrx_ops);
1296 /* peer is created wma_vdev_attach->wma_create_peer */
1297 qdf_status = ol_txrx_register_peer(&sta_desc);
1298 if (QDF_STATUS_SUCCESS != qdf_status) {
1299 hdd_err("WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]",
1300 qdf_status, qdf_status);
1301 goto exit;
1302 }
1303
1304 qdf_status = sme_create_mon_session(hdd_ctx->hHal,
1305 adapter->macAddressCurrent.bytes);
1306 if (QDF_STATUS_SUCCESS != qdf_status) {
1307 hdd_err("sme_create_mon_session() failed to register. Status= %d [0x%08X]",
1308 qdf_status, qdf_status);
1309 }
1310exit:
1311 ret = qdf_status_to_os_return(qdf_status);
1312 return ret;
1313}
Nirav Shahbd36b062016-07-18 11:12:59 +05301314
1315/**
1316 * hdd_send_rps_ind() - send rps indication to daemon
1317 * @adapter: adapter context
1318 *
1319 * If RPS feature enabled by INI, send RPS enable indication to daemon
1320 * Indication contents is the name of interface to find correct sysfs node
1321 * Should send all available interfaces
1322 *
1323 * Return: none
1324 */
1325void hdd_send_rps_ind(hdd_adapter_t *adapter)
1326{
1327 int i;
1328 uint8_t cpu_map_list_len = 0;
1329 hdd_context_t *hdd_ctxt = NULL;
1330 struct wlan_rps_data rps_data;
1331
1332 if (!adapter) {
1333 hdd_err("adapter is NULL");
1334 return;
1335 }
1336
1337 hdd_ctxt = WLAN_HDD_GET_CTX(adapter);
1338 rps_data.num_queues = NUM_TX_QUEUES;
1339
1340 hdd_info("cpu_map_list '%s'", hdd_ctxt->config->cpu_map_list);
1341
1342 /* in case no cpu map list is provided, simply return */
1343 if (!strlen(hdd_ctxt->config->cpu_map_list)) {
1344 hdd_err("no cpu map list found");
1345 goto err;
1346 }
1347
1348 if (QDF_STATUS_SUCCESS !=
1349 hdd_hex_string_to_u16_array(hdd_ctxt->config->cpu_map_list,
1350 rps_data.cpu_map_list,
1351 &cpu_map_list_len,
1352 WLAN_SVC_IFACE_NUM_QUEUES)) {
1353 hdd_err("invalid cpu map list");
1354 goto err;
1355 }
1356
1357 rps_data.num_queues =
1358 (cpu_map_list_len < rps_data.num_queues) ?
1359 cpu_map_list_len : rps_data.num_queues;
1360
1361 for (i = 0; i < rps_data.num_queues; i++) {
1362 hdd_info("cpu_map_list[%d] = 0x%x",
1363 i, rps_data.cpu_map_list[i]);
1364 }
1365
1366 strlcpy(rps_data.ifname, adapter->dev->name,
1367 sizeof(rps_data.ifname));
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05301368 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
1369 WLAN_SVC_RPS_ENABLE_IND,
Nirav Shahbd36b062016-07-18 11:12:59 +05301370 &rps_data, sizeof(rps_data));
1371
1372err:
1373 hdd_err("Wrong RPS configuration. enabling rx_thread");
1374 hdd_ctxt->rps = false;
1375 hdd_ctxt->enableRxThread = true;
1376}
1377
1378