blob: 3816c6f450cefb9ac61e47c4ca6e5fa0baaca619 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnson4fca3b52017-01-12 08:44:18 -08002 * Copyright (c) 2012-2017 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
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -080028/* denote that this file does not allow legacy hddLog */
29#define HDD_DISALLOW_LEGACY_HDDLOG 1
30
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080031/* Include files */
32#include <linux/semaphore.h>
33#include <wlan_hdd_tx_rx.h>
34#include <wlan_hdd_softap_tx_rx.h>
35#include <linux/netdevice.h>
36#include <linux/skbuff.h>
37#include <linux/etherdevice.h>
Anurag Chouhan6d760662016-02-20 16:05:43 +053038#include <qdf_types.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080039#include <ani_global.h>
Anurag Chouhan6d760662016-02-20 16:05:43 +053040#include <qdf_types.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080041#include <net/ieee80211_radiotap.h>
42#include <cds_sched.h>
43#include <wlan_hdd_napi.h>
Leo Changfdb45c32016-10-28 11:09:23 -070044#include <cdp_txrx_cmn.h>
Dhanashri Atreb08959a2016-03-01 17:28:03 -080045#include <cdp_txrx_peer_ops.h>
Manjunathappa Prakash779e4862016-09-12 17:00:11 -070046#include <cds_utils.h>
Leo Changfdb45c32016-10-28 11:09:23 -070047#include <cdp_txrx_flow_ctrl_v2.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048
49#ifdef IPA_OFFLOAD
50#include <wlan_hdd_ipa.h>
51#endif
52
53/* Preprocessor definitions and constants */
54#undef QCA_HDD_SAP_DUMP_SK_BUFF
55
56/* Type declarations */
57
58/* Function definitions and documenation */
59#ifdef QCA_HDD_SAP_DUMP_SK_BUFF
60/**
61 * hdd_softap_dump_sk_buff() - Dump an skb
62 * @skb: skb to dump
63 *
64 * Return: None
65 */
66static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
67{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053068 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080069 "%s: head = %p ", __func__, skb->head);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053070 /* QDF_TRACE( QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data); */
71 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072 "%s: tail = %p ", __func__, skb->tail);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053073 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074 "%s: end = %p ", __func__, skb->end);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053075 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076 "%s: len = %d ", __func__, skb->len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053077 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078 "%s: data_len = %d ", __func__, skb->data_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053079 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080 "%s: mac_len = %d", __func__, skb->mac_len);
81
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053082 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", skb->data[0],
84 skb->data[1], skb->data[2], skb->data[3], skb->data[4],
85 skb->data[5], skb->data[6], skb->data[7]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053086 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080087 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", skb->data[8],
88 skb->data[9], skb->data[10], skb->data[11], skb->data[12],
89 skb->data[13], skb->data[14], skb->data[15]);
90}
91#else
92static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
93{
94}
95#endif
96
97#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
98/**
99 * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler
100 * @adapter_context: pointer to vdev adapter
101 *
102 * TX Q resume timer handler for SAP and P2P GO interface. If Blocked
103 * OS Q is not resumed during timeout period, to prevent permanent
104 * stall, resume OS Q forcefully for SAP and P2P GO interface.
105 *
106 * Return: None
107 */
108void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context)
109{
110 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
111
112 if (!pAdapter) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800113 hdd_err("NULL adapter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114 return;
115 }
116
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800117 hdd_notice("Enabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800118 wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE,
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800119 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120 return;
121}
122
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530123#if defined(CONFIG_PER_VDEV_TX_DESC_POOL)
124
125/**
126 * hdd_softap_tx_resume_false() - Resume OS TX Q false leads to queue disabling
127 * @pAdapter: pointer to hdd adapter
128 * @tx_resume: TX Q resume trigger
129 *
130 *
131 * Return: None
132 */
133static void
134hdd_softap_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
135{
136 if (true == tx_resume)
137 return;
138
139 hdd_notice("Disabling queues");
140 wlan_hdd_netif_queue_control(pAdapter, WLAN_STOP_ALL_NETIF_QUEUE,
141 WLAN_DATA_FLOW_CONTROL);
142
143 if (QDF_TIMER_STATE_STOPPED ==
144 qdf_mc_timer_get_current_state(&pAdapter->
145 tx_flow_control_timer)) {
146 QDF_STATUS status;
147 status = qdf_mc_timer_start(&pAdapter->tx_flow_control_timer,
148 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
149
150 if (!QDF_IS_STATUS_SUCCESS(status))
151 hdd_err("Failed to start tx_flow_control_timer");
152 else
153 pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++;
154 }
155 return;
156}
157#else
158
159static inline void
160hdd_softap_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
161{
162 return;
163}
164#endif
165
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166/**
167 * hdd_softap_tx_resume_cb() - Resume OS TX Q.
168 * @adapter_context: pointer to vdev apdapter
169 * @tx_resume: TX Q resume trigger
170 *
171 * Q was stopped due to WLAN TX path low resource condition
172 *
173 * Return: None
174 */
175void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume)
176{
177 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
178
179 if (!pAdapter) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800180 hdd_err("NULL adapter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800181 return;
182 }
183
184 /* Resume TX */
185 if (true == tx_resume) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530186 if (QDF_TIMER_STATE_STOPPED !=
187 qdf_mc_timer_get_current_state(&pAdapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188 tx_flow_control_timer)) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530189 qdf_mc_timer_stop(&pAdapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800190 }
191
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800192 hdd_notice("Enabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193 wlan_hdd_netif_queue_control(pAdapter,
194 WLAN_WAKE_ALL_NETIF_QUEUE,
195 WLAN_DATA_FLOW_CONTROL);
196 }
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530197 hdd_softap_tx_resume_false(pAdapter, tx_resume);
198
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 return;
200}
gbianec670c592016-11-24 11:21:30 +0800201
202static inline struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter,
203 struct sk_buff *skb)
204{
205 if (pAdapter->tx_flow_low_watermark > 0)
206 skb_orphan(skb);
207 else {
208 skb = skb_unshare(skb, GFP_ATOMIC);
209 }
210
211 return skb;
212}
213
214#else
215
216static inline struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter,
217 struct sk_buff *skb)
218{
219 return skb_unshare(skb, GFP_ATOMIC);
220}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
222
223/**
Mukul Sharmac4de4ef2016-09-12 15:39:00 +0530224 * __hdd_softap_hard_start_xmit() - Transmit a frame
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 * @skb: pointer to OS packet (sk_buff)
226 * @dev: pointer to network device
227 *
228 * Function registered with the Linux OS for transmitting
229 * packets. This version of the function directly passes
230 * the packet to Transport Layer.
231 *
232 * Return: Always returns NETDEV_TX_OK
233 */
Jeff Johnson6376abe2016-10-05 16:24:56 -0700234static int __hdd_softap_hard_start_xmit(struct sk_buff *skb,
235 struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236{
237 sme_ac_enum_type ac = SME_AC_BE;
238 hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev);
239 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530240 struct qdf_mac_addr *pDestMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800241 uint8_t STAId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800242
243 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
244 /* Prevent this function from being called during SSR since TL
245 * context may not be reinitialized at this time which may
246 * lead to a crash.
247 */
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800248 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530249 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800250 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251 goto drop_pkt;
252 }
253
254 /*
255 * If the device is operating on a DFS Channel
256 * then check if SAP is in CAC WAIT state and
257 * drop the packets. In CAC WAIT state device
258 * is expected not to transmit any frames.
259 * SAP starts Tx only after the BSS START is
260 * done.
261 */
262 if (pHddApCtx->dfs_cac_block_tx) {
263 goto drop_pkt;
264 }
265
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800266 /*
Jeff Johnson4fca3b52017-01-12 08:44:18 -0800267 * If a transmit function is not registered, drop packet
268 */
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800269 if (!pAdapter->tx_fn) {
270 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
271 "%s: TX function not registered by the data path",
272 __func__);
273 goto drop_pkt;
274 }
275
Nirav Shah5e74bb82016-07-20 16:01:27 +0530276 wlan_hdd_classify_pkt(skb);
277
Anurag Chouhan6d760662016-02-20 16:05:43 +0530278 pDestMacAddress = (struct qdf_mac_addr *) skb->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279
Nirav Shah5e74bb82016-07-20 16:01:27 +0530280 if (QDF_NBUF_CB_GET_IS_BCAST(skb) ||
281 QDF_NBUF_CB_GET_IS_MCAST(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800282 /* The BC/MC station ID is assigned during BSS
283 * starting phase. SAP will return the station ID
284 * used for BC/MC traffic.
285 */
286 STAId = pHddApCtx->uBCStaId;
287 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530288 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 hdd_softap_get_sta_id(pAdapter,
290 pDestMacAddress, &STAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530291 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
292 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 "%s: Failed to find right station", __func__);
294 goto drop_pkt;
295 }
296
Prakash Dhavali3107b752016-11-28 14:35:06 +0530297 if (STAId >= WLAN_MAX_STA_COUNT) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530298 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
299 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 "%s: Failed to find right station", __func__);
301 goto drop_pkt;
302 } else if (false == pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530303 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
304 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800305 "%s: STA %d is unregistered", __func__,
306 STAId);
307 goto drop_pkt;
308 }
309
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800310 if ((OL_TXRX_PEER_STATE_CONN !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800311 pAdapter->aStaInfo[STAId].tlSTAState)
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800312 && (OL_TXRX_PEER_STATE_AUTH !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800313 pAdapter->aStaInfo[STAId].tlSTAState)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530314 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
315 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316 "%s: Station not connected yet", __func__);
317 goto drop_pkt;
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800318 } else if (OL_TXRX_PEER_STATE_CONN ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319 pAdapter->aStaInfo[STAId].tlSTAState) {
320 if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530321 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
322 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800323 "%s: NON-EAPOL packet in non-Authenticated state",
324 __func__);
325 goto drop_pkt;
326 }
327 }
328 }
329
330 hdd_get_tx_resource(pAdapter, STAId,
331 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
332
333 /* Get TL AC corresponding to Qdisc queue index/AC. */
334 ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
335 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
336
337#if defined (IPA_OFFLOAD)
Nirav Shahcbc6d722016-03-01 16:24:53 +0530338 if (!qdf_nbuf_ipa_owned_get(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800339#endif
gbianec670c592016-11-24 11:21:30 +0800340
341#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 19, 0))
342 /*
Jeff Johnson4fca3b52017-01-12 08:44:18 -0800343 * The TCP TX throttling logic is changed a little after
344 * 3.19-rc1 kernel, the TCP sending limit will be smaller,
345 * which will throttle the TCP packets to the host driver.
346 * The TCP UP LINK throughput will drop heavily. In order to
347 * fix this issue, need to orphan the socket buffer asap, which
348 * will call skb's destructor to notify the TCP stack that the
349 * SKB buffer is unowned. And then the TCP stack will pump more
350 * packets to host driver.
351 *
352 * The TX packets might be dropped for UDP case in the iperf
353 * testing. So need to be protected by follow control.
354 */
gbianec670c592016-11-24 11:21:30 +0800355 skb = hdd_skb_orphan(pAdapter, skb);
356#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357 /* Check if the buffer has enough header room */
358 skb = skb_unshare(skb, GFP_ATOMIC);
gbianec670c592016-11-24 11:21:30 +0800359#endif
360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800362 goto drop_pkt_accounting;
gbianec670c592016-11-24 11:21:30 +0800363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364#if defined (IPA_OFFLOAD)
365 }
366#endif
367
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368 pAdapter->stats.tx_bytes += skb->len;
369 ++pAdapter->stats.tx_packets;
370
Nirav Shah5e74bb82016-07-20 16:01:27 +0530371 hdd_event_eapol_log(skb, QDF_TX);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530372 qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530373 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
374 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530376 qdf_dp_trace_set_track(skb, QDF_TX);
377 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
Himanshu Agarwalee3411a2017-01-31 12:56:47 +0530378 qdf_nbuf_data_addr(skb), sizeof(qdf_nbuf_data(skb)),
379 QDF_TX));
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530380 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
381 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530382 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530383 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
384 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
385 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386
Leo Changfdb45c32016-10-28 11:09:23 -0700387 if (pAdapter->tx_fn(pAdapter->txrx_vdev,
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800388 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530389 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 "%s: Failed to send packet to txrx for staid:%d",
391 __func__, STAId);
392 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
393 goto drop_pkt;
394 }
Dustin Browne0024fa2016-10-14 16:29:21 -0700395 netif_trans_update(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800396
397 return NETDEV_TX_OK;
398
399drop_pkt:
400
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530401 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530402 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530403 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530404 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530405 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
406 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Jeff Johnsonedeff232015-11-11 17:19:42 -0800407 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408
Jeff Johnsonedeff232015-11-11 17:19:42 -0800409drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800410 ++pAdapter->stats.tx_dropped;
411 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412
413 return NETDEV_TX_OK;
414}
415
416/**
Mukul Sharmac4de4ef2016-09-12 15:39:00 +0530417 * hdd_softap_hard_start_xmit() - Wrapper function to protect
418 * __hdd_softap_hard_start_xmit from SSR
419 * @skb: pointer to OS packet
420 * @dev: pointer to net_device structure
421 *
422 * Function called by OS if any packet needs to transmit.
423 *
424 * Return: Always returns NETDEV_TX_OK
425 */
426int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
427{
428 int ret;
429
430 cds_ssr_protect(__func__);
431 ret = __hdd_softap_hard_start_xmit(skb, dev);
432 cds_ssr_unprotect(__func__);
433
434 return ret;
435}
436
437/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800438 * __hdd_softap_tx_timeout() - TX timeout handler
439 * @dev: pointer to network device
440 *
441 * This function is registered as a netdev ndo_tx_timeout method, and
442 * is invoked by the kernel if the driver takes too long to transmit a
443 * frame.
444 *
445 * Return: None
446 */
447static void __hdd_softap_tx_timeout(struct net_device *dev)
448{
449 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
450 hdd_context_t *hdd_ctx;
Nirav Shah89223f72016-03-01 18:10:38 +0530451 struct netdev_queue *txq;
452 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800453
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530454 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530455 NULL, 0, QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456 /* Getting here implies we disabled the TX queues for too
457 * long. Queues are disabled either because of disassociation
458 * or low resource scenarios. In case of disassociation it is
459 * ok to ignore this. But if associated, we have do possible
460 * recovery here
461 */
462 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800463 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530464 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800465 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466 return;
467 }
Nirav Shah89223f72016-03-01 18:10:38 +0530468
Dustin Browne0024fa2016-10-14 16:29:21 -0700469 TX_TIMEOUT_TRACE(dev, QDF_MODULE_ID_HDD_SAP_DATA);
Nirav Shah89223f72016-03-01 18:10:38 +0530470
471 for (i = 0; i < NUM_TX_QUEUES; i++) {
472 txq = netdev_get_tx_queue(dev, i);
473 QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
474 QDF_TRACE_LEVEL_ERROR,
475 "Queue%d status: %d txq->trans_start %lu",
476 i, netif_tx_queue_stopped(txq), txq->trans_start);
477 }
478
479 wlan_hdd_display_netif_queue_history(hdd_ctx);
Leo Changfdb45c32016-10-28 11:09:23 -0700480 cdp_dump_flow_pool_info(cds_get_context(QDF_MODULE_ID_SOC));
Nirav Shah89223f72016-03-01 18:10:38 +0530481 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
482 "carrier state: %d", netif_carrier_ok(dev));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483}
484
485/**
486 * hdd_softap_tx_timeout() - SSR wrapper for __hdd_softap_tx_timeout
487 * @dev: pointer to net_device
488 *
489 * Return: none
490 */
491void hdd_softap_tx_timeout(struct net_device *dev)
492{
493 cds_ssr_protect(__func__);
494 __hdd_softap_tx_timeout(dev);
495 cds_ssr_unprotect(__func__);
496}
497
498/**
499 * @hdd_softap_init_tx_rx() - Initialize Tx/RX module
500 * @pAdapter: pointer to adapter context
501 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530502 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
503 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530505QDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530507 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508
509 uint8_t STAId = 0;
510
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530511 qdf_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512
513 spin_lock_init(&pAdapter->staInfo_lock);
514
515 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530516 qdf_mem_zero(&pAdapter->aStaInfo[STAId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 sizeof(hdd_station_info_t));
518 }
519
520 return status;
521}
522
523/**
524 * @hdd_softap_deinit_tx_rx() - Deinitialize Tx/RX module
525 * @pAdapter: pointer to adapter context
526 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530527 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
528 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530530QDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800531{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530532 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800533
534 return status;
535}
536
537/**
538 * hdd_softap_init_tx_rx_sta() - Initialize tx/rx for a softap station
539 * @pAdapter: pointer to adapter context
540 * @STAId: Station ID to initialize
541 * @pmacAddrSTA: pointer to the MAC address of the station
542 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530543 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
544 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530546QDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530547 struct qdf_mac_addr *pmacAddrSTA)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548{
549 spin_lock_bh(&pAdapter->staInfo_lock);
550 if (pAdapter->aStaInfo[STAId].isUsed) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551 spin_unlock_bh(&pAdapter->staInfo_lock);
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800552 hdd_err("Reinit of in use station %d", STAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530553 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554 }
555
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530556 qdf_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557
558 pAdapter->aStaInfo[STAId].isUsed = true;
559 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530560 qdf_copy_macaddr(&pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561
562 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530563 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564}
565
566/**
567 * hdd_softap_deinit_tx_rx_sta() - Deinitialize tx/rx for a softap station
568 * @pAdapter: pointer to adapter context
569 * @STAId: Station ID to deinitialize
570 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530571 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
572 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530574QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530576 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577 hdd_hostapd_state_t *pHostapdState;
578
579 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
580
581 spin_lock_bh(&pAdapter->staInfo_lock);
582
583 if (false == pAdapter->aStaInfo[STAId].isUsed) {
584 spin_unlock_bh(&pAdapter->staInfo_lock);
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800585 hdd_err("Deinit station not inited %d", STAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530586 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800587 }
588
589 pAdapter->aStaInfo[STAId].isUsed = false;
590 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
591
592 spin_unlock_bh(&pAdapter->staInfo_lock);
593 return status;
594}
595
596/**
597 * hdd_softap_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800598 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530599 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800600 *
601 * Receive callback registered with TL. TL will call this to notify
602 * the HDD when one or more packets were received for a registered
603 * STA.
604 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530605 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
606 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800608QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609{
610 hdd_adapter_t *pAdapter = NULL;
611 int rxstat;
612 unsigned int cpu_index;
613 struct sk_buff *skb = NULL;
Dhanashri Atrecefa8802017-02-02 16:17:14 -0800614 struct sk_buff *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 hdd_context_t *pHddCtx = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616
617 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800618 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530619 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530621 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622 }
623
Dhanashri Atre182b0272016-02-17 15:35:07 -0800624 pAdapter = (hdd_adapter_t *)context;
625 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
626 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
627 "Magic cookie(%x) for adapter sanity verification is invalid",
628 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530629 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630 }
631
Dhanashri Atre182b0272016-02-17 15:35:07 -0800632 pHddCtx = pAdapter->pHddCtx;
633 if (unlikely(NULL == pHddCtx)) {
634 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
635 "%s: HDD context is Null", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530636 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637 }
638
639 /* walk the chain until all are processed */
Dhanashri Atrecefa8802017-02-02 16:17:14 -0800640 next = (struct sk_buff *)rxBuf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641
Dhanashri Atrecefa8802017-02-02 16:17:14 -0800642 while (next) {
643 skb = next;
644 next = skb->next;
Dhanashri Atre63d98022017-01-24 18:22:09 -0800645 skb->next = NULL;
Dhanashri Atrecefa8802017-02-02 16:17:14 -0800646
647#ifdef QCA_WIFI_NAPIER_EMULATION /* Debug code, remove later */
648 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
649 "%s: skb %p skb->len %d\n", __func__, skb, skb->len);
650#endif
651
Dhanashri Atre63d98022017-01-24 18:22:09 -0800652 hdd_softap_dump_sk_buff(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653
Dhanashri Atre63d98022017-01-24 18:22:09 -0800654 skb->dev = pAdapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655
Dhanashri Atre63d98022017-01-24 18:22:09 -0800656 if (unlikely(skb->dev == NULL)) {
657
658 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
659 "%s: ERROR!!Invalid netdevice", __func__);
Dhanashri Atrecefa8802017-02-02 16:17:14 -0800660 continue;
Dhanashri Atre63d98022017-01-24 18:22:09 -0800661 }
662 cpu_index = wlan_hdd_get_cpu();
663 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
664 ++pAdapter->stats.rx_packets;
665 pAdapter->stats.rx_bytes += skb->len;
666
667 hdd_event_eapol_log(skb, QDF_RX);
Himanshu Agarwalee3411a2017-01-31 12:56:47 +0530668 DPTRACE(qdf_dp_trace(skb,
Dhanashri Atre63d98022017-01-24 18:22:09 -0800669 QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
Himanshu Agarwalee3411a2017-01-31 12:56:47 +0530670 qdf_nbuf_data_addr(skb),
671 sizeof(qdf_nbuf_data(skb)), QDF_RX));
672 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_RX_PACKET_RECORD,
673 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_RX));
674 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
675 DPTRACE(qdf_dp_trace(skb,
676 QDF_DP_TRACE_HDD_RX_PACKET_RECORD,
677 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
678 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE),
679 QDF_RX));
Dhanashri Atre63d98022017-01-24 18:22:09 -0800680
681 skb->protocol = eth_type_trans(skb, skb->dev);
682
683 /* hold configurable wakelock for unicast traffic */
684 if (pHddCtx->config->rx_wakelock_timeout &&
685 skb->pkt_type != PACKET_BROADCAST &&
686 skb->pkt_type != PACKET_MULTICAST) {
687 cds_host_diag_log_work(&pHddCtx->rx_wake_lock,
688 pHddCtx->config->rx_wakelock_timeout,
689 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
690 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
691 pHddCtx->config->
692 rx_wakelock_timeout);
693 }
694
695 /* Remove SKB from internal tracking table before submitting
696 * it to stack
697 */
698 qdf_net_buf_debug_release_skb(rxBuf);
699 if (hdd_napi_enabled(HDD_NAPI_ANY) &&
700 !pHddCtx->enableRxThread)
701 rxstat = netif_receive_skb(skb);
702 else
703 rxstat = netif_rx_ni(skb);
704 if (NET_RX_SUCCESS == rxstat) {
705 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
706 } else {
707 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];
708 }
709
710 pAdapter->dev->last_rx = jiffies;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800712
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530713 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714}
715
716/**
717 * hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
718 * @pAdapter: pointer to adapter context
719 * @staId: Station ID to deregister
720 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530721 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530723QDF_STATUS hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530725 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 hdd_context_t *pHddCtx;
727
728 if (NULL == pAdapter) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800729 hdd_err("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530730 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731 }
732
733 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800734 hdd_err("Invalid adapter magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530735 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736 }
737
738 pHddCtx = (hdd_context_t *) (pAdapter->pHddCtx);
739 /* Clear station in TL and then update HDD data
740 * structures. This helps to block RX frames from other
741 * station to this station.
742 */
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -0800743 qdf_status = cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Leo Changfdb45c32016-10-28 11:09:23 -0700744 cds_get_context(QDF_MODULE_ID_TXRX), staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530745 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -0800746 hdd_err("cdp_clear_peer failed for staID %d, Status=%d [0x%08X]",
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800747 staId, qdf_status, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800748 }
749
750 if (pAdapter->aStaInfo[staId].isUsed) {
751 spin_lock_bh(&pAdapter->staInfo_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530752 qdf_mem_zero(&pAdapter->aStaInfo[staId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753 sizeof(hdd_station_info_t));
754 spin_unlock_bh(&pAdapter->staInfo_lock);
755 }
756 pHddCtx->sta_to_adapter[staId] = NULL;
757
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530758 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759}
760
761/**
762 * hdd_softap_register_sta() - Register a SoftAP STA
763 * @pAdapter: pointer to adapter context
764 * @fAuthRequired: is additional authentication required?
765 * @fPrivacyBit: should 802.11 privacy bit be set?
766 * @staId: station ID assigned to this station
767 * @ucastSig: unicast security signature
768 * @bcastSig: broadcast security signature
769 * @pPeerMacAddress: station MAC address
770 * @fWmmEnabled: is WMM enabled for this STA?
771 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530772 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530774QDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 bool fAuthRequired,
776 bool fPrivacyBit,
777 uint8_t staId,
778 uint8_t ucastSig,
779 uint8_t bcastSig,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530780 struct qdf_mac_addr *pPeerMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 bool fWmmEnabled)
782{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530783 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784 struct ol_txrx_desc_type staDesc = { 0 };
785 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800786 struct ol_txrx_ops txrx_ops;
Leo Changfdb45c32016-10-28 11:09:23 -0700787 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
788 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800790 hdd_info("STA:%u, Auth:%u, Priv:%u, WMM:%u",
791 staId, fAuthRequired, fPrivacyBit, fWmmEnabled);
792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 /*
794 * Clean up old entry if it is not cleaned up properly
795 */
796 if (pAdapter->aStaInfo[staId].isUsed) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800797 hdd_info("clean up old entry for STA %d", staId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798 hdd_softap_deregister_sta(pAdapter, staId);
799 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800801 /* Get the Station ID from the one saved during the assocation. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800802 staDesc.sta_id = staId;
803
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800804 /* Save the pAdapter Pointer for this staId */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805 pHddCtx->sta_to_adapter[staId] = pAdapter;
806
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530807 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808 hdd_softap_init_tx_rx_sta(pAdapter, staId,
809 pPeerMacAddress);
810
811 staDesc.is_qos_enabled = fWmmEnabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812
Dhanashri Atre182b0272016-02-17 15:35:07 -0800813 /* Register the vdev transmit and receive functions */
814 qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
815 txrx_ops.rx.rx = hdd_softap_rx_packet_cbk;
Leo Changfdb45c32016-10-28 11:09:23 -0700816 cdp_vdev_register(soc,
817 cdp_get_vdev_from_vdev_id(soc, pdev, pAdapter->sessionId),
Dhanashri Atre182b0272016-02-17 15:35:07 -0800818 pAdapter, &txrx_ops);
Leo Changfdb45c32016-10-28 11:09:23 -0700819 pAdapter->txrx_vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
820 pAdapter->sessionId);
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800821 pAdapter->tx_fn = txrx_ops.tx.tx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800822
Leo Changfdb45c32016-10-28 11:09:23 -0700823 qdf_status = cdp_peer_register(soc, pdev, &staDesc);
Dhanashri Atre50141c52016-04-07 13:15:29 -0700824 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800825 hdd_err("cdp_peer_register() failed to register. Status = %d [0x%08X]",
826 qdf_status, qdf_status);
Dhanashri Atre50141c52016-04-07 13:15:29 -0700827 return qdf_status;
828 }
829
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830 /* if ( WPA ), tell TL to go to 'connected' and after keys come to the
831 * driver then go to 'authenticated'. For all other authentication
832 * types (those that do not require upper layer authentication) we can
833 * put TL directly into 'authenticated' state
834 */
835
836 pAdapter->aStaInfo[staId].ucSTAId = staId;
837 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
838
839 if (!fAuthRequired) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800840 hdd_info("open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
841 pAdapter->aStaInfo[staId].ucSTAId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842
843 /* Connections that do not need Upper layer auth,
844 * transition TL directly to 'Authenticated' state.
845 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530846 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800847 OL_TXRX_PEER_STATE_AUTH, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800849 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800850 pAdapter->sessionCtx.ap.uIsAuthenticated = true;
851 } else {
852
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800853 hdd_info("ULA auth StaId= %d. Changing TL state to CONNECTED at Join time",
854 pAdapter->aStaInfo[staId].ucSTAId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530856 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800857 OL_TXRX_PEER_STATE_CONN, false);
858 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_CONN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859
860 pAdapter->sessionCtx.ap.uIsAuthenticated = false;
861
862 }
863
864 /* Enable Tx queue */
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800865 hdd_notice("Enabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866 wlan_hdd_netif_queue_control(pAdapter,
867 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
868 WLAN_CONTROL_PATH);
869
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530870 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871}
872
873/**
874 * hdd_softap_register_bc_sta() - Register the SoftAP broadcast STA
875 * @pAdapter: pointer to adapter context
876 * @fPrivacyBit: should 802.11 privacy bit be set?
877 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530878 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530880QDF_STATUS hdd_softap_register_bc_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800881 bool fPrivacyBit)
882{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530883 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530885 struct qdf_mac_addr broadcastMacAddr =
886 QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800887 hdd_ap_ctx_t *pHddApCtx;
888
889 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
890
891 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800892 pHddCtx->sta_to_adapter[pHddApCtx->uBCStaId] = pAdapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530893 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 hdd_softap_register_sta(pAdapter, false, fPrivacyBit,
895 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
896 uBCStaId, 0, 1, &broadcastMacAddr, 0);
897
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530898 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800899}
900
901/**
902 * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA
903 * @pAdapter: pointer to adapter context
904 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530905 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530907QDF_STATUS hdd_softap_deregister_bc_sta(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908{
909 return hdd_softap_deregister_sta(pAdapter,
910 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
911 uBCStaId);
912}
913
914/**
915 * hdd_softap_stop_bss() - Stop the BSS
916 * @pAdapter: pointer to adapter context
917 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530918 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530920QDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530922 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 uint8_t staId = 0;
924 hdd_context_t *pHddCtx;
925 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
926
927 /* bss deregister is not allowed during wlan driver loading or
928 * unloading
929 */
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800930 if (cds_is_load_or_unload_in_progress()) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800931 hdd_err("Loading_unloading in Progress, state: 0x%x. Ignore!!!",
932 cds_get_driver_state());
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530933 return QDF_STATUS_E_PERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 }
935
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530936 qdf_status = hdd_softap_deregister_bc_sta(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800937
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530938 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800939 hdd_err("Failed to deregister BC sta Id %d",
940 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941 }
942
943 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) {
944 /* This excludes BC sta as it is already deregistered */
945 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530946 qdf_status = hdd_softap_deregister_sta(pAdapter, staId);
947 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800948 hdd_err("Failed to deregister sta Id %d",
949 staId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 }
951 }
952 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530953 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954}
955
956/**
957 * hdd_softap_change_sta_state() - Change the state of a SoftAP station
958 * @pAdapter: pointer to adapter context
959 * @pDestMacAddress: MAC address of the station
960 * @state: new state of the station
961 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530962 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530964QDF_STATUS hdd_softap_change_sta_state(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530965 struct qdf_mac_addr *pDestMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966 enum ol_txrx_peer_state state)
967{
968 uint8_t ucSTAId = WLAN_MAX_STA_COUNT;
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800969 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800971 ENTER_DEV(pAdapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800973 qdf_status = hdd_softap_get_sta_id(pAdapter, pDestMacAddress, &ucSTAId);
974 if (QDF_STATUS_SUCCESS != qdf_status) {
975 hdd_err("Failed to find right station");
976 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977 }
978
979 if (false ==
Anurag Chouhanc5548422016-02-24 18:33:27 +0530980 qdf_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800981 pDestMacAddress)) {
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800982 hdd_err("Station %u MAC address not matching", ucSTAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530983 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800984 }
985
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530986 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987 hdd_change_peer_state(pAdapter, ucSTAId, state, false);
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800988 hdd_info("Station %u changed to state %d", ucSTAId, state);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530990 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 pAdapter->aStaInfo[ucSTAId].tlSTAState =
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800992 OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993 }
994
Jeff Johnsond5bd6fd2016-12-05 12:29:21 -0800995 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530996 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997}
998
999/*
1000 * hdd_softap_get_sta_id() - Find station ID from MAC address
1001 * @pAdapter: pointer to adapter context
1002 * @pDestMacAddress: MAC address of the destination
1003 * @staId: Station ID associated with the MAC address
1004 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301005 * Return: QDF_STATUS_SUCCESS if a match was found, in which case
1006 * staId is populated, QDF_STATUS_E_FAILURE if a match is
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001007 * not found
1008 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301009QDF_STATUS hdd_softap_get_sta_id(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301010 struct qdf_mac_addr *pMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001011 uint8_t *staId)
1012{
1013 uint8_t i;
1014
1015 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301016 if (!qdf_mem_cmp
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001017 (&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301018 QDF_MAC_ADDR_SIZE) && pAdapter->aStaInfo[i].isUsed) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019 *staId = i;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301020 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001021 }
1022 }
1023
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301024 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025}