blob: 066031d6600f4c3a0d74d175ba047889d9795525 [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
120/**
121 * hdd_softap_tx_resume_cb() - Resume OS TX Q.
122 * @adapter_context: pointer to vdev apdapter
123 * @tx_resume: TX Q resume trigger
124 *
125 * Q was stopped due to WLAN TX path low resource condition
126 *
127 * Return: None
128 */
129void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume)
130{
131 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
132
133 if (!pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530134 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135 "%s: INV ARG", __func__);
136 /* INVALID ARG */
137 return;
138 }
139
140 /* Resume TX */
141 if (true == tx_resume) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530142 if (QDF_TIMER_STATE_STOPPED !=
143 qdf_mc_timer_get_current_state(&pAdapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144 tx_flow_control_timer)) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530145 qdf_mc_timer_stop(&pAdapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146 }
147
148 hddLog(LOG1, FL("Enabling queues"));
149 wlan_hdd_netif_queue_control(pAdapter,
150 WLAN_WAKE_ALL_NETIF_QUEUE,
151 WLAN_DATA_FLOW_CONTROL);
152 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153 return;
154}
155#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
156
157/**
158 * hdd_softap_hard_start_xmit() - Transmit a frame
159 * @skb: pointer to OS packet (sk_buff)
160 * @dev: pointer to network device
161 *
162 * Function registered with the Linux OS for transmitting
163 * packets. This version of the function directly passes
164 * the packet to Transport Layer.
165 *
166 * Return: Always returns NETDEV_TX_OK
167 */
168int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
169{
170 sme_ac_enum_type ac = SME_AC_BE;
171 hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev);
172 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530173 struct qdf_mac_addr *pDestMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174 uint8_t STAId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800175#ifdef QCA_PKT_PROTO_TRACE
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800176 uint8_t proto_type = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177 hdd_context_t *hddCtxt = (hdd_context_t *) pAdapter->pHddCtx;
178#endif /* QCA_PKT_PROTO_TRACE */
179
180 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
181 /* Prevent this function from being called during SSR since TL
182 * context may not be reinitialized at this time which may
183 * lead to a crash.
184 */
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800185 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530186 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800187 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188 goto drop_pkt;
189 }
190
191 /*
192 * If the device is operating on a DFS Channel
193 * then check if SAP is in CAC WAIT state and
194 * drop the packets. In CAC WAIT state device
195 * is expected not to transmit any frames.
196 * SAP starts Tx only after the BSS START is
197 * done.
198 */
199 if (pHddApCtx->dfs_cac_block_tx) {
200 goto drop_pkt;
201 }
202
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800203 /*
204 * If a transmit function is not registered, drop packet
205 */
206 if (!pAdapter->tx_fn) {
207 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
208 "%s: TX function not registered by the data path",
209 __func__);
210 goto drop_pkt;
211 }
212
Anurag Chouhan6d760662016-02-20 16:05:43 +0530213 pDestMacAddress = (struct qdf_mac_addr *) skb->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214
Anurag Chouhanc5548422016-02-24 18:33:27 +0530215 if (qdf_is_macaddr_broadcast(pDestMacAddress) ||
216 qdf_is_macaddr_group(pDestMacAddress)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 /* The BC/MC station ID is assigned during BSS
218 * starting phase. SAP will return the station ID
219 * used for BC/MC traffic.
220 */
221 STAId = pHddApCtx->uBCStaId;
222 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530223 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 hdd_softap_get_sta_id(pAdapter,
225 pDestMacAddress, &STAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530226 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
227 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 "%s: Failed to find right station", __func__);
229 goto drop_pkt;
230 }
231
232 if (STAId == HDD_WLAN_INVALID_STA_ID) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530233 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
234 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235 "%s: Failed to find right station", __func__);
236 goto drop_pkt;
237 } else if (false == pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530238 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
239 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800240 "%s: STA %d is unregistered", __func__,
241 STAId);
242 goto drop_pkt;
243 }
244
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800245 if ((OL_TXRX_PEER_STATE_CONN !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246 pAdapter->aStaInfo[STAId].tlSTAState)
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800247 && (OL_TXRX_PEER_STATE_AUTH !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800248 pAdapter->aStaInfo[STAId].tlSTAState)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530249 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
250 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251 "%s: Station not connected yet", __func__);
252 goto drop_pkt;
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800253 } else if (OL_TXRX_PEER_STATE_CONN ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800254 pAdapter->aStaInfo[STAId].tlSTAState) {
255 if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530256 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
257 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800258 "%s: NON-EAPOL packet in non-Authenticated state",
259 __func__);
260 goto drop_pkt;
261 }
262 }
263 }
264
265 hdd_get_tx_resource(pAdapter, STAId,
266 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
267
268 /* Get TL AC corresponding to Qdisc queue index/AC. */
269 ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
270 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
271
272#if defined (IPA_OFFLOAD)
Nirav Shahcbc6d722016-03-01 16:24:53 +0530273 if (!qdf_nbuf_ipa_owned_get(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800274#endif
275 /* Check if the buffer has enough header room */
276 skb = skb_unshare(skb, GFP_ATOMIC);
277 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800278 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279
280 if (skb_headroom(skb) < dev->hard_header_len) {
281 struct sk_buff *tmp;
282 tmp = skb;
283 skb = skb_realloc_headroom(tmp, dev->hard_header_len);
284 dev_kfree_skb(tmp);
285 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800286 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800287 }
288#if defined (IPA_OFFLOAD)
289 }
290#endif
291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292#ifdef QCA_PKT_PROTO_TRACE
293 if ((hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
294 (hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
295 /* Proto Trace enabled */
296 proto_type = cds_pkt_get_proto_type(skb,
297 hddCtxt->config->
298 gEnableDebugLog, 0);
299 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
300 cds_pkt_trace_buf_update("HA:T:EPL");
301 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
302 cds_pkt_trace_buf_update("HA:T:DHC");
303 }
304 }
305#endif /* QCA_PKT_PROTO_TRACE */
306 pAdapter->stats.tx_bytes += skb->len;
307 ++pAdapter->stats.tx_packets;
308
309 /* Zero out skb's context buffer for the driver to use */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530310 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530311 qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530312 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
313 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800314
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530315 qdf_dp_trace_set_track(skb, QDF_TX);
316 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD,
317 (uint8_t *)&skb->data, sizeof(skb->data), QDF_TX));
318 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
319 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530320 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530321 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_TX_PACKET_RECORD,
322 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
323 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800325#ifdef QCA_PKT_PROTO_TRACE
326 qdf_nbuf_trace_set_proto_type(skb, proto_type);
327#endif
328 if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId),
329 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530330 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800331 "%s: Failed to send packet to txrx for staid:%d",
332 __func__, STAId);
333 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
334 goto drop_pkt;
335 }
336 dev->trans_start = jiffies;
337
338 return NETDEV_TX_OK;
339
340drop_pkt:
341
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530342 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530343 (uint8_t *)skb->data, qdf_nbuf_len(skb), QDF_TX));
Nirav Shahcbc6d722016-03-01 16:24:53 +0530344 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530345 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530346 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
347 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE), QDF_TX));
Jeff Johnsonedeff232015-11-11 17:19:42 -0800348 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800349
Jeff Johnsonedeff232015-11-11 17:19:42 -0800350drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351 ++pAdapter->stats.tx_dropped;
352 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800353
354 return NETDEV_TX_OK;
355}
356
357/**
358 * __hdd_softap_tx_timeout() - TX timeout handler
359 * @dev: pointer to network device
360 *
361 * This function is registered as a netdev ndo_tx_timeout method, and
362 * is invoked by the kernel if the driver takes too long to transmit a
363 * frame.
364 *
365 * Return: None
366 */
367static void __hdd_softap_tx_timeout(struct net_device *dev)
368{
369 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
370 hdd_context_t *hdd_ctx;
Nirav Shah89223f72016-03-01 18:10:38 +0530371 struct netdev_queue *txq;
372 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530374 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530375 NULL, 0, QDF_TX));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 /* Getting here implies we disabled the TX queues for too
377 * long. Queues are disabled either because of disassociation
378 * or low resource scenarios. In case of disassociation it is
379 * ok to ignore this. But if associated, we have do possible
380 * recovery here
381 */
382 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800383 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530384 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800385 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 return;
387 }
Nirav Shah89223f72016-03-01 18:10:38 +0530388
389 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
390 "%s: Transmission timeout occurred jiffies %lu trans_start %lu"
391 , __func__, jiffies, dev->trans_start);
392
393 for (i = 0; i < NUM_TX_QUEUES; i++) {
394 txq = netdev_get_tx_queue(dev, i);
395 QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
396 QDF_TRACE_LEVEL_ERROR,
397 "Queue%d status: %d txq->trans_start %lu",
398 i, netif_tx_queue_stopped(txq), txq->trans_start);
399 }
400
401 wlan_hdd_display_netif_queue_history(hdd_ctx);
402 ol_tx_dump_flow_pool_info();
403 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
404 "carrier state: %d", netif_carrier_ok(dev));
405
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800406}
407
408/**
409 * hdd_softap_tx_timeout() - SSR wrapper for __hdd_softap_tx_timeout
410 * @dev: pointer to net_device
411 *
412 * Return: none
413 */
414void hdd_softap_tx_timeout(struct net_device *dev)
415{
416 cds_ssr_protect(__func__);
417 __hdd_softap_tx_timeout(dev);
418 cds_ssr_unprotect(__func__);
419}
420
421/**
422 * @hdd_softap_init_tx_rx() - Initialize Tx/RX module
423 * @pAdapter: pointer to adapter context
424 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530425 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
426 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800427 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530428QDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530430 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431
432 uint8_t STAId = 0;
433
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530434 qdf_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435
436 spin_lock_init(&pAdapter->staInfo_lock);
437
438 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530439 qdf_mem_zero(&pAdapter->aStaInfo[STAId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800440 sizeof(hdd_station_info_t));
441 }
442
443 return status;
444}
445
446/**
447 * @hdd_softap_deinit_tx_rx() - Deinitialize Tx/RX module
448 * @pAdapter: pointer to adapter context
449 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530450 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
451 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800452 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530453QDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530455 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456
457 return status;
458}
459
460/**
461 * hdd_softap_init_tx_rx_sta() - Initialize tx/rx for a softap station
462 * @pAdapter: pointer to adapter context
463 * @STAId: Station ID to initialize
464 * @pmacAddrSTA: pointer to the MAC address of the station
465 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530466 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
467 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800468 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530469QDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530470 struct qdf_mac_addr *pmacAddrSTA)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471{
472 spin_lock_bh(&pAdapter->staInfo_lock);
473 if (pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530474 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 "%s: Reinit station %d", __func__, STAId);
476 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530477 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478 }
479
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530480 qdf_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481
482 pAdapter->aStaInfo[STAId].isUsed = true;
483 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530484 qdf_copy_macaddr(&pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485
486 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530487 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488}
489
490/**
491 * hdd_softap_deinit_tx_rx_sta() - Deinitialize tx/rx for a softap station
492 * @pAdapter: pointer to adapter context
493 * @STAId: Station ID to deinitialize
494 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530495 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
496 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530498QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530500 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501 hdd_hostapd_state_t *pHostapdState;
502
503 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
504
505 spin_lock_bh(&pAdapter->staInfo_lock);
506
507 if (false == pAdapter->aStaInfo[STAId].isUsed) {
508 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530509 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 "%s: Deinit station not inited %d", __func__, STAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530511 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512 }
513
514 pAdapter->aStaInfo[STAId].isUsed = false;
515 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
516
517 spin_unlock_bh(&pAdapter->staInfo_lock);
518 return status;
519}
520
521/**
522 * hdd_softap_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800523 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530524 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 *
526 * Receive callback registered with TL. TL will call this to notify
527 * the HDD when one or more packets were received for a registered
528 * STA.
529 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530530 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
531 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800533QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534{
535 hdd_adapter_t *pAdapter = NULL;
536 int rxstat;
537 unsigned int cpu_index;
538 struct sk_buff *skb = NULL;
539 hdd_context_t *pHddCtx = NULL;
540#ifdef QCA_PKT_PROTO_TRACE
541 uint8_t proto_type;
542#endif /* QCA_PKT_PROTO_TRACE */
543
544 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800545 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530546 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530548 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 }
550
Dhanashri Atre182b0272016-02-17 15:35:07 -0800551 pAdapter = (hdd_adapter_t *)context;
552 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
553 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
554 "Magic cookie(%x) for adapter sanity verification is invalid",
555 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530556 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557 }
558
Dhanashri Atre182b0272016-02-17 15:35:07 -0800559 pHddCtx = pAdapter->pHddCtx;
560 if (unlikely(NULL == pHddCtx)) {
561 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
562 "%s: HDD context is Null", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530563 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564 }
565
566 /* walk the chain until all are processed */
567 skb = (struct sk_buff *)rxBuf;
568
569 hdd_softap_dump_sk_buff(skb);
570
571 skb->dev = pAdapter->dev;
572
Dhanashri Atre182b0272016-02-17 15:35:07 -0800573 if (unlikely(skb->dev == NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530575 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576 "%s: ERROR!!Invalid netdevice", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530577 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 }
579 cpu_index = wlan_hdd_get_cpu();
580 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
581 ++pAdapter->stats.rx_packets;
582 pAdapter->stats.rx_bytes += skb->len;
583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584#ifdef QCA_PKT_PROTO_TRACE
585 if ((pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
586 (pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
587 proto_type = cds_pkt_get_proto_type(skb,
588 pHddCtx->config->
589 gEnableDebugLog, 0);
590 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
591 cds_pkt_trace_buf_update("HA:R:EPL");
592 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
593 cds_pkt_trace_buf_update("HA:R:DHC");
594 }
595 }
596#endif /* QCA_PKT_PROTO_TRACE */
597
Nirav Shah0d58a7e2016-04-26 22:54:12 +0530598 DPTRACE(qdf_dp_trace(rxBuf,
599 QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
600 qdf_nbuf_data_addr(rxBuf),
601 sizeof(qdf_nbuf_data(rxBuf)), QDF_RX));
602
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 skb->protocol = eth_type_trans(skb, skb->dev);
604#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530605 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606 HDD_WAKE_LOCK_DURATION,
607 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
608#endif
609
610 /* Remove SKB from internal tracking table before submitting
611 * it to stack
612 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530613 qdf_net_buf_debug_release_skb(rxBuf);
Orhan K AKYILDIZ4f20db52015-12-30 12:35:44 -0800614 if (hdd_napi_enabled(HDD_NAPI_ANY) && !pHddCtx->config->enableRxThread)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 rxstat = netif_receive_skb(skb);
616 else
617 rxstat = netif_rx_ni(skb);
618 if (NET_RX_SUCCESS == rxstat) {
619 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
620 } else {
621 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];
622 }
623
624 pAdapter->dev->last_rx = jiffies;
625
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530626 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627}
628
629/**
630 * hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
631 * @pAdapter: pointer to adapter context
632 * @staId: Station ID to deregister
633 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530634 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530636QDF_STATUS hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530638 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 hdd_context_t *pHddCtx;
640
641 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530642 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643 "%s: pAdapter is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530644 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645 }
646
647 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530648 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 "%s: Invalid pAdapter magic", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530650 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 }
652
653 pHddCtx = (hdd_context_t *) (pAdapter->pHddCtx);
654 /* Clear station in TL and then update HDD data
655 * structures. This helps to block RX frames from other
656 * station to this station.
657 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530658 qdf_status = ol_txrx_clear_peer(staId);
659 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530660 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 "ol_txrx_clear_peer() failed to for staID %d. "
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530662 "Status= %d [0x%08X]", staId, qdf_status, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 }
664
665 if (pAdapter->aStaInfo[staId].isUsed) {
666 spin_lock_bh(&pAdapter->staInfo_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530667 qdf_mem_zero(&pAdapter->aStaInfo[staId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668 sizeof(hdd_station_info_t));
669 spin_unlock_bh(&pAdapter->staInfo_lock);
670 }
671 pHddCtx->sta_to_adapter[staId] = NULL;
672
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530673 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800674}
675
676/**
677 * hdd_softap_register_sta() - Register a SoftAP STA
678 * @pAdapter: pointer to adapter context
679 * @fAuthRequired: is additional authentication required?
680 * @fPrivacyBit: should 802.11 privacy bit be set?
681 * @staId: station ID assigned to this station
682 * @ucastSig: unicast security signature
683 * @bcastSig: broadcast security signature
684 * @pPeerMacAddress: station MAC address
685 * @fWmmEnabled: is WMM enabled for this STA?
686 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530687 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530689QDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 bool fAuthRequired,
691 bool fPrivacyBit,
692 uint8_t staId,
693 uint8_t ucastSig,
694 uint8_t bcastSig,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530695 struct qdf_mac_addr *pPeerMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 bool fWmmEnabled)
697{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530698 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 struct ol_txrx_desc_type staDesc = { 0 };
700 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800701 struct ol_txrx_ops txrx_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702
703 /*
704 * Clean up old entry if it is not cleaned up properly
705 */
706 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530707 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 "clean up old entry for STA %d", staId);
709 hdd_softap_deregister_sta(pAdapter, staId);
710 }
711 /* Get the Station ID from the one saved during the assocation. */
712
713 staDesc.sta_id = staId;
714
715 /*Save the pAdapter Pointer for this staId */
716 pHddCtx->sta_to_adapter[staId] = pAdapter;
717
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530718 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 hdd_softap_init_tx_rx_sta(pAdapter, staId,
720 pPeerMacAddress);
721
722 staDesc.is_qos_enabled = fWmmEnabled;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530723 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 "HDD SOFTAP register TL QoS_enabled=%d",
725 staDesc.is_qos_enabled);
726
Dhanashri Atre182b0272016-02-17 15:35:07 -0800727 /* Register the vdev transmit and receive functions */
728 qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
729 txrx_ops.rx.rx = hdd_softap_rx_packet_cbk;
730 ol_txrx_vdev_register(
731 ol_txrx_get_vdev_from_vdev_id(pAdapter->sessionId),
732 pAdapter, &txrx_ops);
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800733 pAdapter->tx_fn = txrx_ops.tx.tx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800734
Dhanashri Atre50141c52016-04-07 13:15:29 -0700735 qdf_status = ol_txrx_register_peer(&staDesc);
736 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
737 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
738 "SOFTAP ol_txrx_register_peer() failed to register. Status= %d [0x%08X]",
739 qdf_status, qdf_status);
740 return qdf_status;
741 }
742
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743 /* if ( WPA ), tell TL to go to 'connected' and after keys come to the
744 * driver then go to 'authenticated'. For all other authentication
745 * types (those that do not require upper layer authentication) we can
746 * put TL directly into 'authenticated' state
747 */
748
749 pAdapter->aStaInfo[staId].ucSTAId = staId;
750 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
751
752 if (!fAuthRequired) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530753 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
755 pAdapter->aStaInfo[staId].ucSTAId);
756
757 /* Connections that do not need Upper layer auth,
758 * transition TL directly to 'Authenticated' state.
759 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530760 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800761 OL_TXRX_PEER_STATE_AUTH, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800763 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 pAdapter->sessionCtx.ap.uIsAuthenticated = true;
765 } else {
766
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530767 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time",
769 pAdapter->aStaInfo[staId].ucSTAId);
770
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530771 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800772 OL_TXRX_PEER_STATE_CONN, false);
773 pAdapter->aStaInfo[staId].tlSTAState = OL_TXRX_PEER_STATE_CONN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774
775 pAdapter->sessionCtx.ap.uIsAuthenticated = false;
776
777 }
778
779 /* Enable Tx queue */
780 hddLog(LOG1, FL("Enabling queues"));
781 wlan_hdd_netif_queue_control(pAdapter,
782 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
783 WLAN_CONTROL_PATH);
784
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530785 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786}
787
788/**
789 * hdd_softap_register_bc_sta() - Register the SoftAP broadcast STA
790 * @pAdapter: pointer to adapter context
791 * @fPrivacyBit: should 802.11 privacy bit be set?
792 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530793 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530795QDF_STATUS hdd_softap_register_bc_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796 bool fPrivacyBit)
797{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530798 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530800 struct qdf_mac_addr broadcastMacAddr =
801 QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800802 hdd_ap_ctx_t *pHddApCtx;
803
804 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
805
806 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
807#ifdef WLAN_FEATURE_MBSSID
808 pHddCtx->sta_to_adapter[pHddApCtx->uBCStaId] = pAdapter;
809#else
810 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
811#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530812 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 hdd_softap_register_sta(pAdapter, false, fPrivacyBit,
814 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
815 uBCStaId, 0, 1, &broadcastMacAddr, 0);
816
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530817 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818}
819
820/**
821 * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA
822 * @pAdapter: pointer to adapter context
823 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530824 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530826QDF_STATUS hdd_softap_deregister_bc_sta(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827{
828 return hdd_softap_deregister_sta(pAdapter,
829 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
830 uBCStaId);
831}
832
833/**
834 * hdd_softap_stop_bss() - Stop the BSS
835 * @pAdapter: pointer to adapter context
836 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530837 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530839QDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530841 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842 uint8_t staId = 0;
843 hdd_context_t *pHddCtx;
844 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
845
846 /* bss deregister is not allowed during wlan driver loading or
847 * unloading
848 */
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800849 if (cds_is_load_or_unload_in_progress()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530850 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800851 "%s: Loading_unloading in Progress, state: 0x%x. Ignore!!!",
852 __func__, cds_get_driver_state());
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530853 return QDF_STATUS_E_PERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854 }
855
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530856 qdf_status = hdd_softap_deregister_bc_sta(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800857
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530858 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530859 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860 "%s: Failed to deregister BC sta Id %d", __func__,
861 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
862 }
863
864 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) {
865 /* This excludes BC sta as it is already deregistered */
866 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530867 qdf_status = hdd_softap_deregister_sta(pAdapter, staId);
868 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530869 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
870 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871 "%s: Failed to deregister sta Id %d",
872 __func__, staId);
873 }
874 }
875 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530876 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800877}
878
879/**
880 * hdd_softap_change_sta_state() - Change the state of a SoftAP station
881 * @pAdapter: pointer to adapter context
882 * @pDestMacAddress: MAC address of the station
883 * @state: new state of the station
884 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530885 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530887QDF_STATUS hdd_softap_change_sta_state(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530888 struct qdf_mac_addr *pDestMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889 enum ol_txrx_peer_state state)
890{
891 uint8_t ucSTAId = WLAN_MAX_STA_COUNT;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530892 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530894 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800895 "%s: enter", __func__);
896
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530897 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898 hdd_softap_get_sta_id(pAdapter,
899 pDestMacAddress, &ucSTAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530900 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901 "%s: Failed to find right station", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530902 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903 }
904
905 if (false ==
Anurag Chouhanc5548422016-02-24 18:33:27 +0530906 qdf_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800907 pDestMacAddress)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530908 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909 "%s: Station MAC address does not matching",
910 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530911 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 }
913
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530914 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800915 hdd_change_peer_state(pAdapter, ucSTAId, state, false);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530916 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 "%s: change station to state %d succeed", __func__, state);
918
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530919 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920 pAdapter->aStaInfo[ucSTAId].tlSTAState =
Dhanashri Atreb08959a2016-03-01 17:28:03 -0800921 OL_TXRX_PEER_STATE_AUTH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 }
923
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530924 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925 "%s exit", __func__);
926
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530927 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800928}
929
930/*
931 * hdd_softap_get_sta_id() - Find station ID from MAC address
932 * @pAdapter: pointer to adapter context
933 * @pDestMacAddress: MAC address of the destination
934 * @staId: Station ID associated with the MAC address
935 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530936 * Return: QDF_STATUS_SUCCESS if a match was found, in which case
937 * staId is populated, QDF_STATUS_E_FAILURE if a match is
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800938 * not found
939 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530940QDF_STATUS hdd_softap_get_sta_id(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530941 struct qdf_mac_addr *pMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 uint8_t *staId)
943{
944 uint8_t i;
945
946 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530947 if (!qdf_mem_cmp
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948 (&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530949 QDF_MAC_ADDR_SIZE) && pAdapter->aStaInfo[i].isUsed) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 *staId = i;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530951 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 }
953 }
954
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530955 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800956}