blob: 5bb3492c54b7c8121002181c6170e21deaa4c55d [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
292 wlan_hdd_log_eapol(skb,
293 WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED);
294
295#ifdef QCA_PKT_PROTO_TRACE
296 if ((hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
297 (hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
298 /* Proto Trace enabled */
299 proto_type = cds_pkt_get_proto_type(skb,
300 hddCtxt->config->
301 gEnableDebugLog, 0);
302 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
303 cds_pkt_trace_buf_update("HA:T:EPL");
304 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
305 cds_pkt_trace_buf_update("HA:T:DHC");
306 }
307 }
308#endif /* QCA_PKT_PROTO_TRACE */
309 pAdapter->stats.tx_bytes += skb->len;
310 ++pAdapter->stats.tx_packets;
311
312 /* Zero out skb's context buffer for the driver to use */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530313 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530314 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
315 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530317 qdf_dp_trace_set_track(skb);
318 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_PACKET_PTR_RECORD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319 (uint8_t *)skb->data, sizeof(skb->data)));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530320 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_PACKET_RECORD,
Nirav Shahcbc6d722016-03-01 16:24:53 +0530321 (uint8_t *)skb->data, qdf_nbuf_len(skb)));
322 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530323 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_PACKET_RECORD,
324 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
Nirav Shahcbc6d722016-03-01 16:24:53 +0530325 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800326
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800327#ifdef QCA_PKT_PROTO_TRACE
328 qdf_nbuf_trace_set_proto_type(skb, proto_type);
329#endif
330 if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId),
331 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530332 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800333 "%s: Failed to send packet to txrx for staid:%d",
334 __func__, STAId);
335 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
336 goto drop_pkt;
337 }
338 dev->trans_start = jiffies;
339
340 return NETDEV_TX_OK;
341
342drop_pkt:
343
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530344 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shahcbc6d722016-03-01 16:24:53 +0530345 (uint8_t *)skb->data, qdf_nbuf_len(skb)));
346 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530347 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
348 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
Nirav Shahcbc6d722016-03-01 16:24:53 +0530349 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE)));
Jeff Johnsonedeff232015-11-11 17:19:42 -0800350 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351
Jeff Johnsonedeff232015-11-11 17:19:42 -0800352drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800353 ++pAdapter->stats.tx_dropped;
354 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355
356 return NETDEV_TX_OK;
357}
358
359/**
360 * __hdd_softap_tx_timeout() - TX timeout handler
361 * @dev: pointer to network device
362 *
363 * This function is registered as a netdev ndo_tx_timeout method, and
364 * is invoked by the kernel if the driver takes too long to transmit a
365 * frame.
366 *
367 * Return: None
368 */
369static void __hdd_softap_tx_timeout(struct net_device *dev)
370{
371 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
372 hdd_context_t *hdd_ctx;
Nirav Shah89223f72016-03-01 18:10:38 +0530373 struct netdev_queue *txq;
374 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530376 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 NULL, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 /* Getting here implies we disabled the TX queues for too
379 * long. Queues are disabled either because of disassociation
380 * or low resource scenarios. In case of disassociation it is
381 * ok to ignore this. But if associated, we have do possible
382 * recovery here
383 */
384 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800385 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530386 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800387 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 return;
389 }
Nirav Shah89223f72016-03-01 18:10:38 +0530390
391 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
392 "%s: Transmission timeout occurred jiffies %lu trans_start %lu"
393 , __func__, jiffies, dev->trans_start);
394
395 for (i = 0; i < NUM_TX_QUEUES; i++) {
396 txq = netdev_get_tx_queue(dev, i);
397 QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
398 QDF_TRACE_LEVEL_ERROR,
399 "Queue%d status: %d txq->trans_start %lu",
400 i, netif_tx_queue_stopped(txq), txq->trans_start);
401 }
402
403 wlan_hdd_display_netif_queue_history(hdd_ctx);
404 ol_tx_dump_flow_pool_info();
405 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
406 "carrier state: %d", netif_carrier_ok(dev));
407
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408}
409
410/**
411 * hdd_softap_tx_timeout() - SSR wrapper for __hdd_softap_tx_timeout
412 * @dev: pointer to net_device
413 *
414 * Return: none
415 */
416void hdd_softap_tx_timeout(struct net_device *dev)
417{
418 cds_ssr_protect(__func__);
419 __hdd_softap_tx_timeout(dev);
420 cds_ssr_unprotect(__func__);
421}
422
423/**
424 * @hdd_softap_init_tx_rx() - Initialize Tx/RX module
425 * @pAdapter: pointer to adapter context
426 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530427 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
428 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530430QDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530432 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433
434 uint8_t STAId = 0;
435
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530436 qdf_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800437
438 spin_lock_init(&pAdapter->staInfo_lock);
439
440 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530441 qdf_mem_zero(&pAdapter->aStaInfo[STAId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 sizeof(hdd_station_info_t));
443 }
444
445 return status;
446}
447
448/**
449 * @hdd_softap_deinit_tx_rx() - Deinitialize Tx/RX module
450 * @pAdapter: pointer to adapter context
451 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530452 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
453 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530455QDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530457 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458
459 return status;
460}
461
462/**
463 * hdd_softap_init_tx_rx_sta() - Initialize tx/rx for a softap station
464 * @pAdapter: pointer to adapter context
465 * @STAId: Station ID to initialize
466 * @pmacAddrSTA: pointer to the MAC address of the station
467 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530468 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
469 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800470 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530471QDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530472 struct qdf_mac_addr *pmacAddrSTA)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473{
474 spin_lock_bh(&pAdapter->staInfo_lock);
475 if (pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530476 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477 "%s: Reinit station %d", __func__, STAId);
478 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530479 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480 }
481
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530482 qdf_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483
484 pAdapter->aStaInfo[STAId].isUsed = true;
485 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530486 qdf_copy_macaddr(&pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800487
488 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530489 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490}
491
492/**
493 * hdd_softap_deinit_tx_rx_sta() - Deinitialize tx/rx for a softap station
494 * @pAdapter: pointer to adapter context
495 * @STAId: Station ID to deinitialize
496 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530497 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
498 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530500QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530502 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800503 hdd_hostapd_state_t *pHostapdState;
504
505 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
506
507 spin_lock_bh(&pAdapter->staInfo_lock);
508
509 if (false == pAdapter->aStaInfo[STAId].isUsed) {
510 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530511 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512 "%s: Deinit station not inited %d", __func__, STAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530513 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800514 }
515
516 pAdapter->aStaInfo[STAId].isUsed = false;
517 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
518
519 spin_unlock_bh(&pAdapter->staInfo_lock);
520 return status;
521}
522
523/**
524 * hdd_softap_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800525 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530526 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800527 *
528 * Receive callback registered with TL. TL will call this to notify
529 * the HDD when one or more packets were received for a registered
530 * STA.
531 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530532 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
533 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800535QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536{
537 hdd_adapter_t *pAdapter = NULL;
538 int rxstat;
539 unsigned int cpu_index;
540 struct sk_buff *skb = NULL;
541 hdd_context_t *pHddCtx = NULL;
542#ifdef QCA_PKT_PROTO_TRACE
543 uint8_t proto_type;
544#endif /* QCA_PKT_PROTO_TRACE */
545
546 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800547 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530548 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530550 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551 }
552
Dhanashri Atre182b0272016-02-17 15:35:07 -0800553 pAdapter = (hdd_adapter_t *)context;
554 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
555 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
556 "Magic cookie(%x) for adapter sanity verification is invalid",
557 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530558 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 }
560
Dhanashri Atre182b0272016-02-17 15:35:07 -0800561 pHddCtx = pAdapter->pHddCtx;
562 if (unlikely(NULL == pHddCtx)) {
563 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
564 "%s: HDD context is Null", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530565 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 }
567
568 /* walk the chain until all are processed */
569 skb = (struct sk_buff *)rxBuf;
570
571 hdd_softap_dump_sk_buff(skb);
572
573 skb->dev = pAdapter->dev;
574
Dhanashri Atre182b0272016-02-17 15:35:07 -0800575 if (unlikely(skb->dev == NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530577 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 "%s: ERROR!!Invalid netdevice", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530579 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 }
581 cpu_index = wlan_hdd_get_cpu();
582 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
583 ++pAdapter->stats.rx_packets;
584 pAdapter->stats.rx_bytes += skb->len;
585
586 wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
587
588#ifdef QCA_PKT_PROTO_TRACE
589 if ((pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
590 (pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
591 proto_type = cds_pkt_get_proto_type(skb,
592 pHddCtx->config->
593 gEnableDebugLog, 0);
594 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
595 cds_pkt_trace_buf_update("HA:R:EPL");
596 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
597 cds_pkt_trace_buf_update("HA:R:DHC");
598 }
599 }
600#endif /* QCA_PKT_PROTO_TRACE */
601
602 skb->protocol = eth_type_trans(skb, skb->dev);
603#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530604 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800605 HDD_WAKE_LOCK_DURATION,
606 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
607#endif
608
609 /* Remove SKB from internal tracking table before submitting
610 * it to stack
611 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530612 qdf_net_buf_debug_release_skb(rxBuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613
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}