blob: f5c670d1174f057ebe2245cc2e5a91f417ac80ab [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/* Include files */
29#include <linux/semaphore.h>
30#include <wlan_hdd_tx_rx.h>
31#include <wlan_hdd_softap_tx_rx.h>
32#include <linux/netdevice.h>
33#include <linux/skbuff.h>
34#include <linux/etherdevice.h>
Anurag Chouhan6d760662016-02-20 16:05:43 +053035#include <qdf_types.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include <ani_global.h>
Anurag Chouhan6d760662016-02-20 16:05:43 +053037#include <qdf_types.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038#include <net/ieee80211_radiotap.h>
39#include <cds_sched.h>
40#include <wlan_hdd_napi.h>
Dhanashri Atre182b0272016-02-17 15:35:07 -080041#include <ol_txrx.h>
Dhanashri Atreb08959a2016-03-01 17:28:03 -080042#include <cdp_txrx_peer_ops.h>
Manjunathappa Prakash779e4862016-09-12 17:00:11 -070043#include <cds_utils.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080044
45#ifdef IPA_OFFLOAD
46#include <wlan_hdd_ipa.h>
47#endif
48
49/* Preprocessor definitions and constants */
50#undef QCA_HDD_SAP_DUMP_SK_BUFF
51
52/* Type declarations */
53
54/* Function definitions and documenation */
55#ifdef QCA_HDD_SAP_DUMP_SK_BUFF
56/**
57 * hdd_softap_dump_sk_buff() - Dump an skb
58 * @skb: skb to dump
59 *
60 * Return: None
61 */
62static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
63{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065 "%s: head = %p ", __func__, skb->head);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053066 /* QDF_TRACE( QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data); */
67 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080068 "%s: tail = %p ", __func__, skb->tail);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053069 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070 "%s: end = %p ", __func__, skb->end);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053071 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072 "%s: len = %d ", __func__, skb->len);
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: data_len = %d ", __func__, skb->data_len);
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: mac_len = %d", __func__, skb->mac_len);
77
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053078 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", skb->data[0],
80 skb->data[1], skb->data[2], skb->data[3], skb->data[4],
81 skb->data[5], skb->data[6], skb->data[7]);
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[8],
84 skb->data[9], skb->data[10], skb->data[11], skb->data[12],
85 skb->data[13], skb->data[14], skb->data[15]);
86}
87#else
88static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
89{
90}
91#endif
92
93#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
94/**
95 * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler
96 * @adapter_context: pointer to vdev adapter
97 *
98 * TX Q resume timer handler for SAP and P2P GO interface. If Blocked
99 * OS Q is not resumed during timeout period, to prevent permanent
100 * stall, resume OS Q forcefully for SAP and P2P GO interface.
101 *
102 * Return: None
103 */
104void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context)
105{
106 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
107
108 if (!pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530109 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110 "%s: INV ARG", __func__);
111 /* INVALID ARG */
112 return;
113 }
114
115 hddLog(LOG1, FL("Enabling queues"));
116 wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE,
117 WLAN_CONTROL_PATH);
118 return;
119}
120
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530121#if defined(CONFIG_PER_VDEV_TX_DESC_POOL)
122
123/**
124 * hdd_softap_tx_resume_false() - Resume OS TX Q false leads to queue disabling
125 * @pAdapter: pointer to hdd adapter
126 * @tx_resume: TX Q resume trigger
127 *
128 *
129 * Return: None
130 */
131static void
132hdd_softap_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
133{
134 if (true == tx_resume)
135 return;
136
137 hdd_notice("Disabling queues");
138 wlan_hdd_netif_queue_control(pAdapter, WLAN_STOP_ALL_NETIF_QUEUE,
139 WLAN_DATA_FLOW_CONTROL);
140
141 if (QDF_TIMER_STATE_STOPPED ==
142 qdf_mc_timer_get_current_state(&pAdapter->
143 tx_flow_control_timer)) {
144 QDF_STATUS status;
145 status = qdf_mc_timer_start(&pAdapter->tx_flow_control_timer,
146 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
147
148 if (!QDF_IS_STATUS_SUCCESS(status))
149 hdd_err("Failed to start tx_flow_control_timer");
150 else
151 pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++;
152 }
153 return;
154}
155#else
156
157static inline void
158hdd_softap_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
159{
160 return;
161}
162#endif
163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164/**
165 * hdd_softap_tx_resume_cb() - Resume OS TX Q.
166 * @adapter_context: pointer to vdev apdapter
167 * @tx_resume: TX Q resume trigger
168 *
169 * Q was stopped due to WLAN TX path low resource condition
170 *
171 * Return: None
172 */
173void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume)
174{
175 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
176
177 if (!pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530178 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179 "%s: INV ARG", __func__);
180 /* INVALID ARG */
181 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
192 hddLog(LOG1, FL("Enabling queues"));
193 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}
201#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
202
203/**
Mukul Sharmac4de4ef2016-09-12 15:39:00 +0530204 * __hdd_softap_hard_start_xmit() - Transmit a frame
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205 * @skb: pointer to OS packet (sk_buff)
206 * @dev: pointer to network device
207 *
208 * Function registered with the Linux OS for transmitting
209 * packets. This version of the function directly passes
210 * the packet to Transport Layer.
211 *
212 * Return: Always returns NETDEV_TX_OK
213 */
Jeff Johnson6376abe2016-10-05 16:24:56 -0700214static int __hdd_softap_hard_start_xmit(struct sk_buff *skb,
215 struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216{
217 sme_ac_enum_type ac = SME_AC_BE;
218 hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev);
219 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530220 struct qdf_mac_addr *pDestMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221 uint8_t STAId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222
223 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
224 /* Prevent this function from being called during SSR since TL
225 * context may not be reinitialized at this time which may
226 * lead to a crash.
227 */
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800228 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530229 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800230 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 goto drop_pkt;
232 }
233
234 /*
235 * If the device is operating on a DFS Channel
236 * then check if SAP is in CAC WAIT state and
237 * drop the packets. In CAC WAIT state device
238 * is expected not to transmit any frames.
239 * SAP starts Tx only after the BSS START is
240 * done.
241 */
242 if (pHddApCtx->dfs_cac_block_tx) {
243 goto drop_pkt;
244 }
245
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800246 /*
247 * If a transmit function is not registered, drop packet
248 */
249 if (!pAdapter->tx_fn) {
250 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
251 "%s: TX function not registered by the data path",
252 __func__);
253 goto drop_pkt;
254 }
255
Nirav Shah5e74bb82016-07-20 16:01:27 +0530256 wlan_hdd_classify_pkt(skb);
257
Anurag Chouhan6d760662016-02-20 16:05:43 +0530258 pDestMacAddress = (struct qdf_mac_addr *) skb->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800259
Nirav Shah5e74bb82016-07-20 16:01:27 +0530260 if (QDF_NBUF_CB_GET_IS_BCAST(skb) ||
261 QDF_NBUF_CB_GET_IS_MCAST(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800262 /* The BC/MC station ID is assigned during BSS
263 * starting phase. SAP will return the station ID
264 * used for BC/MC traffic.
265 */
266 STAId = pHddApCtx->uBCStaId;
267 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530268 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 hdd_softap_get_sta_id(pAdapter,
270 pDestMacAddress, &STAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530271 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
272 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273 "%s: Failed to find right station", __func__);
274 goto drop_pkt;
275 }
276
277 if (STAId == HDD_WLAN_INVALID_STA_ID) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530278 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
279 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800280 "%s: Failed to find right station", __func__);
281 goto drop_pkt;
282 } else if (false == pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530283 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
284 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800285 "%s: STA %d is unregistered", __func__,
286 STAId);
287 goto drop_pkt;
288 }
289
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800290 if ((OL_TXRX_PEER_STATE_CONN !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 pAdapter->aStaInfo[STAId].tlSTAState)
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800292 && (OL_TXRX_PEER_STATE_AUTH !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 pAdapter->aStaInfo[STAId].tlSTAState)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530294 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
295 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 "%s: Station not connected yet", __func__);
297 goto drop_pkt;
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800298 } else if (OL_TXRX_PEER_STATE_CONN ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299 pAdapter->aStaInfo[STAId].tlSTAState) {
300 if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530301 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
302 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800303 "%s: NON-EAPOL packet in non-Authenticated state",
304 __func__);
305 goto drop_pkt;
306 }
307 }
308 }
309
310 hdd_get_tx_resource(pAdapter, STAId,
311 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
312
313 /* Get TL AC corresponding to Qdisc queue index/AC. */
314 ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
315 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
316
317#if defined (IPA_OFFLOAD)
Nirav Shahcbc6d722016-03-01 16:24:53 +0530318 if (!qdf_nbuf_ipa_owned_get(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319#endif
320 /* Check if the buffer has enough header room */
321 skb = skb_unshare(skb, GFP_ATOMIC);
322 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800323 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324#if defined (IPA_OFFLOAD)
325 }
326#endif
327
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800328 pAdapter->stats.tx_bytes += skb->len;
329 ++pAdapter->stats.tx_packets;
330
Nirav Shah5e74bb82016-07-20 16:01:27 +0530331 hdd_event_eapol_log(skb, QDF_TX);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530332 qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530333 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
334 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800335
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530336 qdf_dp_trace_set_track(skb, QDF_TX);
337 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
338 (uint8_t *)&skb->data, sizeof(skb->data), QDF_TX));
339 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
340 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530341 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530342 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
343 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
344 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800346 if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId),
347 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530348 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800349 "%s: Failed to send packet to txrx for staid:%d",
350 __func__, STAId);
351 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
352 goto drop_pkt;
353 }
Dustin Browne0024fa2016-10-14 16:29:21 -0700354 netif_trans_update(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355
356 return NETDEV_TX_OK;
357
358drop_pkt:
359
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530360 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530361 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530362 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530363 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530364 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
365 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Jeff Johnsonedeff232015-11-11 17:19:42 -0800366 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800367
Jeff Johnsonedeff232015-11-11 17:19:42 -0800368drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369 ++pAdapter->stats.tx_dropped;
370 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371
372 return NETDEV_TX_OK;
373}
374
375/**
Mukul Sharmac4de4ef2016-09-12 15:39:00 +0530376 * hdd_softap_hard_start_xmit() - Wrapper function to protect
377 * __hdd_softap_hard_start_xmit from SSR
378 * @skb: pointer to OS packet
379 * @dev: pointer to net_device structure
380 *
381 * Function called by OS if any packet needs to transmit.
382 *
383 * Return: Always returns NETDEV_TX_OK
384 */
385int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
386{
387 int ret;
388
389 cds_ssr_protect(__func__);
390 ret = __hdd_softap_hard_start_xmit(skb, dev);
391 cds_ssr_unprotect(__func__);
392
393 return ret;
394}
395
396/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800397 * __hdd_softap_tx_timeout() - TX timeout handler
398 * @dev: pointer to network device
399 *
400 * This function is registered as a netdev ndo_tx_timeout method, and
401 * is invoked by the kernel if the driver takes too long to transmit a
402 * frame.
403 *
404 * Return: None
405 */
406static void __hdd_softap_tx_timeout(struct net_device *dev)
407{
408 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
409 hdd_context_t *hdd_ctx;
Nirav Shah89223f72016-03-01 18:10:38 +0530410 struct netdev_queue *txq;
411 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530413 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530414 NULL, 0, QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 /* Getting here implies we disabled the TX queues for too
416 * long. Queues are disabled either because of disassociation
417 * or low resource scenarios. In case of disassociation it is
418 * ok to ignore this. But if associated, we have do possible
419 * recovery here
420 */
421 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
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_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800424 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425 return;
426 }
Nirav Shah89223f72016-03-01 18:10:38 +0530427
Dustin Browne0024fa2016-10-14 16:29:21 -0700428 TX_TIMEOUT_TRACE(dev, QDF_MODULE_ID_HDD_SAP_DATA);
Nirav Shah89223f72016-03-01 18:10:38 +0530429
430 for (i = 0; i < NUM_TX_QUEUES; i++) {
431 txq = netdev_get_tx_queue(dev, i);
432 QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
433 QDF_TRACE_LEVEL_ERROR,
434 "Queue%d status: %d txq->trans_start %lu",
435 i, netif_tx_queue_stopped(txq), txq->trans_start);
436 }
437
438 wlan_hdd_display_netif_queue_history(hdd_ctx);
439 ol_tx_dump_flow_pool_info();
440 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
441 "carrier state: %d", netif_carrier_ok(dev));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442}
443
444/**
445 * hdd_softap_tx_timeout() - SSR wrapper for __hdd_softap_tx_timeout
446 * @dev: pointer to net_device
447 *
448 * Return: none
449 */
450void hdd_softap_tx_timeout(struct net_device *dev)
451{
452 cds_ssr_protect(__func__);
453 __hdd_softap_tx_timeout(dev);
454 cds_ssr_unprotect(__func__);
455}
456
457/**
458 * @hdd_softap_init_tx_rx() - Initialize Tx/RX module
459 * @pAdapter: pointer to adapter context
460 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530461 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
462 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800463 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530464QDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530466 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467
468 uint8_t STAId = 0;
469
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530470 qdf_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471
472 spin_lock_init(&pAdapter->staInfo_lock);
473
474 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530475 qdf_mem_zero(&pAdapter->aStaInfo[STAId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476 sizeof(hdd_station_info_t));
477 }
478
479 return status;
480}
481
482/**
483 * @hdd_softap_deinit_tx_rx() - Deinitialize Tx/RX module
484 * @pAdapter: pointer to adapter context
485 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530486 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
487 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530489QDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530491 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492
493 return status;
494}
495
496/**
497 * hdd_softap_init_tx_rx_sta() - Initialize tx/rx for a softap station
498 * @pAdapter: pointer to adapter context
499 * @STAId: Station ID to initialize
500 * @pmacAddrSTA: pointer to the MAC address of the station
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_sta(hdd_adapter_t *pAdapter, uint8_t STAId,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530506 struct qdf_mac_addr *pmacAddrSTA)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507{
508 spin_lock_bh(&pAdapter->staInfo_lock);
509 if (pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530510 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800511 "%s: Reinit station %d", __func__, STAId);
512 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530513 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800514 }
515
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530516 qdf_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517
518 pAdapter->aStaInfo[STAId].isUsed = true;
519 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530520 qdf_copy_macaddr(&pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521
522 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530523 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524}
525
526/**
527 * hdd_softap_deinit_tx_rx_sta() - Deinitialize tx/rx for a softap station
528 * @pAdapter: pointer to adapter context
529 * @STAId: Station ID to deinitialize
530 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530531 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
532 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800533 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530534QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800535{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530536 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537 hdd_hostapd_state_t *pHostapdState;
538
539 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
540
541 spin_lock_bh(&pAdapter->staInfo_lock);
542
543 if (false == pAdapter->aStaInfo[STAId].isUsed) {
544 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530545 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546 "%s: Deinit station not inited %d", __func__, STAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530547 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 }
549
550 pAdapter->aStaInfo[STAId].isUsed = false;
551 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
552
553 spin_unlock_bh(&pAdapter->staInfo_lock);
554 return status;
555}
556
557/**
558 * hdd_softap_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800559 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530560 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 *
562 * Receive callback registered with TL. TL will call this to notify
563 * the HDD when one or more packets were received for a registered
564 * STA.
565 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530566 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
567 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800569QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800570{
571 hdd_adapter_t *pAdapter = NULL;
572 int rxstat;
573 unsigned int cpu_index;
574 struct sk_buff *skb = NULL;
575 hdd_context_t *pHddCtx = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576
577 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800578 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530579 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530581 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582 }
583
Dhanashri Atre182b0272016-02-17 15:35:07 -0800584 pAdapter = (hdd_adapter_t *)context;
585 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
586 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
587 "Magic cookie(%x) for adapter sanity verification is invalid",
588 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530589 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590 }
591
Dhanashri Atre182b0272016-02-17 15:35:07 -0800592 pHddCtx = pAdapter->pHddCtx;
593 if (unlikely(NULL == pHddCtx)) {
594 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
595 "%s: HDD context is Null", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530596 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800597 }
598
599 /* walk the chain until all are processed */
600 skb = (struct sk_buff *)rxBuf;
601
602 hdd_softap_dump_sk_buff(skb);
603
604 skb->dev = pAdapter->dev;
605
Dhanashri Atre182b0272016-02-17 15:35:07 -0800606 if (unlikely(skb->dev == NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530608 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609 "%s: ERROR!!Invalid netdevice", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530610 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800611 }
612 cpu_index = wlan_hdd_get_cpu();
613 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
614 ++pAdapter->stats.rx_packets;
615 pAdapter->stats.rx_bytes += skb->len;
616
Nirav Shah5e74bb82016-07-20 16:01:27 +0530617 hdd_event_eapol_log(skb, QDF_RX);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530618 DPTRACE(qdf_dp_trace(rxBuf,
619 QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
620 qdf_nbuf_data_addr(rxBuf),
621 sizeof(qdf_nbuf_data(rxBuf)), QDF_RX));
622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623 skb->protocol = eth_type_trans(skb, skb->dev);
624#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +0530625 cds_host_diag_log_work(&pHddCtx->rx_wake_lock,
626 HDD_WAKE_LOCK_DURATION,
627 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530628 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +0530629 HDD_WAKE_LOCK_DURATION);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630#endif
631
632 /* Remove SKB from internal tracking table before submitting
633 * it to stack
634 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530635 qdf_net_buf_debug_release_skb(rxBuf);
Nirav Shahbd36b062016-07-18 11:12:59 +0530636 if (hdd_napi_enabled(HDD_NAPI_ANY) &&
637 !pHddCtx->enableRxThread)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 rxstat = netif_receive_skb(skb);
639 else
640 rxstat = netif_rx_ni(skb);
641 if (NET_RX_SUCCESS == rxstat) {
642 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
643 } else {
644 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];
645 }
646
647 pAdapter->dev->last_rx = jiffies;
648
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530649 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650}
651
652/**
653 * hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
654 * @pAdapter: pointer to adapter context
655 * @staId: Station ID to deregister
656 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530657 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530659QDF_STATUS hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530661 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 hdd_context_t *pHddCtx;
663
664 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530665 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800666 "%s: pAdapter is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530667 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668 }
669
670 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530671 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800672 "%s: Invalid pAdapter magic", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530673 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800674 }
675
676 pHddCtx = (hdd_context_t *) (pAdapter->pHddCtx);
677 /* Clear station in TL and then update HDD data
678 * structures. This helps to block RX frames from other
679 * station to this station.
680 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530681 qdf_status = ol_txrx_clear_peer(staId);
682 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530683 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 "ol_txrx_clear_peer() failed to for staID %d. "
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530685 "Status= %d [0x%08X]", staId, qdf_status, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 }
687
688 if (pAdapter->aStaInfo[staId].isUsed) {
689 spin_lock_bh(&pAdapter->staInfo_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530690 qdf_mem_zero(&pAdapter->aStaInfo[staId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 sizeof(hdd_station_info_t));
692 spin_unlock_bh(&pAdapter->staInfo_lock);
693 }
694 pHddCtx->sta_to_adapter[staId] = NULL;
695
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530696 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697}
698
699/**
700 * hdd_softap_register_sta() - Register a SoftAP STA
701 * @pAdapter: pointer to adapter context
702 * @fAuthRequired: is additional authentication required?
703 * @fPrivacyBit: should 802.11 privacy bit be set?
704 * @staId: station ID assigned to this station
705 * @ucastSig: unicast security signature
706 * @bcastSig: broadcast security signature
707 * @pPeerMacAddress: station MAC address
708 * @fWmmEnabled: is WMM enabled for this STA?
709 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530710 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530712QDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 bool fAuthRequired,
714 bool fPrivacyBit,
715 uint8_t staId,
716 uint8_t ucastSig,
717 uint8_t bcastSig,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530718 struct qdf_mac_addr *pPeerMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 bool fWmmEnabled)
720{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530721 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 struct ol_txrx_desc_type staDesc = { 0 };
723 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800724 struct ol_txrx_ops txrx_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725
726 /*
727 * Clean up old entry if it is not cleaned up properly
728 */
729 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530730 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731 "clean up old entry for STA %d", staId);
732 hdd_softap_deregister_sta(pAdapter, staId);
733 }
734 /* Get the Station ID from the one saved during the assocation. */
735
736 staDesc.sta_id = staId;
737
738 /*Save the pAdapter Pointer for this staId */
739 pHddCtx->sta_to_adapter[staId] = pAdapter;
740
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530741 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742 hdd_softap_init_tx_rx_sta(pAdapter, staId,
743 pPeerMacAddress);
744
745 staDesc.is_qos_enabled = fWmmEnabled;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530746 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747 "HDD SOFTAP register TL QoS_enabled=%d",
748 staDesc.is_qos_enabled);
749
Dhanashri Atre182b0272016-02-17 15:35:07 -0800750 /* Register the vdev transmit and receive functions */
751 qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
752 txrx_ops.rx.rx = hdd_softap_rx_packet_cbk;
753 ol_txrx_vdev_register(
754 ol_txrx_get_vdev_from_vdev_id(pAdapter->sessionId),
755 pAdapter, &txrx_ops);
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800756 pAdapter->tx_fn = txrx_ops.tx.tx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800757
Dhanashri Atre50141c52016-04-07 13:15:29 -0700758 qdf_status = ol_txrx_register_peer(&staDesc);
759 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
760 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
761 "SOFTAP ol_txrx_register_peer() failed to register. Status= %d [0x%08X]",
762 qdf_status, qdf_status);
763 return qdf_status;
764 }
765
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766 /* if ( WPA ), tell TL to go to 'connected' and after keys come to the
767 * driver then go to 'authenticated'. For all other authentication
768 * types (those that do not require upper layer authentication) we can
769 * put TL directly into 'authenticated' state
770 */
771
772 pAdapter->aStaInfo[staId].ucSTAId = staId;
773 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
774
775 if (!fAuthRequired) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530776 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
778 pAdapter->aStaInfo[staId].ucSTAId);
779
780 /* Connections that do not need Upper layer auth,
781 * transition TL directly to 'Authenticated' state.
782 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530783 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800784 OL_TXRX_PEER_STATE_AUTH, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800786 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787 pAdapter->sessionCtx.ap.uIsAuthenticated = true;
788 } else {
789
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530790 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time",
792 pAdapter->aStaInfo[staId].ucSTAId);
793
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530794 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800795 OL_TXRX_PEER_STATE_CONN, false);
796 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_CONN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800797
798 pAdapter->sessionCtx.ap.uIsAuthenticated = false;
799
800 }
801
802 /* Enable Tx queue */
803 hddLog(LOG1, FL("Enabling queues"));
804 wlan_hdd_netif_queue_control(pAdapter,
805 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
806 WLAN_CONTROL_PATH);
807
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530808 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800809}
810
811/**
812 * hdd_softap_register_bc_sta() - Register the SoftAP broadcast STA
813 * @pAdapter: pointer to adapter context
814 * @fPrivacyBit: should 802.11 privacy bit be set?
815 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530816 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530818QDF_STATUS hdd_softap_register_bc_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 bool fPrivacyBit)
820{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530821 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530823 struct qdf_mac_addr broadcastMacAddr =
824 QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 hdd_ap_ctx_t *pHddApCtx;
826
827 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
828
829 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830 pHddCtx->sta_to_adapter[pHddApCtx->uBCStaId] = pAdapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530831 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832 hdd_softap_register_sta(pAdapter, false, fPrivacyBit,
833 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
834 uBCStaId, 0, 1, &broadcastMacAddr, 0);
835
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530836 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837}
838
839/**
840 * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA
841 * @pAdapter: pointer to adapter context
842 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530843 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530845QDF_STATUS hdd_softap_deregister_bc_sta(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846{
847 return hdd_softap_deregister_sta(pAdapter,
848 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
849 uBCStaId);
850}
851
852/**
853 * hdd_softap_stop_bss() - Stop the BSS
854 * @pAdapter: pointer to adapter context
855 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530856 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800857 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530858QDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530860 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861 uint8_t staId = 0;
862 hdd_context_t *pHddCtx;
863 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
864
865 /* bss deregister is not allowed during wlan driver loading or
866 * unloading
867 */
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800868 if (cds_is_load_or_unload_in_progress()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530869 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800870 "%s: Loading_unloading in Progress, state: 0x%x. Ignore!!!",
871 __func__, cds_get_driver_state());
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530872 return QDF_STATUS_E_PERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 }
874
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530875 qdf_status = hdd_softap_deregister_bc_sta(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530877 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530878 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 "%s: Failed to deregister BC sta Id %d", __func__,
880 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
881 }
882
883 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) {
884 /* This excludes BC sta as it is already deregistered */
885 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530886 qdf_status = hdd_softap_deregister_sta(pAdapter, staId);
887 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530888 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
889 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890 "%s: Failed to deregister sta Id %d",
891 __func__, staId);
892 }
893 }
894 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530895 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896}
897
898/**
899 * hdd_softap_change_sta_state() - Change the state of a SoftAP station
900 * @pAdapter: pointer to adapter context
901 * @pDestMacAddress: MAC address of the station
902 * @state: new state of the station
903 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530904 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800905 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530906QDF_STATUS hdd_softap_change_sta_state(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530907 struct qdf_mac_addr *pDestMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908 enum ol_txrx_peer_state state)
909{
910 uint8_t ucSTAId = WLAN_MAX_STA_COUNT;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530911 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530913 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 "%s: enter", __func__);
915
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530916 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 hdd_softap_get_sta_id(pAdapter,
918 pDestMacAddress, &ucSTAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530919 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920 "%s: Failed to find right station", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530921 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 }
923
924 if (false ==
Anurag Chouhanc5548422016-02-24 18:33:27 +0530925 qdf_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926 pDestMacAddress)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530927 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800928 "%s: Station MAC address does not matching",
929 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530930 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 }
932
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530933 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 hdd_change_peer_state(pAdapter, ucSTAId, state, false);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530935 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936 "%s: change station to state %d succeed", __func__, state);
937
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530938 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 pAdapter->aStaInfo[ucSTAId].tlSTAState =
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800940 OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941 }
942
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530943 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944 "%s exit", __func__);
945
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530946 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947}
948
949/*
950 * hdd_softap_get_sta_id() - Find station ID from MAC address
951 * @pAdapter: pointer to adapter context
952 * @pDestMacAddress: MAC address of the destination
953 * @staId: Station ID associated with the MAC address
954 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530955 * Return: QDF_STATUS_SUCCESS if a match was found, in which case
956 * staId is populated, QDF_STATUS_E_FAILURE if a match is
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957 * not found
958 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530959QDF_STATUS hdd_softap_get_sta_id(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530960 struct qdf_mac_addr *pMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961 uint8_t *staId)
962{
963 uint8_t i;
964
965 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530966 if (!qdf_mem_cmp
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967 (&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530968 QDF_MAC_ADDR_SIZE) && pAdapter->aStaInfo[i].isUsed) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969 *staId = i;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530970 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 }
972 }
973
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530974 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800975}