blob: fb4739fe9e6b1e84cefaccb929b53fbe463c9303 [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>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080042
43#ifdef IPA_OFFLOAD
44#include <wlan_hdd_ipa.h>
45#endif
46
47/* Preprocessor definitions and constants */
48#undef QCA_HDD_SAP_DUMP_SK_BUFF
49
50/* Type declarations */
51
52/* Function definitions and documenation */
53#ifdef QCA_HDD_SAP_DUMP_SK_BUFF
54/**
55 * hdd_softap_dump_sk_buff() - Dump an skb
56 * @skb: skb to dump
57 *
58 * Return: None
59 */
60static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
61{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053062 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063 "%s: head = %p ", __func__, skb->head);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064 /* QDF_TRACE( QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data); */
65 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080066 "%s: tail = %p ", __func__, skb->tail);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053067 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080068 "%s: end = %p ", __func__, skb->end);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053069 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070 "%s: len = %d ", __func__, skb->len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053071 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072 "%s: data_len = %d ", __func__, skb->data_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053073 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074 "%s: mac_len = %d", __func__, skb->mac_len);
75
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053076 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", skb->data[0],
78 skb->data[1], skb->data[2], skb->data[3], skb->data[4],
79 skb->data[5], skb->data[6], skb->data[7]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053080 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", skb->data[8],
82 skb->data[9], skb->data[10], skb->data[11], skb->data[12],
83 skb->data[13], skb->data[14], skb->data[15]);
84}
85#else
86static void hdd_softap_dump_sk_buff(struct sk_buff *skb)
87{
88}
89#endif
90
91#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
92/**
93 * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler
94 * @adapter_context: pointer to vdev adapter
95 *
96 * TX Q resume timer handler for SAP and P2P GO interface. If Blocked
97 * OS Q is not resumed during timeout period, to prevent permanent
98 * stall, resume OS Q forcefully for SAP and P2P GO interface.
99 *
100 * Return: None
101 */
102void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context)
103{
104 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
105
106 if (!pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530107 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108 "%s: INV ARG", __func__);
109 /* INVALID ARG */
110 return;
111 }
112
113 hddLog(LOG1, FL("Enabling queues"));
114 wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE,
115 WLAN_CONTROL_PATH);
116 return;
117}
118
119/**
120 * hdd_softap_tx_resume_cb() - Resume OS TX Q.
121 * @adapter_context: pointer to vdev apdapter
122 * @tx_resume: TX Q resume trigger
123 *
124 * Q was stopped due to WLAN TX path low resource condition
125 *
126 * Return: None
127 */
128void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume)
129{
130 hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context;
131
132 if (!pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530133 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 "%s: INV ARG", __func__);
135 /* INVALID ARG */
136 return;
137 }
138
139 /* Resume TX */
140 if (true == tx_resume) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530141 if (QDF_TIMER_STATE_STOPPED !=
142 qdf_mc_timer_get_current_state(&pAdapter->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 tx_flow_control_timer)) {
Anurag Chouhan210db072016-02-22 18:42:15 +0530144 qdf_mc_timer_stop(&pAdapter->tx_flow_control_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145 }
146
147 hddLog(LOG1, FL("Enabling queues"));
148 wlan_hdd_netif_queue_control(pAdapter,
149 WLAN_WAKE_ALL_NETIF_QUEUE,
150 WLAN_DATA_FLOW_CONTROL);
151 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152 return;
153}
154#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
155
156/**
157 * hdd_softap_hard_start_xmit() - Transmit a frame
158 * @skb: pointer to OS packet (sk_buff)
159 * @dev: pointer to network device
160 *
161 * Function registered with the Linux OS for transmitting
162 * packets. This version of the function directly passes
163 * the packet to Transport Layer.
164 *
165 * Return: Always returns NETDEV_TX_OK
166 */
167int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
168{
169 sme_ac_enum_type ac = SME_AC_BE;
170 hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev);
171 hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530172 struct qdf_mac_addr *pDestMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800173 uint8_t STAId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174#ifdef QCA_PKT_PROTO_TRACE
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800175 uint8_t proto_type = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176 hdd_context_t *hddCtxt = (hdd_context_t *) pAdapter->pHddCtx;
177#endif /* QCA_PKT_PROTO_TRACE */
178
179 ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
180 /* Prevent this function from being called during SSR since TL
181 * context may not be reinitialized at this time which may
182 * lead to a crash.
183 */
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800184 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530185 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800186 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187 goto drop_pkt;
188 }
189
190 /*
191 * If the device is operating on a DFS Channel
192 * then check if SAP is in CAC WAIT state and
193 * drop the packets. In CAC WAIT state device
194 * is expected not to transmit any frames.
195 * SAP starts Tx only after the BSS START is
196 * done.
197 */
198 if (pHddApCtx->dfs_cac_block_tx) {
199 goto drop_pkt;
200 }
201
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800202 /*
203 * If a transmit function is not registered, drop packet
204 */
205 if (!pAdapter->tx_fn) {
206 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
207 "%s: TX function not registered by the data path",
208 __func__);
209 goto drop_pkt;
210 }
211
Anurag Chouhan6d760662016-02-20 16:05:43 +0530212 pDestMacAddress = (struct qdf_mac_addr *) skb->data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213
Anurag Chouhanc5548422016-02-24 18:33:27 +0530214 if (qdf_is_macaddr_broadcast(pDestMacAddress) ||
215 qdf_is_macaddr_group(pDestMacAddress)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 /* The BC/MC station ID is assigned during BSS
217 * starting phase. SAP will return the station ID
218 * used for BC/MC traffic.
219 */
220 STAId = pHddApCtx->uBCStaId;
221 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530222 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 hdd_softap_get_sta_id(pAdapter,
224 pDestMacAddress, &STAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530225 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
226 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227 "%s: Failed to find right station", __func__);
228 goto drop_pkt;
229 }
230
231 if (STAId == HDD_WLAN_INVALID_STA_ID) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530232 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
233 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234 "%s: Failed to find right station", __func__);
235 goto drop_pkt;
236 } else if (false == pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530237 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
238 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239 "%s: STA %d is unregistered", __func__,
240 STAId);
241 goto drop_pkt;
242 }
243
244 if ((ol_txrx_peer_state_conn !=
245 pAdapter->aStaInfo[STAId].tlSTAState)
246 && (ol_txrx_peer_state_auth !=
247 pAdapter->aStaInfo[STAId].tlSTAState)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530248 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
249 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250 "%s: Station not connected yet", __func__);
251 goto drop_pkt;
252 } else if (ol_txrx_peer_state_conn ==
253 pAdapter->aStaInfo[STAId].tlSTAState) {
254 if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530255 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
256 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800257 "%s: NON-EAPOL packet in non-Authenticated state",
258 __func__);
259 goto drop_pkt;
260 }
261 }
262 }
263
264 hdd_get_tx_resource(pAdapter, STAId,
265 WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
266
267 /* Get TL AC corresponding to Qdisc queue index/AC. */
268 ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
269 ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
270
271#if defined (IPA_OFFLOAD)
Nirav Shahcbc6d722016-03-01 16:24:53 +0530272 if (!qdf_nbuf_ipa_owned_get(skb)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273#endif
274 /* Check if the buffer has enough header room */
275 skb = skb_unshare(skb, GFP_ATOMIC);
276 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800277 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278
279 if (skb_headroom(skb) < dev->hard_header_len) {
280 struct sk_buff *tmp;
281 tmp = skb;
282 skb = skb_realloc_headroom(tmp, dev->hard_header_len);
283 dev_kfree_skb(tmp);
284 if (!skb)
Jeff Johnsonedeff232015-11-11 17:19:42 -0800285 goto drop_pkt_accounting;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 }
287#if defined (IPA_OFFLOAD)
288 }
289#endif
290
291 wlan_hdd_log_eapol(skb,
292 WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED);
293
294#ifdef QCA_PKT_PROTO_TRACE
295 if ((hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
296 (hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
297 /* Proto Trace enabled */
298 proto_type = cds_pkt_get_proto_type(skb,
299 hddCtxt->config->
300 gEnableDebugLog, 0);
301 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
302 cds_pkt_trace_buf_update("HA:T:EPL");
303 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
304 cds_pkt_trace_buf_update("HA:T:DHC");
305 }
306 }
307#endif /* QCA_PKT_PROTO_TRACE */
308 pAdapter->stats.tx_bytes += skb->len;
309 ++pAdapter->stats.tx_packets;
310
311 /* Zero out skb's context buffer for the driver to use */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530312 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Nirav Shahcbc6d722016-03-01 16:24:53 +0530313 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
314 QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800315
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530316 qdf_dp_trace_set_track(skb);
317 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_PACKET_PTR_RECORD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318 (uint8_t *)skb->data, sizeof(skb->data)));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530319 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_PACKET_RECORD,
Nirav Shahcbc6d722016-03-01 16:24:53 +0530320 (uint8_t *)skb->data, qdf_nbuf_len(skb)));
321 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530322 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_HDD_PACKET_RECORD,
323 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
Nirav Shahcbc6d722016-03-01 16:24:53 +0530324 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800325
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800326#ifdef QCA_PKT_PROTO_TRACE
327 qdf_nbuf_trace_set_proto_type(skb, proto_type);
328#endif
329 if (pAdapter->tx_fn(ol_txrx_get_vdev_by_sta_id(STAId),
330 (qdf_nbuf_t) skb) != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530331 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800332 "%s: Failed to send packet to txrx for staid:%d",
333 __func__, STAId);
334 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
335 goto drop_pkt;
336 }
337 dev->trans_start = jiffies;
338
339 return NETDEV_TX_OK;
340
341drop_pkt:
342
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530343 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
Nirav Shahcbc6d722016-03-01 16:24:53 +0530344 (uint8_t *)skb->data, qdf_nbuf_len(skb)));
345 if (qdf_nbuf_len(skb) > QDF_DP_TRACE_RECORD_SIZE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530346 DPTRACE(qdf_dp_trace(skb, QDF_DP_TRACE_DROP_PACKET_RECORD,
347 (uint8_t *)&skb->data[QDF_DP_TRACE_RECORD_SIZE],
Nirav Shahcbc6d722016-03-01 16:24:53 +0530348 (qdf_nbuf_len(skb)-QDF_DP_TRACE_RECORD_SIZE)));
Jeff Johnsonedeff232015-11-11 17:19:42 -0800349 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800350
Jeff Johnsonedeff232015-11-11 17:19:42 -0800351drop_pkt_accounting:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352 ++pAdapter->stats.tx_dropped;
353 ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354
355 return NETDEV_TX_OK;
356}
357
358/**
359 * __hdd_softap_tx_timeout() - TX timeout handler
360 * @dev: pointer to network device
361 *
362 * This function is registered as a netdev ndo_tx_timeout method, and
363 * is invoked by the kernel if the driver takes too long to transmit a
364 * frame.
365 *
366 * Return: None
367 */
368static void __hdd_softap_tx_timeout(struct net_device *dev)
369{
370 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
371 hdd_context_t *hdd_ctx;
372
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530373 DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374 NULL, 0));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530375 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 "%s: Transmission timeout occurred", __func__);
377 /* Getting here implies we disabled the TX queues for too
378 * long. Queues are disabled either because of disassociation
379 * or low resource scenarios. In case of disassociation it is
380 * ok to ignore this. But if associated, we have do possible
381 * recovery here
382 */
383 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800384 if (cds_is_driver_recovering()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530385 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800386 "%s: Recovery in Progress. Ignore!!!", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 return;
388 }
389}
390
391/**
392 * hdd_softap_tx_timeout() - SSR wrapper for __hdd_softap_tx_timeout
393 * @dev: pointer to net_device
394 *
395 * Return: none
396 */
397void hdd_softap_tx_timeout(struct net_device *dev)
398{
399 cds_ssr_protect(__func__);
400 __hdd_softap_tx_timeout(dev);
401 cds_ssr_unprotect(__func__);
402}
403
404/**
405 * @hdd_softap_init_tx_rx() - Initialize Tx/RX module
406 * @pAdapter: pointer to adapter context
407 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530408 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
409 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800410 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530411QDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530413 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800414
415 uint8_t STAId = 0;
416
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530417 qdf_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418
419 spin_lock_init(&pAdapter->staInfo_lock);
420
421 for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530422 qdf_mem_zero(&pAdapter->aStaInfo[STAId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423 sizeof(hdd_station_info_t));
424 }
425
426 return status;
427}
428
429/**
430 * @hdd_softap_deinit_tx_rx() - Deinitialize Tx/RX module
431 * @pAdapter: pointer to adapter context
432 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530433 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
434 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530436QDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800437{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530438 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439
440 return status;
441}
442
443/**
444 * hdd_softap_init_tx_rx_sta() - Initialize tx/rx for a softap station
445 * @pAdapter: pointer to adapter context
446 * @STAId: Station ID to initialize
447 * @pmacAddrSTA: pointer to the MAC address of the station
448 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530449 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
450 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800451 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530452QDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530453 struct qdf_mac_addr *pmacAddrSTA)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454{
455 spin_lock_bh(&pAdapter->staInfo_lock);
456 if (pAdapter->aStaInfo[STAId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530457 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 "%s: Reinit station %d", __func__, STAId);
459 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530460 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800461 }
462
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530463 qdf_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800464
465 pAdapter->aStaInfo[STAId].isUsed = true;
466 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530467 qdf_copy_macaddr(&pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800468
469 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530470 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471}
472
473/**
474 * hdd_softap_deinit_tx_rx_sta() - Deinitialize tx/rx for a softap station
475 * @pAdapter: pointer to adapter context
476 * @STAId: Station ID to deinitialize
477 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530478 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
479 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530481QDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530483 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800484 hdd_hostapd_state_t *pHostapdState;
485
486 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
487
488 spin_lock_bh(&pAdapter->staInfo_lock);
489
490 if (false == pAdapter->aStaInfo[STAId].isUsed) {
491 spin_unlock_bh(&pAdapter->staInfo_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530492 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800493 "%s: Deinit station not inited %d", __func__, STAId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530494 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 }
496
497 pAdapter->aStaInfo[STAId].isUsed = false;
498 pAdapter->aStaInfo[STAId].isDeauthInProgress = false;
499
500 spin_unlock_bh(&pAdapter->staInfo_lock);
501 return status;
502}
503
504/**
505 * hdd_softap_rx_packet_cbk() - Receive packet handler
Dhanashri Atre182b0272016-02-17 15:35:07 -0800506 * @context: pointer to HDD context
Nirav Shahcbc6d722016-03-01 16:24:53 +0530507 * @rxBuf: pointer to rx qdf_nbuf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 *
509 * Receive callback registered with TL. TL will call this to notify
510 * the HDD when one or more packets were received for a registered
511 * STA.
512 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530513 * Return: QDF_STATUS_E_FAILURE if any errors encountered,
514 * QDF_STATUS_SUCCESS otherwise
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800516QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517{
518 hdd_adapter_t *pAdapter = NULL;
519 int rxstat;
520 unsigned int cpu_index;
521 struct sk_buff *skb = NULL;
522 hdd_context_t *pHddCtx = NULL;
523#ifdef QCA_PKT_PROTO_TRACE
524 uint8_t proto_type;
525#endif /* QCA_PKT_PROTO_TRACE */
526
527 /* Sanity check on inputs */
Dhanashri Atre182b0272016-02-17 15:35:07 -0800528 if (unlikely((NULL == context) || (NULL == rxBuf))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530529 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530 "%s: Null params being passed", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530531 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 }
533
Dhanashri Atre182b0272016-02-17 15:35:07 -0800534 pAdapter = (hdd_adapter_t *)context;
535 if (unlikely(WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
536 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_FATAL,
537 "Magic cookie(%x) for adapter sanity verification is invalid",
538 pAdapter->magic);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530539 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800540 }
541
Dhanashri Atre182b0272016-02-17 15:35:07 -0800542 pHddCtx = pAdapter->pHddCtx;
543 if (unlikely(NULL == pHddCtx)) {
544 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
545 "%s: HDD context is Null", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530546 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547 }
548
549 /* walk the chain until all are processed */
550 skb = (struct sk_buff *)rxBuf;
551
552 hdd_softap_dump_sk_buff(skb);
553
554 skb->dev = pAdapter->dev;
555
Dhanashri Atre182b0272016-02-17 15:35:07 -0800556 if (unlikely(skb->dev == NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530558 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 "%s: ERROR!!Invalid netdevice", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530560 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 }
562 cpu_index = wlan_hdd_get_cpu();
563 ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
564 ++pAdapter->stats.rx_packets;
565 pAdapter->stats.rx_bytes += skb->len;
566
567 wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
568
569#ifdef QCA_PKT_PROTO_TRACE
570 if ((pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
571 (pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
572 proto_type = cds_pkt_get_proto_type(skb,
573 pHddCtx->config->
574 gEnableDebugLog, 0);
575 if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
576 cds_pkt_trace_buf_update("HA:R:EPL");
577 } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
578 cds_pkt_trace_buf_update("HA:R:DHC");
579 }
580 }
581#endif /* QCA_PKT_PROTO_TRACE */
582
583 skb->protocol = eth_type_trans(skb, skb->dev);
584#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530585 qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586 HDD_WAKE_LOCK_DURATION,
587 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
588#endif
589
590 /* Remove SKB from internal tracking table before submitting
591 * it to stack
592 */
Nirav Shahcbc6d722016-03-01 16:24:53 +0530593 qdf_net_buf_debug_release_skb(rxBuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594
Orhan K AKYILDIZ4f20db52015-12-30 12:35:44 -0800595 if (hdd_napi_enabled(HDD_NAPI_ANY) && !pHddCtx->config->enableRxThread)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596 rxstat = netif_receive_skb(skb);
597 else
598 rxstat = netif_rx_ni(skb);
599 if (NET_RX_SUCCESS == rxstat) {
600 ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
601 } else {
602 ++pAdapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];
603 }
604
605 pAdapter->dev->last_rx = jiffies;
606
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530607 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608}
609
610/**
611 * hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
612 * @pAdapter: pointer to adapter context
613 * @staId: Station ID to deregister
614 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530615 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530617QDF_STATUS hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530619 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 hdd_context_t *pHddCtx;
621
622 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530623 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 "%s: pAdapter is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530625 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626 }
627
628 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530629 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630 "%s: Invalid pAdapter magic", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530631 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632 }
633
634 pHddCtx = (hdd_context_t *) (pAdapter->pHddCtx);
635 /* Clear station in TL and then update HDD data
636 * structures. This helps to block RX frames from other
637 * station to this station.
638 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530639 qdf_status = ol_txrx_clear_peer(staId);
640 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530641 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642 "ol_txrx_clear_peer() failed to for staID %d. "
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530643 "Status= %d [0x%08X]", staId, qdf_status, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800644 }
645
646 if (pAdapter->aStaInfo[staId].isUsed) {
647 spin_lock_bh(&pAdapter->staInfo_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530648 qdf_mem_zero(&pAdapter->aStaInfo[staId],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 sizeof(hdd_station_info_t));
650 spin_unlock_bh(&pAdapter->staInfo_lock);
651 }
652 pHddCtx->sta_to_adapter[staId] = NULL;
653
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530654 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655}
656
657/**
658 * hdd_softap_register_sta() - Register a SoftAP STA
659 * @pAdapter: pointer to adapter context
660 * @fAuthRequired: is additional authentication required?
661 * @fPrivacyBit: should 802.11 privacy bit be set?
662 * @staId: station ID assigned to this station
663 * @ucastSig: unicast security signature
664 * @bcastSig: broadcast security signature
665 * @pPeerMacAddress: station MAC address
666 * @fWmmEnabled: is WMM enabled for this STA?
667 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530668 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530670QDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671 bool fAuthRequired,
672 bool fPrivacyBit,
673 uint8_t staId,
674 uint8_t ucastSig,
675 uint8_t bcastSig,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530676 struct qdf_mac_addr *pPeerMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 bool fWmmEnabled)
678{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530679 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 struct ol_txrx_desc_type staDesc = { 0 };
681 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800682 struct ol_txrx_ops txrx_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683
684 /*
685 * Clean up old entry if it is not cleaned up properly
686 */
687 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530688 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689 "clean up old entry for STA %d", staId);
690 hdd_softap_deregister_sta(pAdapter, staId);
691 }
692 /* Get the Station ID from the one saved during the assocation. */
693
694 staDesc.sta_id = staId;
695
696 /*Save the pAdapter Pointer for this staId */
697 pHddCtx->sta_to_adapter[staId] = pAdapter;
698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 hdd_softap_init_tx_rx_sta(pAdapter, staId,
701 pPeerMacAddress);
702
703 staDesc.is_qos_enabled = fWmmEnabled;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530704 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 "HDD SOFTAP register TL QoS_enabled=%d",
706 staDesc.is_qos_enabled);
707
Dhanashri Atre182b0272016-02-17 15:35:07 -0800708 qdf_status = ol_txrx_register_peer(&staDesc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530709 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530710 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 "SOFTAP ol_txrx_register_peer() failed to register. Status= %d [0x%08X]",
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530712 qdf_status, qdf_status);
713 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 }
715
Dhanashri Atre182b0272016-02-17 15:35:07 -0800716 /* Register the vdev transmit and receive functions */
717 qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
718 txrx_ops.rx.rx = hdd_softap_rx_packet_cbk;
719 ol_txrx_vdev_register(
720 ol_txrx_get_vdev_from_vdev_id(pAdapter->sessionId),
721 pAdapter, &txrx_ops);
Dhanashri Atre168d2b42016-02-22 14:43:06 -0800722 pAdapter->tx_fn = txrx_ops.tx.tx;
Dhanashri Atre182b0272016-02-17 15:35:07 -0800723
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 /* if ( WPA ), tell TL to go to 'connected' and after keys come to the
725 * driver then go to 'authenticated'. For all other authentication
726 * types (those that do not require upper layer authentication) we can
727 * put TL directly into 'authenticated' state
728 */
729
730 pAdapter->aStaInfo[staId].ucSTAId = staId;
731 pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled;
732
733 if (!fAuthRequired) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530734 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800735 "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time",
736 pAdapter->aStaInfo[staId].ucSTAId);
737
738 /* Connections that do not need Upper layer auth,
739 * transition TL directly to 'Authenticated' state.
740 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530741 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742 ol_txrx_peer_state_auth, false);
743
744 pAdapter->aStaInfo[staId].tlSTAState = ol_txrx_peer_state_auth;
745 pAdapter->sessionCtx.ap.uIsAuthenticated = true;
746 } else {
747
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530748 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800749 "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time",
750 pAdapter->aStaInfo[staId].ucSTAId);
751
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530752 qdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753 ol_txrx_peer_state_conn, false);
754 pAdapter->aStaInfo[staId].tlSTAState = ol_txrx_peer_state_conn;
755
756 pAdapter->sessionCtx.ap.uIsAuthenticated = false;
757
758 }
759
760 /* Enable Tx queue */
761 hddLog(LOG1, FL("Enabling queues"));
762 wlan_hdd_netif_queue_control(pAdapter,
763 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
764 WLAN_CONTROL_PATH);
765
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767}
768
769/**
770 * hdd_softap_register_bc_sta() - Register the SoftAP broadcast STA
771 * @pAdapter: pointer to adapter context
772 * @fPrivacyBit: should 802.11 privacy bit be set?
773 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530774 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530776QDF_STATUS hdd_softap_register_bc_sta(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 bool fPrivacyBit)
778{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530779 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +0530781 struct qdf_mac_addr broadcastMacAddr =
782 QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 hdd_ap_ctx_t *pHddApCtx;
784
785 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
786
787 pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter;
788#ifdef WLAN_FEATURE_MBSSID
789 pHddCtx->sta_to_adapter[pHddApCtx->uBCStaId] = pAdapter;
790#else
791 pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter;
792#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530793 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 hdd_softap_register_sta(pAdapter, false, fPrivacyBit,
795 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
796 uBCStaId, 0, 1, &broadcastMacAddr, 0);
797
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530798 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799}
800
801/**
802 * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA
803 * @pAdapter: pointer to adapter context
804 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530805 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530807QDF_STATUS hdd_softap_deregister_bc_sta(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808{
809 return hdd_softap_deregister_sta(pAdapter,
810 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->
811 uBCStaId);
812}
813
814/**
815 * hdd_softap_stop_bss() - Stop the BSS
816 * @pAdapter: pointer to adapter context
817 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530818 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530820QDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530822 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 uint8_t staId = 0;
824 hdd_context_t *pHddCtx;
825 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
826
827 /* bss deregister is not allowed during wlan driver loading or
828 * unloading
829 */
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800830 if (cds_is_load_or_unload_in_progress()) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530831 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800832 "%s: Loading_unloading in Progress, state: 0x%x. Ignore!!!",
833 __func__, cds_get_driver_state());
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530834 return QDF_STATUS_E_PERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835 }
836
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530837 qdf_status = hdd_softap_deregister_bc_sta(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530839 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530840 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 "%s: Failed to deregister BC sta Id %d", __func__,
842 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId);
843 }
844
845 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) {
846 /* This excludes BC sta as it is already deregistered */
847 if (pAdapter->aStaInfo[staId].isUsed) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530848 qdf_status = hdd_softap_deregister_sta(pAdapter, staId);
849 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530850 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
851 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852 "%s: Failed to deregister sta Id %d",
853 __func__, staId);
854 }
855 }
856 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530857 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858}
859
860/**
861 * hdd_softap_change_sta_state() - Change the state of a SoftAP station
862 * @pAdapter: pointer to adapter context
863 * @pDestMacAddress: MAC address of the station
864 * @state: new state of the station
865 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530866 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530868QDF_STATUS hdd_softap_change_sta_state(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530869 struct qdf_mac_addr *pDestMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800870 enum ol_txrx_peer_state state)
871{
872 uint8_t ucSTAId = WLAN_MAX_STA_COUNT;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530873 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530875 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876 "%s: enter", __func__);
877
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530878 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 hdd_softap_get_sta_id(pAdapter,
880 pDestMacAddress, &ucSTAId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530881 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 "%s: Failed to find right station", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530883 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 }
885
886 if (false ==
Anurag Chouhanc5548422016-02-24 18:33:27 +0530887 qdf_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 pDestMacAddress)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530889 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890 "%s: Station MAC address does not matching",
891 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530892 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893 }
894
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530895 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896 hdd_change_peer_state(pAdapter, ucSTAId, state, false);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530897 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898 "%s: change station to state %d succeed", __func__, state);
899
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530900 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901 pAdapter->aStaInfo[ucSTAId].tlSTAState =
902 ol_txrx_peer_state_auth;
903 }
904
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530905 QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 "%s exit", __func__);
907
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530908 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909}
910
911/*
912 * hdd_softap_get_sta_id() - Find station ID from MAC address
913 * @pAdapter: pointer to adapter context
914 * @pDestMacAddress: MAC address of the destination
915 * @staId: Station ID associated with the MAC address
916 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530917 * Return: QDF_STATUS_SUCCESS if a match was found, in which case
918 * staId is populated, QDF_STATUS_E_FAILURE if a match is
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919 * not found
920 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530921QDF_STATUS hdd_softap_get_sta_id(hdd_adapter_t *pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530922 struct qdf_mac_addr *pMacAddress,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 uint8_t *staId)
924{
925 uint8_t i;
926
927 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530928 if (!qdf_mem_cmp
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929 (&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530930 QDF_MAC_ADDR_SIZE) && pAdapter->aStaInfo[i].isUsed) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 *staId = i;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530932 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800933 }
934 }
935
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530936 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800937}