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