1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* denote that this file does not allow legacy hddLog */
21 #define HDD_DISALLOW_LEGACY_HDDLOG 1
22 
23 /* Include files */
24 #include <linux/semaphore.h>
25 #include "osif_sync.h"
26 #include <wlan_hdd_tx_rx.h>
27 #include <wlan_hdd_softap_tx_rx.h>
28 #include <linux/netdevice.h>
29 #include <linux/skbuff.h>
30 #include <linux/etherdevice.h>
31 #include <qdf_types.h>
32 #include <ani_global.h>
33 #include <qdf_types.h>
34 #include <net/ieee80211_radiotap.h>
35 #include <cds_sched.h>
36 #include <cdp_txrx_cmn.h>
37 #include <cdp_txrx_peer_ops.h>
38 #include <cds_utils.h>
39 #include <cdp_txrx_flow_ctrl_v2.h>
40 #include <cdp_txrx_misc.h>
41 #include <wlan_hdd_object_manager.h>
42 #include "wlan_p2p_ucfg_api.h"
43 #include <wlan_hdd_regulatory.h>
44 #include "wlan_ipa_ucfg_api.h"
45 #include "wlan_dp_ucfg_api.h"
46 #include "wlan_policy_mgr_ucfg.h"
47 #include <wma_types.h>
48 #include "wlan_hdd_sta_info.h"
49 #include "ol_defines.h"
50 #include <wlan_hdd_sar_limits.h>
51 #include "wlan_hdd_tsf.h"
52 #include "wlan_hdd_wds.h"
53 #include <cdp_txrx_ctrl.h>
54 #ifdef FEATURE_WDS
55 #include <net/llc_pdu.h>
56 #endif
57 #include <os_if_dp.h>
58 #include <cfg_ucfg_api.h>
59 #include <wlan_twt_ucfg_ext_api.h>
60 #include "wlan_hdd_stats.h"
61 
62 /* Preprocessor definitions and constants */
63 #undef QCA_HDD_SAP_DUMP_SK_BUFF
64 
65 /* Type declarations */
66 #ifdef FEATURE_WDS
67 /**
68  * struct l2_update_frame - Layer-2 update frame format
69  * @eh: ethernet header
70  * @l2_update_pdu: llc pdu format
71  * @l2_update_xid_info: xid command information field
72  */
73 struct l2_update_frame {
74 	struct ethhdr eh;
75 	struct llc_pdu_un l2_update_pdu;
76 	struct llc_xid_info l2_update_xid_info;
77 } qdf_packed;
78 #endif
79 
80 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
hdd_softap_tx_resume_timer_expired_handler(void * adapter_context)81 void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context)
82 {
83 	struct hdd_adapter *adapter = (struct hdd_adapter *) adapter_context;
84 
85 	if (!adapter) {
86 		hdd_err("NULL adapter");
87 		return;
88 	}
89 
90 	hdd_debug("Enabling queues");
91 	wlan_hdd_netif_queue_control(adapter, WLAN_WAKE_ALL_NETIF_QUEUE,
92 				     WLAN_CONTROL_PATH);
93 }
94 
95 /**
96  * hdd_softap_tx_resume_false() - Resume OS TX Q false leads to queue disabling
97  * @adapter: pointer to hdd adapter
98  * @tx_resume: TX Q resume trigger
99  *
100  *
101  * Return: None
102  */
103 static void
hdd_softap_tx_resume_false(struct hdd_adapter * adapter,bool tx_resume)104 hdd_softap_tx_resume_false(struct hdd_adapter *adapter, bool tx_resume)
105 {
106 	QDF_STATUS status;
107 	qdf_mc_timer_t *fc_timer;
108 
109 	if (true == tx_resume)
110 		return;
111 
112 	hdd_debug("Disabling queues");
113 	wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE,
114 				     WLAN_DATA_FLOW_CONTROL);
115 
116 	fc_timer = &adapter->tx_flow_control_timer;
117 	if (QDF_TIMER_STATE_STOPPED != qdf_mc_timer_get_current_state(fc_timer))
118 		return;
119 
120 	status = qdf_mc_timer_start(fc_timer,
121 				    WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME);
122 
123 	if (QDF_IS_STATUS_ERROR(status))
124 		hdd_err("Failed to start tx_flow_control_timer");
125 	else
126 		adapter->deflink->hdd_stats.tx_rx_stats.txflow_timer_cnt++;
127 }
128 
hdd_softap_tx_resume_cb(void * adapter_context,bool tx_resume)129 void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume)
130 {
131 	struct hdd_adapter *adapter = (struct hdd_adapter *) adapter_context;
132 
133 	if (!adapter) {
134 		hdd_err("NULL adapter");
135 		return;
136 	}
137 
138 	/* Resume TX  */
139 	if (true == tx_resume) {
140 		if (QDF_TIMER_STATE_STOPPED !=
141 		    qdf_mc_timer_get_current_state(&adapter->
142 						   tx_flow_control_timer)) {
143 			qdf_mc_timer_stop(&adapter->tx_flow_control_timer);
144 		}
145 
146 		hdd_debug("Enabling queues");
147 		wlan_hdd_netif_queue_control(adapter,
148 					WLAN_WAKE_ALL_NETIF_QUEUE,
149 					WLAN_DATA_FLOW_CONTROL);
150 	}
151 	hdd_softap_tx_resume_false(adapter, tx_resume);
152 }
153 #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
154 
155 #ifndef MDM_PLATFORM
hdd_ipa_update_rx_mcbc_stats(struct hdd_adapter * adapter,struct sk_buff * skb)156 void hdd_ipa_update_rx_mcbc_stats(struct hdd_adapter *adapter,
157 				  struct sk_buff *skb)
158 {
159 	struct hdd_station_info *hdd_sta_info;
160 	struct qdf_mac_addr *src_mac;
161 	qdf_ether_header_t *eh;
162 
163 	src_mac = (struct qdf_mac_addr *)(skb->data +
164 					  QDF_NBUF_SRC_MAC_OFFSET);
165 
166 	hdd_sta_info = hdd_get_sta_info_by_mac(
167 				&adapter->sta_info_list,
168 				src_mac->bytes,
169 				STA_INFO_SOFTAP_IPA_RX_PKT_CALLBACK);
170 	if (!hdd_sta_info)
171 		return;
172 
173 	if (qdf_nbuf_data_is_ipv4_mcast_pkt(skb->data))
174 		hdd_sta_info->rx_mc_bc_cnt++;
175 
176 	eh = (qdf_ether_header_t *)qdf_nbuf_data(skb);
177 	if (QDF_IS_ADDR_BROADCAST(eh->ether_dhost))
178 		hdd_sta_info->rx_mc_bc_cnt++;
179 
180 	hdd_put_sta_info_ref(&adapter->sta_info_list, &hdd_sta_info,
181 			     true, STA_INFO_SOFTAP_IPA_RX_PKT_CALLBACK);
182 }
183 #else
hdd_ipa_update_rx_mcbc_stats(struct hdd_adapter * adapter,struct sk_buff * skb)184 void hdd_ipa_update_rx_mcbc_stats(struct hdd_adapter *adapter,
185 				  struct sk_buff *skb)
186 {
187 }
188 #endif
189 
190 /**
191  * __hdd_softap_hard_start_xmit() - Transmit a frame
192  * @skb: pointer to OS packet (sk_buff)
193  * @dev: pointer to network device
194  *
195  * Function registered with the Linux OS for transmitting
196  * packets. This version of the function directly passes
197  * the packet to Datapath Layer.
198  * In case of any error, drop the packet.
199  *
200  * Return: None
201  */
__hdd_softap_hard_start_xmit(struct sk_buff * skb,struct net_device * dev)202 static void __hdd_softap_hard_start_xmit(struct sk_buff *skb,
203 					 struct net_device *dev)
204 {
205 	sme_ac_enum_type ac = SME_AC_BE;
206 	struct hdd_adapter *adapter = (struct hdd_adapter *)netdev_priv(dev);
207 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
208 	struct hdd_tx_rx_stats *stats =
209 				&adapter->deflink->hdd_stats.tx_rx_stats;
210 	int cpu = qdf_get_smp_processor_id();
211 	QDF_STATUS status;
212 
213 	osif_dp_mark_pkt_type(skb);
214 	hdd_tx_latency_record_ingress_ts(adapter, skb);
215 
216 	/* Get TL AC corresponding to Qdisc queue index/AC. */
217 	ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping];
218 	++stats->per_cpu[cpu].tx_classified_ac[ac];
219 
220 	status = ucfg_dp_softap_start_xmit((qdf_nbuf_t)skb,
221 					   adapter->deflink->vdev);
222 	if (QDF_IS_STATUS_ERROR(status))
223 		++stats->per_cpu[cpu].tx_dropped_ac[ac];
224 
225 	netif_trans_update(dev);
226 
227 	wlan_hdd_sar_unsolicited_timer_start(hdd_ctx);
228 }
229 
hdd_softap_hard_start_xmit(struct sk_buff * skb,struct net_device * net_dev)230 netdev_tx_t hdd_softap_hard_start_xmit(struct sk_buff *skb,
231 				       struct net_device *net_dev)
232 {
233 	__hdd_softap_hard_start_xmit(skb, net_dev);
234 
235 	return NETDEV_TX_OK;
236 }
237 
hdd_softap_ipa_start_xmit(qdf_nbuf_t nbuf,qdf_netdev_t dev)238 QDF_STATUS hdd_softap_ipa_start_xmit(qdf_nbuf_t nbuf, qdf_netdev_t dev)
239 {
240 	if (NETDEV_TX_OK == hdd_softap_hard_start_xmit(
241 					(struct sk_buff *)nbuf,
242 					(struct net_device *)dev))
243 		return QDF_STATUS_SUCCESS;
244 	else
245 		return QDF_STATUS_E_FAILURE;
246 }
247 
__hdd_softap_tx_timeout(struct net_device * dev)248 static void __hdd_softap_tx_timeout(struct net_device *dev)
249 {
250 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
251 	struct hdd_context *hdd_ctx;
252 	struct wlan_objmgr_vdev *vdev;
253 	struct netdev_queue *txq;
254 	int i;
255 
256 	DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
257 			QDF_TRACE_DEFAULT_PDEV_ID,
258 			NULL, 0, QDF_TX));
259 	/* Getting here implies we disabled the TX queues for too
260 	 * long. Queues are disabled either because of disassociation
261 	 * or low resource scenarios. In case of disassociation it is
262 	 * ok to ignore this. But if associated, we have do possible
263 	 * recovery here
264 	 */
265 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
266 	if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
267 		QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR,
268 			 "%s: Recovery in Progress. Ignore!!!", __func__);
269 		return;
270 	}
271 
272 	if (hdd_ctx->hdd_wlan_suspended) {
273 		hdd_debug("wlan is suspended, ignore timeout");
274 		return;
275 	}
276 
277 	TX_TIMEOUT_TRACE(dev, QDF_MODULE_ID_HDD_SAP_DATA);
278 
279 	for (i = 0; i < NUM_TX_QUEUES; i++) {
280 		txq = netdev_get_tx_queue(dev, i);
281 		QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
282 			  QDF_TRACE_LEVEL_DEBUG,
283 			  "Queue: %d status: %d txq->trans_start: %lu",
284 			  i, netif_tx_queue_stopped(txq), txq->trans_start);
285 	}
286 
287 	wlan_hdd_display_adapter_netif_queue_history(adapter);
288 
289 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
290 	if (vdev) {
291 		ucfg_dp_softap_tx_timeout(vdev);
292 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
293 	}
294 
295 	QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
296 			"carrier state: %d", netif_carrier_ok(dev));
297 }
298 
299 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
hdd_softap_tx_timeout(struct net_device * net_dev,unsigned int txqueue)300 void hdd_softap_tx_timeout(struct net_device *net_dev, unsigned int txqueue)
301 #else
302 void hdd_softap_tx_timeout(struct net_device *net_dev)
303 #endif
304 {
305 	struct osif_vdev_sync *vdev_sync;
306 
307 	if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
308 		return;
309 
310 	__hdd_softap_tx_timeout(net_dev);
311 
312 	osif_vdev_sync_op_stop(vdev_sync);
313 }
314 
315 static void
hdd_reset_sta_info_during_reattach(struct hdd_station_info * sta_info)316 hdd_reset_sta_info_during_reattach(struct hdd_station_info *sta_info)
317 {
318 	sta_info->in_use = 0;
319 	sta_info->sta_id = 0;
320 	sta_info->sta_type = 0;
321 	qdf_mem_zero(&sta_info->sta_mac, QDF_MAC_ADDR_SIZE);
322 	sta_info->peer_state = 0;
323 	sta_info->is_qos_enabled = 0;
324 	sta_info->is_deauth_in_progress = 0;
325 	sta_info->nss = 0;
326 	sta_info->rate_flags = 0;
327 	sta_info->ecsa_capable = 0;
328 	sta_info->max_phy_rate = 0;
329 	sta_info->tx_packets = 0;
330 	sta_info->tx_bytes = 0;
331 	sta_info->rx_packets = 0;
332 	sta_info->rx_bytes = 0;
333 	sta_info->last_tx_rx_ts = 0;
334 	sta_info->assoc_ts = 0;
335 	sta_info->disassoc_ts = 0;
336 	sta_info->tx_rate = 0;
337 	sta_info->rx_rate = 0;
338 	sta_info->ampdu = 0;
339 	sta_info->sgi_enable = 0;
340 	sta_info->tx_stbc = 0;
341 	sta_info->rx_stbc = 0;
342 	sta_info->ch_width = 0;
343 	sta_info->mode = 0;
344 	sta_info->max_supp_idx = 0;
345 	sta_info->max_ext_idx = 0;
346 	sta_info->max_mcs_idx = 0;
347 	sta_info->rx_mcs_map = 0;
348 	sta_info->tx_mcs_map = 0;
349 	sta_info->freq = 0;
350 	sta_info->dot11_mode = 0;
351 	sta_info->ht_present = 0;
352 	sta_info->vht_present = 0;
353 	qdf_mem_zero(&sta_info->ht_caps, sizeof(sta_info->ht_caps));
354 	qdf_mem_zero(&sta_info->vht_caps, sizeof(sta_info->vht_caps));
355 	sta_info->reason_code = 0;
356 	sta_info->rssi = 0;
357 	sta_info->dhcp_phase = 0;
358 	sta_info->dhcp_nego_status = 0;
359 	sta_info->capability = 0;
360 	sta_info->support_mode = 0;
361 	sta_info->rx_retry_cnt = 0;
362 	sta_info->rx_mc_bc_cnt = 0;
363 
364 	if (sta_info->assoc_req_ies.len) {
365 		qdf_mem_free(sta_info->assoc_req_ies.ptr);
366 		sta_info->assoc_req_ies.ptr = NULL;
367 		sta_info->assoc_req_ies.len = 0;
368 	}
369 
370 	sta_info->pending_eap_frm_type = 0;
371 }
372 
373 /**
374  * hdd_sta_info_re_attach() - Re-Attach the station info structure into the list
375  * @sta_info_container: The station info container obj that stores and maintains
376  *                      the sta_info obj.
377  * @sta_info: The station info structure that is to be attached to the
378  *            container object.
379  * @sta_mac: MAC address of the station
380  *
381  * This function re-attaches the station if it gets re-connect after
382  * disconnecting and before its all references are released.
383  *
384  * Return: QDF STATUS SUCCESS on successful attach, error code otherwise
385  */
hdd_sta_info_re_attach(struct hdd_sta_info_obj * sta_info_container,struct hdd_station_info * sta_info,struct qdf_mac_addr * sta_mac)386 static QDF_STATUS hdd_sta_info_re_attach(
387 				struct hdd_sta_info_obj *sta_info_container,
388 				struct hdd_station_info *sta_info,
389 				struct qdf_mac_addr *sta_mac)
390 {
391 	if (!sta_info_container || !sta_info) {
392 		hdd_err("Parameter(s) null");
393 		return QDF_STATUS_E_INVAL;
394 	}
395 
396 	qdf_spin_lock_bh(&sta_info_container->sta_obj_lock);
397 
398 	if (sta_info->is_attached) {
399 		qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock);
400 		hdd_err("sta info is already attached");
401 		return QDF_STATUS_SUCCESS;
402 	}
403 
404 	hdd_reset_sta_info_during_reattach(sta_info);
405 	/* Add one extra ref for reattach */
406 	hdd_take_sta_info_ref(sta_info_container, sta_info, false,
407 			      STA_INFO_ATTACH_DETACH);
408 	qdf_mem_copy(&sta_info->sta_mac, sta_mac, sizeof(struct qdf_mac_addr));
409 	sta_info->is_attached = true;
410 	qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock);
411 
412 	return QDF_STATUS_SUCCESS;
413 }
414 
hdd_softap_init_tx_rx_sta(struct hdd_adapter * adapter,struct qdf_mac_addr * sta_mac)415 QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter,
416 				     struct qdf_mac_addr *sta_mac)
417 {
418 	struct hdd_station_info *sta_info;
419 	QDF_STATUS status;
420 
421 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
422 					   sta_mac->bytes,
423 					   STA_INFO_SOFTAP_INIT_TX_RX_STA);
424 
425 	if (sta_info) {
426 		hdd_err("Reinit of in use station " QDF_MAC_ADDR_FMT,
427 			QDF_MAC_ADDR_REF(sta_mac->bytes));
428 		status = hdd_sta_info_re_attach(&adapter->sta_info_list,
429 						sta_info, sta_mac);
430 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
431 				     STA_INFO_SOFTAP_INIT_TX_RX_STA);
432 		return status;
433 	}
434 
435 	sta_info = qdf_mem_malloc(sizeof(struct hdd_station_info));
436 	if (!sta_info)
437 		return QDF_STATUS_E_NOMEM;
438 
439 	sta_info->is_deauth_in_progress = false;
440 	qdf_mem_copy(&sta_info->sta_mac, sta_mac, sizeof(struct qdf_mac_addr));
441 
442 	status = hdd_sta_info_attach(&adapter->sta_info_list, sta_info);
443 	if (QDF_IS_STATUS_ERROR(status)) {
444 		hdd_err("Failed to attach station: " QDF_MAC_ADDR_FMT,
445 			QDF_MAC_ADDR_REF(sta_mac->bytes));
446 		qdf_mem_free(sta_info);
447 	}
448 
449 	return status;
450 }
451 
hdd_softap_deregister_sta(struct hdd_adapter * adapter,struct hdd_station_info ** sta_info)452 QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter,
453 				     struct hdd_station_info **sta_info)
454 {
455 	struct hdd_context *hdd_ctx;
456 	struct qdf_mac_addr *mac_addr;
457 	struct hdd_station_info *sta = *sta_info;
458 	struct hdd_ap_ctx *ap_ctx;
459 	struct wlan_objmgr_vdev *vdev;
460 
461 	if (!adapter) {
462 		hdd_err("NULL adapter");
463 		return QDF_STATUS_E_INVAL;
464 	}
465 
466 	if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
467 		hdd_err("Invalid adapter magic");
468 		return QDF_STATUS_E_INVAL;
469 	}
470 
471 	if (!sta) {
472 		hdd_err("Invalid station");
473 		return QDF_STATUS_E_INVAL;
474 	}
475 
476 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
477 
478 	if (!hdd_ctx) {
479 		hdd_err("HDD context is null");
480 		return QDF_STATUS_E_INVAL;
481 	}
482 
483 	/*
484 	 * If the address is a broadcast address then the CDP layers expects
485 	 * the self mac address of the adapter.
486 	 */
487 	if (QDF_IS_ADDR_BROADCAST(sta->sta_mac.bytes)) {
488 		mac_addr = &adapter->mac_addr;
489 	} else {
490 		if (wlan_vdev_mlme_is_mlo_vdev(adapter->deflink->vdev) &&
491 		    !qdf_is_macaddr_zero(&sta->mld_addr))
492 			mac_addr = &sta->mld_addr;
493 		else
494 			mac_addr = &sta->sta_mac;
495 	}
496 
497 	if (ucfg_ipa_is_enabled()) {
498 		if (ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev,
499 				      adapter->device_mode,
500 				      adapter->deflink->vdev_id,
501 				      WLAN_IPA_CLIENT_DISCONNECT,
502 				      mac_addr->bytes,
503 				      false) != QDF_STATUS_SUCCESS)
504 			hdd_debug("WLAN_CLIENT_DISCONNECT event failed");
505 	}
506 
507 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
508 	if (!vdev)
509 		return QDF_STATUS_E_INVAL;
510 
511 	ucfg_dp_del_latency_critical_client(vdev, sta->dot11_mode);
512 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
513 
514 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
515 	if (!QDF_IS_ADDR_BROADCAST(sta->sta_mac.bytes) &&
516 	    sta->dot11_mode < QCA_WLAN_802_11_MODE_INVALID)
517 		ap_ctx->client_count[sta->dot11_mode]--;
518 
519 	hdd_sta_info_detach(&adapter->sta_info_list, &sta);
520 
521 	ucfg_mlme_update_oce_flags(hdd_ctx->pdev);
522 
523 	return QDF_STATUS_SUCCESS;
524 }
525 
hdd_softap_register_sta(struct wlan_hdd_link_info * link_info,bool auth_required,bool privacy_required,struct qdf_mac_addr * sta_mac,tSap_StationAssocReassocCompleteEvent * event)526 QDF_STATUS hdd_softap_register_sta(struct wlan_hdd_link_info *link_info,
527 				   bool auth_required, bool privacy_required,
528 				   struct qdf_mac_addr *sta_mac,
529 				   tSap_StationAssocReassocCompleteEvent *event)
530 {
531 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
532 	struct ol_txrx_desc_type txrx_desc = {0};
533 	struct hdd_adapter *adapter = link_info->adapter;
534 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
535 	struct ol_txrx_ops txrx_ops;
536 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
537 	struct hdd_ap_ctx *ap_ctx;
538 	struct hdd_station_info *sta_info;
539 	bool wmm_enabled = false;
540 	enum qca_wlan_802_11_mode dot11mode = QCA_WLAN_802_11_MODE_INVALID;
541 	bool is_macaddr_broadcast = false;
542 	enum phy_ch_width ch_width;
543 	struct wlan_objmgr_vdev *vdev;
544 
545 	if (event) {
546 		wmm_enabled = event->wmmEnabled;
547 		dot11mode = hdd_convert_dot11mode_from_phymode(event->chan_info.info);
548 	}
549 
550 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
551 
552 	/*
553 	 * If the address is a broadcast address, then provide the self mac addr
554 	 * to the data path. Else provide the mac address of the connected peer.
555 	 */
556 	if (qdf_is_macaddr_broadcast(sta_mac)) {
557 		qdf_mem_copy(&txrx_desc.peer_addr, &adapter->mac_addr,
558 			     QDF_MAC_ADDR_SIZE);
559 		is_macaddr_broadcast = true;
560 	} else {
561 		qdf_mem_copy(&txrx_desc.peer_addr, sta_mac,
562 			     QDF_MAC_ADDR_SIZE);
563 	}
564 
565 	qdf_status = hdd_softap_init_tx_rx_sta(adapter, sta_mac);
566 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
567 					   sta_mac->bytes,
568 					   STA_INFO_SOFTAP_REGISTER_STA);
569 
570 	if (!sta_info) {
571 		hdd_debug("STA not found");
572 		return QDF_STATUS_E_INVAL;
573 	}
574 
575 	txrx_desc.is_qos_enabled = wmm_enabled;
576 
577 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_DP_ID);
578 	if (!vdev)
579 		return QDF_STATUS_E_INVAL;
580 
581 	ucfg_dp_add_latency_critical_client(vdev, dot11mode);
582 
583 	if (is_macaddr_broadcast) {
584 		/*
585 		 * Register the vdev transmit and receive functions once with
586 		 * CDP layer. Broadcast STA is registered only once when BSS is
587 		 * started.
588 		 */
589 		qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
590 		txrx_ops.tx.tx_classify_critical_pkt_cb =
591 					hdd_wmm_classify_pkt_cb;
592 		ucfg_dp_softap_register_txrx_ops(vdev, &txrx_ops);
593 	}
594 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
595 
596 	ch_width = ucfg_mlme_get_peer_ch_width(adapter->hdd_ctx->psoc,
597 					       txrx_desc.peer_addr.bytes);
598 	txrx_desc.bw = hdd_convert_ch_width_to_cdp_peer_bw(ch_width);
599 	qdf_status = cdp_peer_register(soc, OL_TXRX_PDEV_ID, &txrx_desc);
600 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
601 		hdd_debug("cdp_peer_register() failed to register.  Status = %d [0x%08X]",
602 			  qdf_status, qdf_status);
603 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
604 				     STA_INFO_SOFTAP_REGISTER_STA);
605 		return qdf_status;
606 	}
607 
608 	/* if ( WPA ), tell TL to go to 'connected' and after keys come to the
609 	 * driver then go to 'authenticated'.  For all other authentication
610 	 * types (those that do not require upper layer authentication) we can
611 	 * put TL directly into 'authenticated' state
612 	 */
613 
614 	sta_info->is_qos_enabled = wmm_enabled;
615 
616 	if (!auth_required) {
617 		hdd_debug("open/shared auth STA MAC= " QDF_MAC_ADDR_FMT
618 			  ".  Changing TL state to AUTHENTICATED at Join time",
619 			 QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
620 
621 		/* Connections that do not need Upper layer auth,
622 		 * transition TL directly to 'Authenticated' state.
623 		 */
624 		qdf_status = hdd_change_peer_state(link_info,
625 						   txrx_desc.peer_addr.bytes,
626 						   OL_TXRX_PEER_STATE_AUTH);
627 
628 		sta_info->peer_state = OL_TXRX_PEER_STATE_AUTH;
629 		if (!qdf_is_macaddr_broadcast(sta_mac))
630 			qdf_status = wlan_hdd_send_sta_authorized_event(
631 							adapter, hdd_ctx,
632 							sta_mac);
633 	} else {
634 
635 		hdd_debug("ULA auth STA MAC = " QDF_MAC_ADDR_FMT
636 			  ".  Changing TL state to CONNECTED at Join time",
637 			 QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
638 
639 		qdf_status = hdd_change_peer_state(link_info,
640 						   txrx_desc.peer_addr.bytes,
641 						   OL_TXRX_PEER_STATE_CONN);
642 
643 		sta_info->peer_state = OL_TXRX_PEER_STATE_CONN;
644 	}
645 
646 	if (!qdf_is_macaddr_broadcast(sta_mac) &&
647 	    dot11mode < QCA_WLAN_802_11_MODE_INVALID)
648 		ap_ctx->client_count[dot11mode]++;
649 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
650 			     STA_INFO_SOFTAP_REGISTER_STA);
651 
652 	if (is_macaddr_broadcast) {
653 		hdd_debug("Enabling queues");
654 		wlan_hdd_netif_queue_control(adapter,
655 					     WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
656 					     WLAN_CONTROL_PATH);
657 	}
658 	ucfg_mlme_update_oce_flags(hdd_ctx->pdev);
659 	ucfg_twt_init_context(hdd_ctx->psoc, sta_mac,
660 			      TWT_ALL_SESSIONS_DIALOG_ID);
661 	return qdf_status;
662 }
663 
664 QDF_STATUS
hdd_softap_register_bc_sta(struct wlan_hdd_link_info * link_info,bool privacy_required)665 hdd_softap_register_bc_sta(struct wlan_hdd_link_info *link_info,
666 			   bool privacy_required)
667 {
668 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
669 	struct qdf_mac_addr broadcast_macaddr = QDF_MAC_ADDR_BCAST_INIT;
670 	struct hdd_ap_ctx *ap_ctx;
671 	uint8_t sta_id;
672 
673 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
674 	sta_id = ap_ctx->broadcast_sta_id;
675 	if (sta_id >= WLAN_MAX_STA_COUNT) {
676 		hdd_err("Error: Invalid sta_id: %u", sta_id);
677 		return qdf_status;
678 	}
679 
680 	qdf_status = hdd_softap_register_sta(link_info, false,
681 					     privacy_required,
682 					     &broadcast_macaddr, NULL);
683 
684 	return qdf_status;
685 }
686 
hdd_softap_stop_bss(struct hdd_adapter * adapter)687 QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter)
688 {
689 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
690 	uint8_t indoor_chnl_marking = 0;
691 	struct hdd_context *hdd_ctx;
692 	struct hdd_station_info *sta_info, *tmp = NULL;
693 
694 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
695 
696 	status = ucfg_policy_mgr_get_indoor_chnl_marking(hdd_ctx->psoc,
697 							 &indoor_chnl_marking);
698 	if (QDF_STATUS_SUCCESS != status)
699 		hdd_err("can't get indoor channel marking, using default");
700 	/* This is stop bss callback running in scheduler thread so do not
701 	 * driver unload in progress check otherwise it can lead to peer
702 	 * object leak
703 	 */
704 
705 	hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
706 				  STA_INFO_SOFTAP_STOP_BSS) {
707 		status = hdd_softap_deregister_sta(adapter, &sta_info);
708 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
709 				     STA_INFO_SOFTAP_STOP_BSS);
710 	}
711 
712 	if (adapter->device_mode == QDF_SAP_MODE &&
713 	    !hdd_ctx->config->disable_channel)
714 		wlan_hdd_restore_channels(hdd_ctx);
715 
716 	/*  Mark the indoor channel (passive) to enable  */
717 	if (indoor_chnl_marking && adapter->device_mode == QDF_SAP_MODE) {
718 		hdd_update_indoor_channel(hdd_ctx, false);
719 		sme_update_channel_list(hdd_ctx->mac_handle);
720 	}
721 
722 	if (ucfg_ipa_is_enabled()) {
723 		if (ucfg_ipa_wlan_evt(hdd_ctx->pdev,
724 				      adapter->dev,
725 				      adapter->device_mode,
726 				      adapter->deflink->vdev_id,
727 				      WLAN_IPA_AP_DISCONNECT,
728 				      adapter->dev->dev_addr,
729 				      false) != QDF_STATUS_SUCCESS)
730 			hdd_err("WLAN_AP_DISCONNECT event failed");
731 	}
732 
733 	/* Setting the RTS profile to original value */
734 	if (sme_cli_set_command(adapter->deflink->vdev_id,
735 				wmi_vdev_param_enable_rtscts,
736 				cfg_get(hdd_ctx->psoc,
737 					CFG_ENABLE_FW_RTS_PROFILE),
738 				VDEV_CMD))
739 		hdd_debug("Failed to set RTS_PROFILE");
740 
741 	return status;
742 }
743 
744 /**
745  * hdd_softap_change_per_sta_state() - Change the state of a SoftAP station
746  * @adapter: pointer to adapter context
747  * @sta_mac: MAC address of the station
748  * @state: new state of the station
749  *
750  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
751  */
hdd_softap_change_per_sta_state(struct hdd_adapter * adapter,struct qdf_mac_addr * sta_mac,enum ol_txrx_peer_state state)752 static QDF_STATUS hdd_softap_change_per_sta_state(struct hdd_adapter *adapter,
753 						  struct qdf_mac_addr *sta_mac,
754 						  enum ol_txrx_peer_state state)
755 {
756 	QDF_STATUS qdf_status;
757 	struct hdd_station_info *sta_info;
758 	struct qdf_mac_addr mac_addr;
759 	struct wlan_objmgr_vdev *vdev;
760 
761 	hdd_enter_dev(adapter->dev);
762 
763 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
764 					   sta_mac->bytes,
765 					   STA_INFO_SOFTAP_CHANGE_STA_STATE);
766 
767 	if (!sta_info) {
768 		hdd_debug("Failed to find right station MAC: " QDF_MAC_ADDR_FMT,
769 			  QDF_MAC_ADDR_REF(sta_mac->bytes));
770 		return QDF_STATUS_E_INVAL;
771 	}
772 
773 	if (qdf_is_macaddr_broadcast(&sta_info->sta_mac))
774 		qdf_mem_copy(&mac_addr, &adapter->mac_addr, QDF_MAC_ADDR_SIZE);
775 	else
776 		qdf_mem_copy(&mac_addr, sta_mac, QDF_MAC_ADDR_SIZE);
777 
778 	qdf_status =
779 		hdd_change_peer_state(adapter->deflink, mac_addr.bytes, state);
780 	hdd_debug("Station " QDF_MAC_ADDR_FMT " changed to state %d",
781 		  QDF_MAC_ADDR_REF(mac_addr.bytes), state);
782 
783 	if (QDF_IS_STATUS_ERROR(qdf_status))
784 		goto put_ref;
785 
786 	sta_info->peer_state = OL_TXRX_PEER_STATE_AUTH;
787 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
788 	if (vdev) {
789 		p2p_peer_authorized(vdev, sta_mac->bytes);
790 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
791 	} else {
792 		hdd_err("vdev is NULL");
793 	}
794 
795 put_ref:
796 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
797 			     STA_INFO_SOFTAP_CHANGE_STA_STATE);
798 	hdd_exit();
799 	return qdf_status;
800 }
801 
hdd_softap_change_sta_state(struct hdd_adapter * adapter,struct qdf_mac_addr * sta_mac,enum ol_txrx_peer_state state)802 QDF_STATUS hdd_softap_change_sta_state(struct hdd_adapter *adapter,
803 				       struct qdf_mac_addr *sta_mac,
804 				       enum ol_txrx_peer_state state)
805 {
806 	struct qdf_mac_addr *mldaddr;
807 	struct wlan_objmgr_peer *peer;
808 	QDF_STATUS status = QDF_STATUS_E_INVAL;
809 	struct hdd_context *hdd_ctx;
810 
811 	status = hdd_softap_change_per_sta_state(adapter, sta_mac, state);
812 
813 	if (QDF_IS_STATUS_ERROR(status))
814 		return status;
815 
816 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
817 
818 	if (!hdd_ctx) {
819 		hdd_err("hdd ctx is null");
820 		return status;
821 	}
822 	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc,
823 					   sta_mac->bytes,
824 					   WLAN_LEGACY_MAC_ID);
825 
826 	if (!peer) {
827 		hdd_debug("peer is null");
828 		return status;
829 	}
830 	mldaddr = (struct qdf_mac_addr *)wlan_peer_mlme_get_mldaddr(peer);
831 	if (mldaddr && !qdf_is_macaddr_zero(mldaddr))
832 		status = hdd_softap_change_per_sta_state(adapter, mldaddr,
833 							 state);
834 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
835 
836 	return status;
837 }
838 
839 #ifdef FEATURE_WDS
hdd_softap_ind_l2_update(struct hdd_adapter * adapter,struct qdf_mac_addr * sta_mac)840 QDF_STATUS hdd_softap_ind_l2_update(struct hdd_adapter *adapter,
841 				    struct qdf_mac_addr *sta_mac)
842 {
843 	qdf_nbuf_t nbuf;
844 	struct l2_update_frame *msg;
845 
846 	nbuf = qdf_nbuf_alloc(NULL, sizeof(*msg), 0, 4, false);
847 	if (!nbuf)
848 		return QDF_STATUS_E_FAILURE;
849 
850 	msg = (struct l2_update_frame *)qdf_nbuf_data(nbuf);
851 
852 	/* 802.2 LLC XID update frame carried over 802.3 */
853 	ether_addr_copy(msg->eh.h_source, sta_mac->bytes);
854 	eth_broadcast_addr(msg->eh.h_dest);
855 	/* packet length - dummy 802.3 packet */
856 	msg->eh.h_proto = htons(sizeof(*msg) - sizeof(struct ethhdr));
857 
858 	/* null DSAP and a null SSAP is a way to solicit a response from any
859 	 * station (i.e., any DA)
860 	 */
861 	msg->l2_update_pdu.dsap = LLC_NULL_SAP;
862 	msg->l2_update_pdu.ssap = LLC_NULL_SAP;
863 
864 	/*
865 	 * unsolicited XID response frame to announce presence.
866 	 * lsb.11110101.
867 	 */
868 	msg->l2_update_pdu.ctrl_1 = LLC_PDU_TYPE_U | LLC_1_PDU_CMD_XID;
869 
870 	/* XID information field 129.1.0 to indicate connectionless service */
871 	msg->l2_update_xid_info.fmt_id = LLC_XID_FMT_ID;
872 	msg->l2_update_xid_info.type = LLC_XID_NULL_CLASS_1;
873 	msg->l2_update_xid_info.rw = 0;
874 
875 	qdf_nbuf_set_pktlen(nbuf, sizeof(*msg));
876 	nbuf->dev = adapter->dev;
877 	nbuf->protocol = eth_type_trans(nbuf, adapter->dev);
878 	qdf_net_buf_debug_release_skb(nbuf);
879 	netif_rx_ni(nbuf);
880 
881 	return QDF_STATUS_SUCCESS;
882 }
883 #endif
884