blob: a0dbea356d3b8f09111e4362c88cbee0042691d0 [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>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043
44#ifdef IPA_OFFLOAD
45#include <wlan_hdd_ipa.h>
46#endif
47
48/* Preprocessor definitions and constants */
49#undef QCA_HDD_SAP_DUMP_SK_BUFF
50
51/* Type declarations */
52
53/* Function definitions and documenation */
54#ifdef QCA_HDD_SAP_DUMP_SK_BUFF
55/**
56 * hdd_softap_dump_sk_buff() - Dump an skb
57 * @skb: skb to dump
58 *
59 * Return: None
60 */
61static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
62{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053063 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080064 "%s: head = %p ", __func__, skb->head);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053065 /* QDF_TRACE( QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data); */
66 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080067 "%s: tail = %p ", __func__, skb->tail);
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: end = %p ", __func__, skb->end);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053070 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071 "%s: len = %d ", __func__, skb->len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053072 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073 "%s: data_len = %d ", __func__, skb->data_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053074 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075 "%s: mac_len = %d", __func__, skb->mac_len);
76
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 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", skb->data[0],
79 skb->data[1], skb->data[2], skb->data[3], skb->data[4],
80 skb->data[5], skb->data[6], skb->data[7]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053081 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", skb->data[8],
83 skb->data[9], skb->data[10], skb->data[11], skb->data[12],
84 skb->data[13], skb->data[14], skb->data[15]);
85}
86#else
87static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
88{
89}
90#endif
91
92#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
93/**
94 * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler
95 * @adapter_context: pointer to vdev adapter
96 *
97 * TX Q resume timer handler for SAP and P2P GO interface. If Blocked
98 * OS Q is not resumed during timeout period, to prevent permanent
99 * stall, resume OS Q forcefully for SAP and P2P GO interface.
100 *
101 * Return: None
102 */
103void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context)
104{
105 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
106
107 if (!pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530108 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800109 "%s: INV ARG", __func__);
110 /* INVALID ARG */
111 return;
112 }
113
114 hddLog(LOG1, FL("Enabling queues"));
115 wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE,
116 WLAN_CONTROL_PATH);
117 return;
118}
119
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530120#if defined(CONFIG_PER_VDEV_TX_DESC_POOL)
121
122/**
123 * hdd_softap_tx_resume_false() - Resume OS TX Q false leads to queue disabling
124 * @pAdapter: pointer to hdd adapter
125 * @tx_resume: TX Q resume trigger
126 *
127 *
128 * Return: None
129 */
130static void
131hdd_softap_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
132{
133 if (true == tx_resume)
134 return;
135
136 hdd_notice("Disabling queues");
137 wlan_hdd_netif_queue_control(pAdapter, WLAN_STOP_ALL_NETIF_QUEUE,
138 WLAN_DATA_FLOW_CONTROL);
139
140 if (QDF_TIMER_STATE_STOPPED ==
141 qdf_mc_timer_get_current_state(&pAdapter->
142 tx_flow_control_timer)) {
143 QDF_STATUS status;
144 status = qdf_mc_timer_start(&pAdapter->tx_flow_control_timer,
145 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
146
147 if (!QDF_IS_STATUS_SUCCESS(status))
148 hdd_err("Failed to start tx_flow_control_timer");
149 else
150 pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++;
151 }
152 return;
153}
154#else
155
156static inline void
157hdd_softap_tx_resume_false(hdd_adapter_t *pAdapter, bool tx_resume)
158{
159 return;
160}
161#endif
162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163/**
164 * hdd_softap_tx_resume_cb() - Resume OS TX Q.
165 * @adapter_context: pointer to vdev apdapter
166 * @tx_resume: TX Q resume trigger
167 *
168 * Q was stopped due to WLAN TX path low resource condition
169 *
170 * Return: None
171 */
172void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume)
173{
174 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
175
176 if (!pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530177 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 "%s: INV ARG", __func__);
179 /* INVALID ARG */
180 return;
181 }
182
183 /* Resume TX */
184 if (true == tx_resume) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530185 if (QDF_TIMER_STATE_STOPPED !=
186 qdf_mc_timer_get_current_state(&pAdapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187 tx_flow_control_timer)) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530188 qdf_mc_timer_stop(&pAdapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 }
190
191 hddLog(LOG1, FL("Enabling queues"));
192 wlan_hdd_netif_queue_control(pAdapter,
193 WLAN_WAKE_ALL_NETIF_QUEUE,
194 WLAN_DATA_FLOW_CONTROL);
195 }
Poddar, Siddarthb61cf642016-04-28 16:02:39 +0530196 hdd_softap_tx_resume_false(pAdapter, tx_resume);
197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 return;
199}
200#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
201
202/**
203 * hdd_softap_hard_start_xmit() - Transmit a frame
204 * @skb: pointer to OS packet (sk_buff)
205 * @dev: pointer to network device
206 *
207 * Function registered with the Linux OS for transmitting
208 * packets. This version of the function directly passes
209 * the packet to Transport Layer.
210 *
211 * Return: Always returns NETDEV_TX_OK
212 */
213int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
214{
215 sme_ac_enum_type ac = SME_AC_BE;
216 hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev);
217 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530218 struct qdf_mac_addr *pDestMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 uint8_t STAId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220
221 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
222 /* Prevent this function from being called during SSR since TL
223 * context may not be reinitialized at this time which may
224 * lead to a crash.
225 */
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800226 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530227 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800228 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 goto drop_pkt;
230 }
231
232 /*
233 * If the device is operating on a DFS Channel
234 * then check if SAP is in CAC WAIT state and
235 * drop the packets. In CAC WAIT state device
236 * is expected not to transmit any frames.
237 * SAP starts Tx only after the BSS START is
238 * done.
239 */
240 if (pHddApCtx->dfs_cac_block_tx) {
241 goto drop_pkt;
242 }
243
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800244 /*
245 * If a transmit function is not registered, drop packet
246 */
247 if (!pAdapter->tx_fn) {
248 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
249 "%s: TX function not registered by the data path",
250 __func__);
251 goto drop_pkt;
252 }
253
Anurag Chouhan6d760662016-02-20 16:05:43 +0530254 pDestMacAddress = (struct qdf_mac_addr *) skb->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800255
Anurag Chouhanc5548422016-02-24 18:33:27 +0530256 if (qdf_is_macaddr_broadcast(pDestMacAddress) ||
257 qdf_is_macaddr_group(pDestMacAddress)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800258 /* The BC/MC station ID is assigned during BSS
259 * starting phase. SAP will return the station ID
260 * used for BC/MC traffic.
261 */
262 STAId = pHddApCtx->uBCStaId;
263 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530264 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800265 hdd_softap_get_sta_id(pAdapter,
266 pDestMacAddress, &STAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530267 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
268 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 "%s: Failed to find right station", __func__);
270 goto drop_pkt;
271 }
272
273 if (STAId == HDD_WLAN_INVALID_STA_ID) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530274 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
275 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 "%s: Failed to find right station", __func__);
277 goto drop_pkt;
278 } else if (false == pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530279 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
280 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 "%s: STA %d is unregistered", __func__,
282 STAId);
283 goto drop_pkt;
284 }
285
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800286 if ((OL_TXRX_PEER_STATE_CONN !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800287 pAdapter->aStaInfo[STAId].tlSTAState)
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800288 && (OL_TXRX_PEER_STATE_AUTH !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 pAdapter->aStaInfo[STAId].tlSTAState)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530290 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
291 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292 "%s: Station not connected yet", __func__);
293 goto drop_pkt;
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800294 } else if (OL_TXRX_PEER_STATE_CONN ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 pAdapter->aStaInfo[STAId].tlSTAState) {
296 if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530297 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
298 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299 "%s: NON-EAPOL packet in non-Authenticated state",
300 __func__);
301 goto drop_pkt;
302 }
303 }
304 }
305
306 hdd_get_tx_resource(pAdapter, STAId,
307 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
308
309 /* Get TL AC corresponding to Qdisc queue index/AC. */
310 ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
311 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
312
313#if defined (IPA_OFFLOAD)
Nirav Shahcbc6d722016-03-01 16:24:53 +0530314 if (!qdf_nbuf_ipa_owned_get(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800315#endif
316 /* Check if the buffer has enough header room */
317 skb = skb_unshare(skb, GFP_ATOMIC);
318 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800319 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800320
321 if (skb_headroom(skb) < dev->hard_header_len) {
322 struct sk_buff *tmp;
323 tmp = skb;
324 skb = skb_realloc_headroom(tmp, dev->hard_header_len);
325 dev_kfree_skb(tmp);
326 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800327 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800328 }
329#if defined (IPA_OFFLOAD)
330 }
331#endif
332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800333 pAdapter->stats.tx_bytes += skb->len;
334 ++pAdapter->stats.tx_packets;
335
336 /* Zero out skb's context buffer for the driver to use */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530337 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530338 qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530339 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
340 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530342 qdf_dp_trace_set_track(skb, QDF_TX);
343 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
344 (uint8_t *)&skb->data, sizeof(skb->data), QDF_TX));
345 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
346 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530347 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530348 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
349 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
350 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800352 if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId),
353 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530354 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355 "%s: Failed to send packet to txrx for staid:%d",
356 __func__, STAId);
357 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
358 goto drop_pkt;
359 }
360 dev->trans_start = jiffies;
361
362 return NETDEV_TX_OK;
363
364drop_pkt:
365
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530366 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530367 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530368 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530369 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530370 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
371 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Jeff Johnsonedeff232015-11-11 17:19:42 -0800372 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373
Jeff Johnsonedeff232015-11-11 17:19:42 -0800374drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375 ++pAdapter->stats.tx_dropped;
376 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377
378 return NETDEV_TX_OK;
379}
380
381/**
382 * __hdd_softap_tx_timeout() - TX timeout handler
383 * @dev: pointer to network device
384 *
385 * This function is registered as a netdev ndo_tx_timeout method, and
386 * is invoked by the kernel if the driver takes too long to transmit a
387 * frame.
388 *
389 * Return: None
390 */
391static void __hdd_softap_tx_timeout(struct net_device *dev)
392{
393 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
394 hdd_context_t *hdd_ctx;
Nirav Shah89223f72016-03-01 18:10:38 +0530395 struct netdev_queue *txq;
396 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800397
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530398 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530399 NULL, 0, QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400 /* Getting here implies we disabled the TX queues for too
401 * long. Queues are disabled either because of disassociation
402 * or low resource scenarios. In case of disassociation it is
403 * ok to ignore this. But if associated, we have do possible
404 * recovery here
405 */
406 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800407 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530408 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800409 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800410 return;
411 }
Nirav Shah89223f72016-03-01 18:10:38 +0530412
413 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
414 "%s: Transmission timeout occurred jiffies %lu trans_start %lu"
415 , __func__, jiffies, dev->trans_start);
416
417 for (i = 0; i < NUM_TX_QUEUES; i++) {
418 txq = netdev_get_tx_queue(dev, i);
419 QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
420 QDF_TRACE_LEVEL_ERROR,
421 "Queue%d status: %d txq->trans_start %lu",
422 i, netif_tx_queue_stopped(txq), txq->trans_start);
423 }
424
425 wlan_hdd_display_netif_queue_history(hdd_ctx);
426 ol_tx_dump_flow_pool_info();
427 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
428 "carrier state: %d", netif_carrier_ok(dev));
429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430}
431
432/**
433 * hdd_softap_tx_timeout() - SSR wrapper for __hdd_softap_tx_timeout
434 * @dev: pointer to net_device
435 *
436 * Return: none
437 */
438void hdd_softap_tx_timeout(struct net_device *dev)
439{
440 cds_ssr_protect(__func__);
441 __hdd_softap_tx_timeout(dev);
442 cds_ssr_unprotect(__func__);
443}
444
445/**
446 * @hdd_softap_init_tx_rx() - Initialize Tx/RX module
447 * @pAdapter: pointer to adapter context
448 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530449 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
450 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800451 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530452QDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800453{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530454 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800455
456 uint8_t STAId = 0;
457
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530458 qdf_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800459
460 spin_lock_init(&pAdapter->staInfo_lock);
461
462 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530463 qdf_mem_zero(&pAdapter->aStaInfo[STAId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800464 sizeof(hdd_station_info_t));
465 }
466
467 return status;
468}
469
470/**
471 * @hdd_softap_deinit_tx_rx() - Deinitialize Tx/RX module
472 * @pAdapter: pointer to adapter context
473 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530474 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
475 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530477QDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530479 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480
481 return status;
482}
483
484/**
485 * hdd_softap_init_tx_rx_sta() - Initialize tx/rx for a softap station
486 * @pAdapter: pointer to adapter context
487 * @STAId: Station ID to initialize
488 * @pmacAddrSTA: pointer to the MAC address of the station
489 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530490 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
491 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530493QDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530494 struct qdf_mac_addr *pmacAddrSTA)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495{
496 spin_lock_bh(&pAdapter->staInfo_lock);
497 if (pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530498 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 "%s: Reinit station %d", __func__, STAId);
500 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530501 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502 }
503
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530504 qdf_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505
506 pAdapter->aStaInfo[STAId].isUsed = true;
507 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530508 qdf_copy_macaddr(&pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800509
510 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530511 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512}
513
514/**
515 * hdd_softap_deinit_tx_rx_sta() - Deinitialize tx/rx for a softap station
516 * @pAdapter: pointer to adapter context
517 * @STAId: Station ID to deinitialize
518 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530519 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
520 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530522QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530524 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 hdd_hostapd_state_t *pHostapdState;
526
527 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
528
529 spin_lock_bh(&pAdapter->staInfo_lock);
530
531 if (false == pAdapter->aStaInfo[STAId].isUsed) {
532 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530533 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534 "%s: Deinit station not inited %d", __func__, STAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530535 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536 }
537
538 pAdapter->aStaInfo[STAId].isUsed = false;
539 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
540
541 spin_unlock_bh(&pAdapter->staInfo_lock);
542 return status;
543}
544
545/**
546 * hdd_softap_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800547 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530548 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 *
550 * Receive callback registered with TL. TL will call this to notify
551 * the HDD when one or more packets were received for a registered
552 * STA.
553 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530554 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
555 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800557QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558{
559 hdd_adapter_t *pAdapter = NULL;
560 int rxstat;
561 unsigned int cpu_index;
562 struct sk_buff *skb = NULL;
563 hdd_context_t *pHddCtx = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564
565 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800566 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530567 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530569 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800570 }
571
Dhanashri Atre182b0272016-02-17 15:35:07 -0800572 pAdapter = (hdd_adapter_t *)context;
573 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
574 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
575 "Magic cookie(%x) for adapter sanity verification is invalid",
576 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530577 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 }
579
Dhanashri Atre182b0272016-02-17 15:35:07 -0800580 pHddCtx = pAdapter->pHddCtx;
581 if (unlikely(NULL == pHddCtx)) {
582 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
583 "%s: HDD context is Null", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530584 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585 }
586
587 /* walk the chain until all are processed */
588 skb = (struct sk_buff *)rxBuf;
589
590 hdd_softap_dump_sk_buff(skb);
591
592 skb->dev = pAdapter->dev;
593
Dhanashri Atre182b0272016-02-17 15:35:07 -0800594 if (unlikely(skb->dev == NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530596 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800597 "%s: ERROR!!Invalid netdevice", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530598 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599 }
600 cpu_index = wlan_hdd_get_cpu();
601 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
602 ++pAdapter->stats.rx_packets;
603 pAdapter->stats.rx_bytes += skb->len;
604
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530605 DPTRACE(qdf_dp_trace(rxBuf,
606 QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
607 qdf_nbuf_data_addr(rxBuf),
608 sizeof(qdf_nbuf_data(rxBuf)), QDF_RX));
609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 skb->protocol = eth_type_trans(skb, skb->dev);
611#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530612 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613 HDD_WAKE_LOCK_DURATION,
614 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
615#endif
616
617 /* Remove SKB from internal tracking table before submitting
618 * it to stack
619 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530620 qdf_net_buf_debug_release_skb(rxBuf);
Orhan K AKYILDIZ4f20db52015-12-30 12:35:44 -0800621 if (hdd_napi_enabled(HDD_NAPI_ANY) && !pHddCtx->config->enableRxThread)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622 rxstat = netif_receive_skb(skb);
623 else
624 rxstat = netif_rx_ni(skb);
625 if (NET_RX_SUCCESS == rxstat) {
626 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
627 } else {
628 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];
629 }
630
631 pAdapter->dev->last_rx = jiffies;
632
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530633 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634}
635
636/**
637 * hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
638 * @pAdapter: pointer to adapter context
639 * @staId: Station ID to deregister
640 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530641 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530643QDF_STATUS hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800644{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530645 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646 hdd_context_t *pHddCtx;
647
648 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530649 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650 "%s: pAdapter is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530651 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 }
653
654 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530655 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 "%s: Invalid pAdapter magic", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530657 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 }
659
660 pHddCtx = (hdd_context_t *) (pAdapter->pHddCtx);
661 /* Clear station in TL and then update HDD data
662 * structures. This helps to block RX frames from other
663 * station to this station.
664 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530665 qdf_status = ol_txrx_clear_peer(staId);
666 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530667 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668 "ol_txrx_clear_peer() failed to for staID %d. "
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530669 "Status= %d [0x%08X]", staId, qdf_status, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800670 }
671
672 if (pAdapter->aStaInfo[staId].isUsed) {
673 spin_lock_bh(&pAdapter->staInfo_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530674 qdf_mem_zero(&pAdapter->aStaInfo[staId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 sizeof(hdd_station_info_t));
676 spin_unlock_bh(&pAdapter->staInfo_lock);
677 }
678 pHddCtx->sta_to_adapter[staId] = NULL;
679
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530680 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681}
682
683/**
684 * hdd_softap_register_sta() - Register a SoftAP STA
685 * @pAdapter: pointer to adapter context
686 * @fAuthRequired: is additional authentication required?
687 * @fPrivacyBit: should 802.11 privacy bit be set?
688 * @staId: station ID assigned to this station
689 * @ucastSig: unicast security signature
690 * @bcastSig: broadcast security signature
691 * @pPeerMacAddress: station MAC address
692 * @fWmmEnabled: is WMM enabled for this STA?
693 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530694 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530696QDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 bool fAuthRequired,
698 bool fPrivacyBit,
699 uint8_t staId,
700 uint8_t ucastSig,
701 uint8_t bcastSig,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530702 struct qdf_mac_addr *pPeerMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 bool fWmmEnabled)
704{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530705 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 struct ol_txrx_desc_type staDesc = { 0 };
707 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800708 struct ol_txrx_ops txrx_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800709
710 /*
711 * Clean up old entry if it is not cleaned up properly
712 */
713 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530714 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 "clean up old entry for STA %d", staId);
716 hdd_softap_deregister_sta(pAdapter, staId);
717 }
718 /* Get the Station ID from the one saved during the assocation. */
719
720 staDesc.sta_id = staId;
721
722 /*Save the pAdapter Pointer for this staId */
723 pHddCtx->sta_to_adapter[staId] = pAdapter;
724
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530725 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 hdd_softap_init_tx_rx_sta(pAdapter, staId,
727 pPeerMacAddress);
728
729 staDesc.is_qos_enabled = fWmmEnabled;
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 "HDD SOFTAP register TL QoS_enabled=%d",
732 staDesc.is_qos_enabled);
733
Dhanashri Atre182b0272016-02-17 15:35:07 -0800734 /* Register the vdev transmit and receive functions */
735 qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
736 txrx_ops.rx.rx = hdd_softap_rx_packet_cbk;
737 ol_txrx_vdev_register(
738 ol_txrx_get_vdev_from_vdev_id(pAdapter->sessionId),
739 pAdapter, &txrx_ops);
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800740 pAdapter->tx_fn = txrx_ops.tx.tx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800741
Dhanashri Atre50141c52016-04-07 13:15:29 -0700742 qdf_status = ol_txrx_register_peer(&staDesc);
743 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
744 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
745 "SOFTAP ol_txrx_register_peer() failed to register. Status= %d [0x%08X]",
746 qdf_status, qdf_status);
747 return qdf_status;
748 }
749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800750 /* if ( WPA ), tell TL to go to 'connected' and after keys come to the
751 * driver then go to 'authenticated'. For all other authentication
752 * types (those that do not require upper layer authentication) we can
753 * put TL directly into 'authenticated' state
754 */
755
756 pAdapter->aStaInfo[staId].ucSTAId = staId;
757 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
758
759 if (!fAuthRequired) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530760 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
762 pAdapter->aStaInfo[staId].ucSTAId);
763
764 /* Connections that do not need Upper layer auth,
765 * transition TL directly to 'Authenticated' state.
766 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530767 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800768 OL_TXRX_PEER_STATE_AUTH, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800770 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800771 pAdapter->sessionCtx.ap.uIsAuthenticated = true;
772 } else {
773
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530774 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time",
776 pAdapter->aStaInfo[staId].ucSTAId);
777
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530778 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800779 OL_TXRX_PEER_STATE_CONN, false);
780 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_CONN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781
782 pAdapter->sessionCtx.ap.uIsAuthenticated = false;
783
784 }
785
786 /* Enable Tx queue */
787 hddLog(LOG1, FL("Enabling queues"));
788 wlan_hdd_netif_queue_control(pAdapter,
789 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
790 WLAN_CONTROL_PATH);
791
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530792 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793}
794
795/**
796 * hdd_softap_register_bc_sta() - Register the SoftAP broadcast STA
797 * @pAdapter: pointer to adapter context
798 * @fPrivacyBit: should 802.11 privacy bit be set?
799 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530800 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800801 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530802QDF_STATUS hdd_softap_register_bc_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800803 bool fPrivacyBit)
804{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530805 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530807 struct qdf_mac_addr broadcastMacAddr =
808 QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800809 hdd_ap_ctx_t *pHddApCtx;
810
811 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
812
813 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
814#ifdef WLAN_FEATURE_MBSSID
815 pHddCtx->sta_to_adapter[pHddApCtx->uBCStaId] = pAdapter;
816#else
817 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
818#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530819 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800820 hdd_softap_register_sta(pAdapter, false, fPrivacyBit,
821 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
822 uBCStaId, 0, 1, &broadcastMacAddr, 0);
823
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530824 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825}
826
827/**
828 * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA
829 * @pAdapter: pointer to adapter context
830 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530831 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530833QDF_STATUS hdd_softap_deregister_bc_sta(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834{
835 return hdd_softap_deregister_sta(pAdapter,
836 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
837 uBCStaId);
838}
839
840/**
841 * hdd_softap_stop_bss() - Stop the BSS
842 * @pAdapter: pointer to adapter context
843 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530844 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530846QDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530848 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 uint8_t staId = 0;
850 hdd_context_t *pHddCtx;
851 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
852
853 /* bss deregister is not allowed during wlan driver loading or
854 * unloading
855 */
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800856 if (cds_is_load_or_unload_in_progress()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530857 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800858 "%s: Loading_unloading in Progress, state: 0x%x. Ignore!!!",
859 __func__, cds_get_driver_state());
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530860 return QDF_STATUS_E_PERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861 }
862
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530863 qdf_status = hdd_softap_deregister_bc_sta(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800864
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530865 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530866 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867 "%s: Failed to deregister BC sta Id %d", __func__,
868 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
869 }
870
871 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) {
872 /* This excludes BC sta as it is already deregistered */
873 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530874 qdf_status = hdd_softap_deregister_sta(pAdapter, staId);
875 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530876 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
877 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878 "%s: Failed to deregister sta Id %d",
879 __func__, staId);
880 }
881 }
882 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530883 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884}
885
886/**
887 * hdd_softap_change_sta_state() - Change the state of a SoftAP station
888 * @pAdapter: pointer to adapter context
889 * @pDestMacAddress: MAC address of the station
890 * @state: new state of the station
891 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530892 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530894QDF_STATUS hdd_softap_change_sta_state(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530895 struct qdf_mac_addr *pDestMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896 enum ol_txrx_peer_state state)
897{
898 uint8_t ucSTAId = WLAN_MAX_STA_COUNT;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530899 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530901 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 "%s: enter", __func__);
903
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530904 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800905 hdd_softap_get_sta_id(pAdapter,
906 pDestMacAddress, &ucSTAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530907 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908 "%s: Failed to find right station", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530909 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800910 }
911
912 if (false ==
Anurag Chouhanc5548422016-02-24 18:33:27 +0530913 qdf_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 pDestMacAddress)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530915 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 "%s: Station MAC address does not matching",
917 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530918 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919 }
920
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530921 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 hdd_change_peer_state(pAdapter, ucSTAId, state, false);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530923 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800924 "%s: change station to state %d succeed", __func__, state);
925
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530926 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800927 pAdapter->aStaInfo[ucSTAId].tlSTAState =
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800928 OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929 }
930
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530931 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800932 "%s exit", __func__);
933
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530934 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800935}
936
937/*
938 * hdd_softap_get_sta_id() - Find station ID from MAC address
939 * @pAdapter: pointer to adapter context
940 * @pDestMacAddress: MAC address of the destination
941 * @staId: Station ID associated with the MAC address
942 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530943 * Return: QDF_STATUS_SUCCESS if a match was found, in which case
944 * staId is populated, QDF_STATUS_E_FAILURE if a match is
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800945 * not found
946 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530947QDF_STATUS hdd_softap_get_sta_id(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530948 struct qdf_mac_addr *pMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 uint8_t *staId)
950{
951 uint8_t i;
952
953 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530954 if (!qdf_mem_cmp
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955 (&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530956 QDF_MAC_ADDR_SIZE) && pAdapter->aStaInfo[i].isUsed) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957 *staId = i;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530958 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959 }
960 }
961
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530962 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963}