diff --git a/Kbuild b/Kbuild index fe0d494ee7a7..ec47a196d239 100644 --- a/Kbuild +++ b/Kbuild @@ -2620,6 +2620,7 @@ cppflags-$(CONFIG_FEATURE_WLAN_SCAN_PNO) += -DFEATURE_WLAN_SCAN_PNO cppflags-$(CONFIG_WLAN_FEATURE_PACKET_FILTERING) += -DWLAN_FEATURE_PACKET_FILTERING cppflags-$(CONFIG_DHCP_SERVER_OFFLOAD) += -DDHCP_SERVER_OFFLOAD cppflags-$(CONFIG_WLAN_NS_OFFLOAD) += -DWLAN_NS_OFFLOAD +cppflags-$(CONFIG_WLAN_DYNAMIC_ARP_NS_OFFLOAD) += -DFEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD cppflags-$(CONFIG_FEATURE_WLAN_RA_FILTERING) += -DFEATURE_WLAN_RA_FILTERING cppflags-$(CONFIG_FEATURE_WLAN_LPHB) += -DFEATURE_WLAN_LPHB cppflags-$(CONFIG_QCA_SUPPORT_TX_THROTTLE) += -DQCA_SUPPORT_TX_THROTTLE diff --git a/components/pkt_capture/core/inc/wlan_pkt_capture_main.h b/components/pkt_capture/core/inc/wlan_pkt_capture_main.h index cb48a75b7b8d..312c0d4f2638 100644 --- a/components/pkt_capture/core/inc/wlan_pkt_capture_main.h +++ b/components/pkt_capture/core/inc/wlan_pkt_capture_main.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -238,6 +239,20 @@ QDF_STATUS pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, */ bool pkt_capture_is_tx_mgmt_enable(struct wlan_objmgr_pdev *pdev); +/** + * pkt_capture_is_frame_filter_set - Check if filter type set by user and packet + * type matches + * @buf: netbuf + * @frame_filter: filter set by user via vendor command + * @direction: Tx or Rx + * + * Return: bool + */ +bool +pkt_capture_is_frame_filter_set(qdf_nbuf_t buf, + struct pkt_capture_frame_filter *frame_filter, + bool direction); + #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 /** * pkt_capture_get_pktcap_mode_v2 - Get packet capture mode diff --git a/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h b/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h index 820de82a18bd..50279fe8b3bb 100644 --- a/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h +++ b/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h @@ -65,6 +65,8 @@ struct pkt_capture_cb_context { * @last_freq: Last connected freq * @curr_freq: current connected freq * @rx_vht_sgi: guard interval of vht rx packet + * @wake_lock: wake lock for packet capture + * @runtime_lock: runtime lock for packet capture */ struct pkt_capture_vdev_priv { struct wlan_objmgr_vdev *vdev; @@ -78,6 +80,8 @@ struct pkt_capture_vdev_priv { qdf_freq_t last_freq; qdf_freq_t curr_freq; uint8_t rx_vht_sgi; + qdf_wake_lock_t wake_lock; + qdf_runtime_lock_t runtime_lock; }; /** diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c b/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c index 7170c423a6fc..b4dbc0a375cc 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c @@ -1634,9 +1634,51 @@ void pkt_capture_offload_deliver_indication_handler( struct pkt_capture_tx_hdr_elem_t *ptr_pktcapture_hdr; struct pkt_capture_tx_hdr_elem_t pktcapture_hdr = {0}; uint32_t txcap_hdr_size = sizeof(struct pkt_capture_tx_hdr_elem_t); + struct wlan_objmgr_vdev *vdev; + struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_capture_frame_filter *frame_filter; + QDF_STATUS ret = QDF_STATUS_SUCCESS; offload_deliver_msg = (struct htt_tx_offload_deliver_ind_hdr_t *)msg; + vdev = pkt_capture_get_vdev(); + ret = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(ret)) + return; + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("vdev priv is NULL"); + pkt_capture_vdev_put_ref(vdev); + return; + } + + frame_filter = &vdev_priv->frame_filter; + + nbuf_len = offload_deliver_msg->tx_mpdu_bytes; + netbuf = qdf_nbuf_alloc(NULL, + roundup(nbuf_len + RESERVE_BYTES, 4), + RESERVE_BYTES, 4, false); + if (!netbuf) { + pkt_capture_vdev_put_ref(vdev); + return; + } + + qdf_nbuf_put_tail(netbuf, nbuf_len); + + qdf_mem_copy(qdf_nbuf_data(netbuf), + buf + sizeof(struct htt_tx_offload_deliver_ind_hdr_t), + nbuf_len); + + if (!(frame_filter->data_tx_frame_filter & + PKT_CAPTURE_DATA_FRAME_TYPE_ALL) && + !pkt_capture_is_frame_filter_set( + netbuf, frame_filter, IEEE80211_FC1_DIR_TODS)) { + qdf_nbuf_free(netbuf); + pkt_capture_vdev_put_ref(vdev); + return; + } + pktcapture_hdr.timestamp = offload_deliver_msg->phy_timestamp_l32; pktcapture_hdr.preamble = offload_deliver_msg->preamble; pktcapture_hdr.mcs = offload_deliver_msg->mcs; @@ -1656,25 +1698,11 @@ void pkt_capture_offload_deliver_indication_handler( status = offload_deliver_msg->status; pkt_format = offload_deliver_msg->format; - nbuf_len = offload_deliver_msg->tx_mpdu_bytes; - - netbuf = qdf_nbuf_alloc(NULL, - roundup(nbuf_len + RESERVE_BYTES, 4), - RESERVE_BYTES, 4, false); - - if (!netbuf) - return; - - qdf_nbuf_put_tail(netbuf, nbuf_len); - - qdf_mem_copy(qdf_nbuf_data(netbuf), - buf + sizeof(struct htt_tx_offload_deliver_ind_hdr_t), - nbuf_len); - qdf_nbuf_push_head(netbuf, txcap_hdr_size); ptr_pktcapture_hdr = (struct pkt_capture_tx_hdr_elem_t *)qdf_nbuf_data(netbuf); + qdf_mem_copy(ptr_pktcapture_hdr, &pktcapture_hdr, txcap_hdr_size); pkt_capture_datapkt_process( @@ -1682,5 +1710,7 @@ void pkt_capture_offload_deliver_indication_handler( netbuf, TXRX_PROCESS_TYPE_DATA_TX, tid, status, pkt_format, bssid, soc, offload_deliver_msg->tx_retry_cnt); + + pkt_capture_vdev_put_ref(vdev); } #endif diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_main.c b/components/pkt_capture/core/src/wlan_pkt_capture_main.c index d4009775dd07..6c29e65cfda7 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_main.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_main.c @@ -35,6 +35,7 @@ #include "wlan_pkt_capture_tgt_api.h" #include #include "wlan_vdev_mgr_utils_api.h" +#include "host_diag_core_event.h" static struct wlan_objmgr_vdev *gp_pkt_capture_vdev; @@ -406,7 +407,7 @@ pkt_capture_process_tx_data(void *soc, void *log_data, u_int16_t vdev_id, * Return: true, if filter bit is set * false, if filter bit is not set */ -static bool +bool pkt_capture_is_frame_filter_set(qdf_nbuf_t buf, struct pkt_capture_frame_filter *frame_filter, bool direction) @@ -594,8 +595,6 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, struct htt_tx_offload_deliver_ind_hdr_t *offload_deliver_msg; bool is_pkt_during_roam = false; uint32_t freq = 0; - qdf_nbuf_t buf = log_data + - sizeof(struct htt_tx_offload_deliver_ind_hdr_t); if (!frame_filter->data_tx_frame_filter) { pkt_capture_vdev_put_ref(vdev); @@ -615,17 +614,9 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, vdev_id = offload_deliver_msg->vdev_id; } - if (frame_filter->data_tx_frame_filter & - PKT_CAPTURE_DATA_FRAME_TYPE_ALL) { - pkt_capture_offload_deliver_indication_handler( + pkt_capture_offload_deliver_indication_handler( log_data, vdev_id, bssid, soc); - } else if (pkt_capture_is_frame_filter_set( - buf, frame_filter, IEEE80211_FC1_DIR_TODS)) { - pkt_capture_offload_deliver_indication_handler( - log_data, - vdev_id, bssid, soc); - } break; } @@ -775,6 +766,10 @@ pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev, goto send_mode_fail; } + qdf_wake_lock_acquire(&vdev_priv->wake_lock, + WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE); + qdf_runtime_pm_prevent_suspend(&vdev_priv->runtime_lock); + return QDF_STATUS_SUCCESS; send_mode_fail: @@ -845,6 +840,10 @@ QDF_STATUS pkt_capture_deregister_callbacks(struct wlan_objmgr_vdev *vdev) vdev_priv->cb_ctx->mon_cb = NULL; vdev_priv->cb_ctx->mon_ctx = NULL; + qdf_wake_lock_release(&vdev_priv->wake_lock, + WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE); + qdf_runtime_pm_allow_suspend(&vdev_priv->runtime_lock); + return QDF_STATUS_SUCCESS; } @@ -1097,6 +1096,8 @@ pkt_capture_vdev_create_notification(struct wlan_objmgr_vdev *vdev, void *arg) } qdf_spinlock_create(&vdev_priv->lock_q); qdf_list_create(&vdev_priv->ppdu_stats_q, PPDU_STATS_Q_MAX_SIZE); + qdf_wake_lock_create(&vdev_priv->wake_lock, "pkt_capture_mode"); + qdf_runtime_lock_init(&vdev_priv->runtime_lock); return status; @@ -1133,6 +1134,9 @@ pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) return QDF_STATUS_E_FAILURE; } + qdf_runtime_lock_deinit(&vdev_priv->runtime_lock); + qdf_wake_lock_destroy(&vdev_priv->wake_lock); + while (qdf_list_remove_front(&vdev_priv->ppdu_stats_q, &node) == QDF_STATUS_SUCCESS) { stats_node = qdf_container_of( @@ -1243,7 +1247,7 @@ QDF_STATUS pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, ol_txrx_soc_handle soc; QDF_STATUS status; enum pkt_capture_config config = 0; - bool check_enable_beacon = 0, send_bcn = 0; + bool send_bcn = 0; struct vdev_mlme_obj *vdev_mlme; uint32_t bcn_interval, nth_beacon_value; @@ -1328,16 +1332,13 @@ QDF_STATUS pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, PKT_CAPTURE_MGMT_CONNECT_NO_BEACON) { mode |= PACKET_CAPTURE_MODE_MGMT_ONLY; config |= PACKET_CAPTURE_CONFIG_NO_BEACON_ENABLE; - } else { - check_enable_beacon = 1; } - } - if (check_enable_beacon) { if (vdev_priv->frame_filter.mgmt_rx_frame_filter & - PKT_CAPTURE_MGMT_CONNECT_BEACON) + PKT_CAPTURE_MGMT_CONNECT_BEACON) { if (!send_bcn) config |= PACKET_CAPTURE_CONFIG_BEACON_ENABLE; + } if (vdev_priv->frame_filter.mgmt_rx_frame_filter & PKT_CAPTURE_MGMT_CONNECT_SCAN_BEACON) diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c b/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c index b2cfe1332536..a3628e34c843 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c @@ -592,10 +592,6 @@ pkt_capture_is_beacon_forward_enable(struct wlan_objmgr_vdev *vdev, return false; } - if (vdev_priv->frame_filter.mgmt_rx_frame_filter & - PKT_CAPTURE_MGMT_CONNECT_NO_BEACON) - return false; - mac_hdr = (tpSirMacMgmtHdr)(qdf_nbuf_data(wbuf)); wlan_vdev_get_bss_peer_mac(vdev, &connected_bssid); diff --git a/components/pmo/core/inc/wlan_pmo_priv.h b/components/pmo/core/inc/wlan_pmo_priv.h index 1bbf04d24c1f..495cd52e31cd 100644 --- a/components/pmo/core/inc/wlan_pmo_priv.h +++ b/components/pmo/core/inc/wlan_pmo_priv.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -110,6 +111,9 @@ struct wlan_pmo_ctx { * @dyn_listen_interval: dynamically user configured listen interval * @restore_dtim_setting: DTIM settings restore flag * @pmo_vdev_lock: spin lock for pmo vdev priv ctx + * @dyn_arp_ns_offload_disable: true when arp/ns offload is disable + * @dyn_arp_ns_offload_rt_lock: wake lock which prevent runtime pm happen if + * arp/ns offload is disable */ struct pmo_vdev_priv_obj { struct pmo_psoc_priv_obj *pmo_psoc_ctx; @@ -132,6 +136,10 @@ struct pmo_vdev_priv_obj { uint32_t dyn_listen_interval; bool restore_dtim_setting; qdf_spinlock_t pmo_vdev_lock; +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD + bool dyn_arp_ns_offload_disable; + qdf_runtime_lock_t dyn_arp_ns_offload_rt_lock; +#endif }; #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */ diff --git a/components/pmo/core/inc/wlan_pmo_suspend_resume.h b/components/pmo/core/inc/wlan_pmo_suspend_resume.h index 0cc7a6b72b6d..dd4297ef8077 100644 --- a/components/pmo/core/inc/wlan_pmo_suspend_resume.h +++ b/components/pmo/core/inc/wlan_pmo_suspend_resume.h @@ -180,6 +180,112 @@ bool pmo_core_vdev_get_restore_dtim(struct wlan_objmgr_vdev *vdev) return value; } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +/** + * pmo_core_dynamic_arp_ns_offload_enable() - Enable vdev arp/ns offload + * @vdev: objmgr vdev handle + * + * Return: QDF_STATUS_E_ALREADY if arp/ns offload already enable + */ +static inline QDF_STATUS +pmo_core_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev) +{ + bool value; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + value = vdev_ctx->dyn_arp_ns_offload_disable; + if (!value) + status = QDF_STATUS_E_ALREADY; + else + vdev_ctx->dyn_arp_ns_offload_disable = false; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return status; +} + +/** + * pmo_core_dynamic_arp_ns_offload_disable() - Disable vdev arp/ns offload + * @vdev: objmgr vdev handle + * + * Return: QDF_STATUS_E_ALREADY if arp/ns offload already disable + */ +static inline QDF_STATUS +pmo_core_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev) +{ + bool value; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + value = vdev_ctx->dyn_arp_ns_offload_disable; + if (value) + status = QDF_STATUS_E_ALREADY; + else + vdev_ctx->dyn_arp_ns_offload_disable = true; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return status; +} + +/** + * pmo_core_get_dynamic_arp_ns_offload_disable() - Get arp/ns offload state + * @vdev: objmgr vdev handle + * + * Return: true if vdev arp/ns offload is disable + */ +static inline bool +pmo_core_get_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev) +{ + bool value; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + value = vdev_ctx->dyn_arp_ns_offload_disable; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return value; +} + +/** + * pmo_core_dynamic_arp_ns_offload_runtime_prevent() - Prevent runtime suspend + * @vdev: objmgr vdev handle + * + * API to prevent runtime suspend happen when arp/ns offload is disable + * + * Return: None + */ +static inline void +pmo_core_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_runtime_pm_prevent_suspend(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} + +/** + * pmo_core_dynamic_arp_ns_offload_runtime_allow() - Allow runtime suspend + * @vdev: objmgr vdev handle + * + * API to allow runtime suspend happen when arp/ns offload is enable + * + * Return: None + */ +static inline void +pmo_core_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_runtime_pm_allow_suspend(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} +#endif + /** * pmo_core_update_power_save_mode() - update power save mode * @vdev: objmgr vdev handle diff --git a/components/pmo/core/src/wlan_pmo_arp.c b/components/pmo/core/src/wlan_pmo_arp.c index d997c8ecdea3..9be6314dd978 100644 --- a/components/pmo/core/src/wlan_pmo_arp.c +++ b/components/pmo/core/src/wlan_pmo_arp.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -129,6 +129,7 @@ pmo_core_do_enable_arp_offload(struct wlan_objmgr_vdev *vdev, status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id); break; case pmo_apps_suspend: + case pmo_arp_ns_offload_dynamic_update: /* enable arp when active offload is false (apps suspend) */ status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id); break; @@ -162,6 +163,7 @@ static QDF_STATUS pmo_core_do_disable_arp_offload(struct wlan_objmgr_vdev *vdev, switch (trigger) { case pmo_apps_resume: + case pmo_arp_ns_offload_dynamic_update: /* disable arp on apps resume when active offload is disable */ status = pmo_tgt_disable_arp_offload_req(vdev, vdev_id); break; diff --git a/components/pmo/core/src/wlan_pmo_ns.c b/components/pmo/core/src/wlan_pmo_ns.c index f41d212f0549..3e8ac4e6fa0b 100644 --- a/components/pmo/core/src/wlan_pmo_ns.c +++ b/components/pmo/core/src/wlan_pmo_ns.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -166,6 +166,7 @@ static QDF_STATUS pmo_core_do_enable_ns_offload(struct wlan_objmgr_vdev *vdev, status = pmo_tgt_enable_ns_offload_req(vdev, vdev_id); break; case pmo_apps_suspend: + case pmo_arp_ns_offload_dynamic_update: /* enable arp when active offload is false (apps suspend) */ status = pmo_tgt_enable_ns_offload_req(vdev, vdev_id); break; @@ -201,6 +202,7 @@ static QDF_STATUS pmo_core_do_disable_ns_offload(struct wlan_objmgr_vdev *vdev, status = pmo_tgt_disable_ns_offload_req(vdev, vdev_id); break; case pmo_apps_resume: + case pmo_arp_ns_offload_dynamic_update: status = pmo_tgt_disable_ns_offload_req(vdev, vdev_id); break; default: diff --git a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h index 56a4f7ed2d32..98d452662c0c 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -205,6 +206,7 @@ typedef QDF_STATUS(*pmo_psoc_resume_handler) * @pmo_ns_offload_dynamic_update: enable/disable ns offload on the fly * @pmo_peer_disconnect: trigger is peer disconnect * @pmo_mcbc_setting_dynamic_update: mcbc value update on the fly + * @pmo_arp_ns_offload_dynamic_update: enable/disable arp/ns offload on the fly * * @pmo_offload_trigger_max: Max trigger value */ @@ -219,6 +221,7 @@ enum pmo_offload_trigger { pmo_ns_offload_dynamic_update, pmo_peer_disconnect, pmo_mcbc_setting_dynamic_update, + pmo_arp_ns_offload_dynamic_update, pmo_offload_trigger_max, }; diff --git a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h index 96a4bc13b4a3..b14b879e04ec 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h @@ -545,6 +545,79 @@ ucfg_pmo_enhanced_mc_filter_disable(struct wlan_objmgr_vdev *vdev) return pmo_core_enhanced_mc_filter_disable(vdev); } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +/** + * ucfg_pmo_dynamic_arp_ns_offload_enable() - enable arp/ns offload + * @vdev: vdev objmgr handle + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_dynamic_arp_ns_offload_disable() - disable arp/ns offload + * @vdev: vdev objmgr handle + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_get_arp_ns_offload_dynamic_disable() - get arp/ns offload state + * @vdev: vdev objmgr handle + * + * Return: QDF_STATUS + */ +bool +ucfg_pmo_get_arp_ns_offload_dynamic_disable(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent() - prevent runtime suspend + * @vdev: vdev objmgr handle + * + * Return: none + */ +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_dynamic_arp_ns_offload_runtime_allow() - allow runtime suspend + * @vdev: vdev objmgr handle + * + * Return: none + */ +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev); +#else +static inline QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev) +{ + return QDF_STATUS_SUCCESS; +} + +static inline bool +ucfg_pmo_get_arp_ns_offload_dynamic_disable(struct wlan_objmgr_vdev *vdev) +{ + return false; +} + +static inline void +ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev) +{ +} + +static inline void +ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev) {} +#endif + /** * ucfg_pmo_enable_mc_addr_filtering_in_fwr(): Enable cached mc add list in fwr * @psoc: objmgr psoc handle diff --git a/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c b/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c index d0efc3070080..920a6718d421 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -227,6 +228,26 @@ out: return status; } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +static inline void +pmo_vdev_dynamic_arp_ns_offload_init(struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_runtime_lock_init(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} + +static inline void +pmo_vdev_dynamic_arp_ns_offload_deinit(struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_runtime_lock_deinit(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} +#else +static inline void +pmo_vdev_dynamic_arp_ns_offload_init(struct pmo_vdev_priv_obj *vdev_ctx) {} + +static inline void +pmo_vdev_dynamic_arp_ns_offload_deinit(struct pmo_vdev_priv_obj *vdev_ctx) {} +#endif + QDF_STATUS pmo_vdev_object_created_notification( struct wlan_objmgr_vdev *vdev, void *arg) { @@ -261,6 +282,7 @@ QDF_STATUS pmo_vdev_object_created_notification( psoc_ctx->psoc_cfg.ptrn_match_enable_all_vdev; vdev_ctx->pmo_psoc_ctx = psoc_ctx; qdf_atomic_init(&vdev_ctx->gtk_err_enable); + pmo_vdev_dynamic_arp_ns_offload_init(vdev_ctx); out: pmo_exit(); @@ -306,6 +328,7 @@ QDF_STATUS pmo_vdev_object_destroyed_notification( pmo_err("Failed to detach vdev_ctx with vdev"); qdf_spinlock_destroy(&vdev_ctx->pmo_vdev_lock); + pmo_vdev_dynamic_arp_ns_offload_deinit(vdev_ctx); qdf_mem_free(vdev_ctx); return status; diff --git a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c index 5663480501c8..8bd050c32bbb 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c @@ -195,6 +195,38 @@ ucfg_pmo_disable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, } #endif /* WLAN_NS_OFFLOAD */ +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_enable(vdev); +} + +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_disable(vdev); +} + +bool +ucfg_pmo_get_arp_ns_offload_dynamic_disable(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_get_dynamic_arp_ns_offload_disable(vdev); +} + +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_runtime_prevent(vdev); +} + +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_runtime_allow(vdev); +} +#endif + QDF_STATUS ucfg_pmo_get_ns_offload_params(struct wlan_objmgr_vdev *vdev, struct pmo_ns_offload_params *params) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 9934f6c2fb0d..25467bbcdd2b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1766,7 +1766,7 @@ enum RX_OFFLOAD { /** * struct hdd_cache_channel_info - Structure of the channel info * which needs to be cached - * @channel_num: channel number + * @freq: frequency * @reg_status: Current regulatory status of the channel * Enable * Disable @@ -1775,7 +1775,7 @@ enum RX_OFFLOAD { * @wiphy_status: Current wiphy status */ struct hdd_cache_channel_info { - uint32_t channel_num; + qdf_freq_t freq; enum channel_state reg_status; uint32_t wiphy_status; }; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 3c5cd5e6ad03..297ea8fd24d6 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -7242,6 +7242,7 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE] = { .type = NLA_U8 }, }; @@ -9024,6 +9025,103 @@ static int hdd_set_nss(struct hdd_adapter *adapter, return ret; } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +#define DYNAMIC_ARP_NS_ENABLE 1 +#define DYNAMIC_ARP_NS_DISABLE 0 + +/** + * hdd_set_arp_ns_offload() - enable/disable arp/ns offload feature + * @adapter: hdd adapter + * @attr: pointer to nla attr + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_set_arp_ns_offload(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + uint8_t offload_state; + int errno; + QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct wlan_objmgr_vdev *vdev; + + errno = wlan_hdd_validate_context(hdd_ctx); + if (errno) + return errno; + + if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc) || + !ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) { + hdd_err_rl("ARP/NS Offload is disabled by ini"); + return -EINVAL; + } + + if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) { + hdd_err_rl("active mode offload is disabled by ini"); + return -EINVAL; + } + + if (adapter->device_mode != QDF_STA_MODE && + adapter->device_mode != QDF_P2P_CLIENT_MODE) { + hdd_err_rl("only support on sta/p2p-cli mode"); + return -EINVAL; + } + + vdev = hdd_objmgr_get_vdev(adapter); + if (!vdev) { + hdd_err("vdev is NULL"); + return -EINVAL; + } + + offload_state = nla_get_u8(attr); + + if (offload_state == DYNAMIC_ARP_NS_ENABLE) + qdf_status = ucfg_pmo_dynamic_arp_ns_offload_enable(vdev); + else if (offload_state == DYNAMIC_ARP_NS_DISABLE) + qdf_status = ucfg_pmo_dynamic_arp_ns_offload_disable(vdev); + + if (QDF_IS_STATUS_SUCCESS(qdf_status)) { + if (offload_state == DYNAMIC_ARP_NS_ENABLE) + ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(vdev); + else + ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(vdev); + } + + hdd_objmgr_put_vdev(vdev); + + if (QDF_IS_STATUS_ERROR(qdf_status)) { + if (qdf_status == QDF_STATUS_E_ALREADY) { + hdd_info_rl("already set arp/ns offload %d", + offload_state); + return 0; + } + return qdf_status_to_os_return(qdf_status); + } + + if (!hdd_is_vdev_in_conn_state(adapter)) { + hdd_info("set not in connect state, updated state %d", + offload_state); + return 0; + } + + if (offload_state == DYNAMIC_ARP_NS_ENABLE) { + hdd_enable_arp_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + hdd_enable_ns_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + } else if (offload_state == DYNAMIC_ARP_NS_DISABLE) { + hdd_disable_arp_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + hdd_disable_ns_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + } + + return 0; +} + +#undef DYNAMIC_ARP_NS_ENABLE +#undef DYNAMIC_ARP_NS_DISABLE +#endif + /** * hdd_set_wfc_state() - Set wfc state * @adapter: hdd adapter @@ -9168,6 +9266,10 @@ static const struct independent_setters independent_setters[] = { hdd_config_udp_qos_upgrade_threshold}, {QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS, hdd_set_ft_over_ds}, +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD + {QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD, + hdd_set_arp_ns_offload}, +#endif {QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE, hdd_set_wfc_state}, }; @@ -18237,6 +18339,9 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode); if (hdd_is_client_mode(adapter->device_mode)) { + if (adapter->device_mode == QDF_STA_MODE) + hdd_cleanup_conn_info(adapter); + if (hdd_is_client_mode(new_mode)) { errno = hdd_change_adapter_mode(adapter, new_mode); if (errno) { diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 075de779d2d5..80659541d94a 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -4980,9 +4980,8 @@ int wlan_hdd_restore_channels(struct hdd_context *hdd_ctx) } for (i = 0; i < cache_chann->num_channels; i++) { - freq = wlan_reg_chan_to_freq( - hdd_ctx->pdev, - cache_chann->channel_info[i].channel_num); + freq = cache_chann->channel_info[i].freq; + if (!freq) continue; @@ -4997,8 +4996,8 @@ int wlan_hdd_restore_channels(struct hdd_context *hdd_ctx) wiphy_channel->flags = cache_chann->channel_info[i].wiphy_status; - hdd_debug("Restore channel %d reg_stat %d wiphy_stat 0x%x", - cache_chann->channel_info[i].channel_num, + hdd_debug("Restore channel_freq %d reg_stat %d wiphy_stat 0x%x", + cache_chann->channel_info[i].freq, cache_chann->channel_info[i].reg_status, wiphy_channel->flags); } @@ -5050,8 +5049,8 @@ int wlan_hdd_disable_channels(struct hdd_context *hdd_ctx) } for (i = 0; i < cache_chann->num_channels; i++) { - freq = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, - cache_chann->channel_info[i].channel_num); + freq = cache_chann->channel_info[i].freq; + if (!freq) continue; wiphy_channel = wlan_hdd_get_wiphy_channel(wiphy, freq); @@ -5068,8 +5067,8 @@ int wlan_hdd_disable_channels(struct hdd_context *hdd_ctx) freq); cache_chann->channel_info[i].wiphy_status = wiphy_channel->flags; - hdd_debug("Disable channel %d reg_stat %d wiphy_stat 0x%x", - cache_chann->channel_info[i].channel_num, + hdd_debug("Disable channel_freq %d reg_stat %d wiphy_stat 0x%x", + cache_chann->channel_info[i].freq, cache_chann->channel_info[i].reg_status, wiphy_channel->flags); diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 6bfdee44a536..c5bcd6328c9e 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -6593,63 +6593,73 @@ static int hdd_alloc_chan_cache(struct hdd_context *hdd_ctx, int num_chan) /** * check_disable_channels() - Check for disable channel * @hdd_ctx: Pointer to hdd context - * @operating_channel: Current operating channel of adapter + * @operating_freq: Current operating frequency of adapter * * This function checks original_channels array for a specific channel * * Return: 0 if channel not found, 1 if channel found */ static bool check_disable_channels(struct hdd_context *hdd_ctx, - uint8_t operating_channel) + qdf_freq_t operating_freq) { uint32_t num_channels; uint8_t i; - if (!hdd_ctx || !hdd_ctx->original_channels || !hdd_ctx->original_channels->channel_info) return false; num_channels = hdd_ctx->original_channels->num_channels; - for (i = 0; i < num_channels; i++) - if (hdd_ctx->original_channels->channel_info[i].channel_num == - operating_channel) + for (i = 0; i < num_channels; i++) { + if (operating_freq == + hdd_ctx->original_channels->channel_info[i].freq) return true; + } + return false; } /** - * disconnect_sta_and_stop_sap() - Disconnect STA and stop SAP + * disconnect_sta_and_restart_sap() - Disconnect STA and restart SAP * * @hdd_ctx: Pointer to hdd context * @reason: Disconnect reason code as per @enum wlan_reason_code * * Disable channels provided by user and disconnect STA if it is - * connected to any AP, stop SAP and send deauthentication request - * to STAs connected to SAP. + * connected to any AP, restart SAP. * * Return: None */ -static void disconnect_sta_and_stop_sap(struct hdd_context *hdd_ctx, - enum wlan_reason_code reason) +static void disconnect_sta_and_restart_sap(struct hdd_context *hdd_ctx, + enum wlan_reason_code reason) { struct hdd_adapter *adapter, *next = NULL; QDF_STATUS status; - uint8_t ap_ch; + uint32_t ch_list[NUM_CHANNELS]; + uint32_t ch_count = 0; + bool is_valid_chan_present = true; if (!hdd_ctx) return; hdd_check_and_disconnect_sta_on_invalid_channel(hdd_ctx, reason); + status = policy_mgr_get_valid_chans(hdd_ctx->psoc, ch_list, &ch_count); + if (QDF_IS_STATUS_ERROR(status) || !ch_count) { + hdd_debug("No valid channels present, stop the SAPs"); + is_valid_chan_present = false; + } + status = hdd_get_front_adapter(hdd_ctx, &adapter); while (adapter && (status == QDF_STATUS_SUCCESS)) { if (!hdd_validate_adapter(adapter) && adapter->device_mode == QDF_SAP_MODE) { - ap_ch = wlan_reg_freq_to_chan( - hdd_ctx->pdev, - adapter->session.ap.operating_chan_freq); - if (check_disable_channels(hdd_ctx, ap_ch)) + if (!is_valid_chan_present) wlan_hdd_stop_sap(adapter); + else if (check_disable_channels( + hdd_ctx, + adapter->session.ap.operating_chan_freq)) + policy_mgr_check_sap_restart(hdd_ctx->psoc, + adapter->vdev_id); } status = hdd_get_next_adapter(hdd_ctx, adapter, &next); @@ -6657,6 +6667,36 @@ static void disconnect_sta_and_stop_sap(struct hdd_context *hdd_ctx, } } +/** + * hdd_check_chan_and_fill_freq() - to validate chan and convert into freq + * @pdev: The physical dev to cache the channels for + * @in_chan: input as channel number or freq + * @freq: frequency for input in_chan (output parameter) + * + * This function checks input "in_chan" is channel number, if yes then fills + * appropriate frequency into "freq" out param. If the "in_param" is greater + * than MAX_5GHZ_CHANNEL then gets the valid frequencies for legacy channels + * else get the valid channel for 6Ghz frequency. + * + * Return: true if "in_chan" is valid channel/frequency; false otherwise + */ +static bool hdd_check_chan_and_fill_freq(struct wlan_objmgr_pdev *pdev, + uint32_t *in_chan, qdf_freq_t *freq) +{ + if (IS_CHANNEL_VALID(*in_chan)) { + *freq = wlan_reg_legacy_chan_to_freq(pdev, *in_chan); + } else if (WLAN_REG_IS_24GHZ_CH_FREQ(*in_chan) || + WLAN_REG_IS_5GHZ_CH_FREQ(*in_chan) || + WLAN_REG_IS_6GHZ_CHAN_FREQ(*in_chan)) { + *freq = *in_chan; + *in_chan = wlan_reg_freq_to_chan(pdev, *in_chan); + } else { + return false; + } + + return true; +} + /** * hdd_parse_disable_chan_cmd() - Parse the channel list received * in command. @@ -6666,11 +6706,13 @@ static void disconnect_sta_and_stop_sap(struct hdd_context *hdd_ctx, * This function parses the channel list received in the command. * command should be a string having format * SET_DISABLE_CHANNEL_LIST - * . - * If the command comes multiple times than this function will compare - * the channels received in the command with the channles cached in the - * first command, if the channel list matches with the cached channles, - * it returns success otherwise returns failure. + * /. + * If this command has frequency as input, this function first converts into + * equivalent channel. + * If the command comes multiple times then the channels received in the + * command or channels converted from frequency will be compared with the + * channels cached in the first command, if the channel list matches with + * the cached channels, it returns success otherwise returns failure. * * Return: 0 on success, Error code on failure */ @@ -6680,8 +6722,9 @@ static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr) struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); uint8_t *param; int j, i, temp_int, ret = 0, num_channels; - uint32_t parsed_channels[NUM_CHANNELS]; + qdf_freq_t *chan_freq_list = NULL; bool is_command_repeated = false; + qdf_freq_t freq = 0; if (!hdd_ctx) { hdd_err("HDD Context is NULL"); @@ -6745,6 +6788,11 @@ static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr) is_command_repeated = true; } num_channels = temp_int; + + chan_freq_list = qdf_mem_malloc(num_channels * sizeof(qdf_freq_t)); + if (!chan_freq_list) + return -ENOMEM; + for (j = 0; j < num_channels; j++) { /* * param pointing to the beginning of first space @@ -6776,14 +6824,16 @@ static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr) goto parse_failed; } - if (!IS_CHANNEL_VALID(temp_int)) { + if (!hdd_check_chan_and_fill_freq(hdd_ctx->pdev, &temp_int, + &freq)) { hdd_err("Invalid channel number received"); ret = -EINVAL; goto parse_failed; } - hdd_debug("channel[%d] = %d", j, temp_int); - parsed_channels[j] = temp_int; + hdd_debug("channel[%d] = %d Frequency[%d] = %d", j, temp_int, + j, freq); + chan_freq_list[j] = freq; } /*extra arguments check*/ @@ -6807,19 +6857,19 @@ static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr) */ if (!is_command_repeated) { for (j = 0; j < num_channels; j++) - hdd_ctx->original_channels-> - channel_info[j].channel_num = - parsed_channels[j]; + hdd_ctx->original_channels->channel_info[j].freq = + chan_freq_list[j]; /* Cache the channel list in regulatory also */ - ucfg_reg_cache_channel_state(hdd_ctx->pdev, parsed_channels, - num_channels); + ucfg_reg_cache_channel_freq_state(hdd_ctx->pdev, + chan_freq_list, + num_channels); } else { for (i = 0; i < num_channels; i++) { for (j = 0; j < num_channels; j++) if (hdd_ctx->original_channels-> - channel_info[i].channel_num == - parsed_channels[j]) + channel_info[i].freq == + chan_freq_list[j]) break; if (j == num_channels) { ret = -EINVAL; @@ -6829,6 +6879,8 @@ static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr) ret = 0; } mem_alloc_failed: + if (chan_freq_list) + qdf_mem_free(chan_freq_list); qdf_mutex_release(&hdd_ctx->cache_channel_lock); /* Disable the channels received in command SET_DISABLE_CHANNEL_LIST */ @@ -6836,8 +6888,9 @@ mem_alloc_failed: ret = wlan_hdd_disable_channels(hdd_ctx); if (ret) return ret; - disconnect_sta_and_stop_sap(hdd_ctx, - REASON_OPER_CHANNEL_BAND_CHANGE); + disconnect_sta_and_restart_sap( + hdd_ctx, + REASON_OPER_CHANNEL_BAND_CHANGE); } hdd_exit(); @@ -6847,7 +6900,8 @@ mem_alloc_failed: parse_failed: if (!is_command_repeated) wlan_hdd_free_cache_channels(hdd_ctx); - + if (chan_freq_list) + qdf_mem_free(chan_freq_list); qdf_mutex_release(&hdd_ctx->cache_channel_lock); hdd_exit(); @@ -6889,7 +6943,10 @@ static int hdd_get_disable_ch_list(struct hdd_context *hdd_ctx, uint8_t *buf, ch_list = hdd_ctx->original_channels->channel_info; for (i = 0; (i < num_ch) && (len < buf_len - 1); i++) { len += scnprintf(buf + len, buf_len - len, - " %d", ch_list[i].channel_num); + " %d", + wlan_reg_freq_to_chan( + hdd_ctx->pdev, + ch_list[i].freq)); } } qdf_mutex_release(&hdd_ctx->cache_channel_lock); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6ff051ffb47d..c907192bed3b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -12527,6 +12527,7 @@ void hdd_psoc_idle_timer_start(struct hdd_context *hdd_ctx) void hdd_psoc_idle_timer_stop(struct hdd_context *hdd_ctx) { qdf_delayed_work_stop_sync(&hdd_ctx->psoc_idle_timeout_work); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER); hdd_debug("Stopped psoc idle timer"); } diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c index 4dde13d19221..4f4a35de848d 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/core/hdd/src/wlan_hdd_nan_datapath.c @@ -564,7 +564,7 @@ static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy, } return os_if_nan_process_ndp_cmd(hdd_ctx->psoc, data, data_len, - hdd_is_ndp_allowed(hdd_ctx)); + hdd_is_ndp_allowed(hdd_ctx), wdev); } /** diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 7099e39b2498..1a82311dedfc 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -572,11 +572,23 @@ void hdd_enable_ns_offload(struct hdd_adapter *adapter, ns_req->trigger = trigger; ns_req->count = 0; + vdev = hdd_objmgr_get_vdev(adapter); + if (!vdev) { + hdd_err("vdev is NULL"); + goto free_req; + } + /* check if offload cache and send is required or not */ status = ucfg_pmo_ns_offload_check(psoc, trigger, adapter->vdev_id); if (QDF_IS_STATUS_ERROR(status)) { hdd_debug("NS offload is not required"); - goto free_req; + goto put_vdev; + } + + if (ucfg_pmo_get_arp_ns_offload_dynamic_disable(vdev)) { + hdd_debug("Dynamic arp ns offload disabled"); + ucfg_pmo_flush_ns_offload_req(vdev); + goto skip_cache_ns; } /* Unicast Addresses */ @@ -586,7 +598,7 @@ void hdd_enable_ns_offload(struct hdd_adapter *adapter, if (errno) { hdd_disable_ns_offload(adapter, trigger); hdd_debug("Max supported addresses: disabling NS offload"); - goto free_req; + goto put_vdev; } /* Anycast Addresses */ @@ -596,21 +608,17 @@ void hdd_enable_ns_offload(struct hdd_adapter *adapter, if (errno) { hdd_disable_ns_offload(adapter, trigger); hdd_debug("Max supported addresses: disabling NS offload"); - goto free_req; + goto put_vdev; } /* cache ns request */ status = ucfg_pmo_cache_ns_offload_req(ns_req); if (QDF_IS_STATUS_ERROR(status)) { hdd_debug("Failed to cache ns request; status:%d", status); - goto free_req; + goto put_vdev; } - vdev = hdd_objmgr_get_vdev(adapter); - if (!vdev) { - hdd_err("vdev is NULL"); - goto free_req; - } +skip_cache_ns: /* enable ns request */ status = ucfg_pmo_enable_ns_offload_in_fwr(vdev, trigger); if (QDF_IS_STATUS_ERROR(status)) { @@ -1284,6 +1292,12 @@ void hdd_enable_arp_offload(struct hdd_adapter *adapter, goto put_vdev; } + if (ucfg_pmo_get_arp_ns_offload_dynamic_disable(vdev)) { + hdd_debug("Dynamic arp ns offload disabled"); + ucfg_pmo_flush_arp_offload_req(vdev); + goto skip_cache_arp; + } + ifa = hdd_get_ipv4_local_interface(adapter); if (!ifa || !ifa->ifa_local) { hdd_info("IP Address is not assigned"); @@ -1299,6 +1313,7 @@ void hdd_enable_arp_offload(struct hdd_adapter *adapter, goto put_vdev; } +skip_cache_arp: status = ucfg_pmo_enable_arp_offload_in_fwr(vdev, trigger); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("failed arp offload config in fw; status:%d", status); diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index bea3c20e9dc7..2c3d3538966a 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 2 #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 8 -#define QWLAN_VERSION_EXTRA "V" -#define QWLAN_VERSION_BUILD 33 +#define QWLAN_VERSION_EXTRA "F" +#define QWLAN_VERSION_BUILD 34 -#define QWLAN_VERSIONSTR "2.0.8.33V" +#define QWLAN_VERSIONSTR "2.0.8.34F" #endif /* QWLAN_VERSION_H */ diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index b535912d9f3b..e75bf160a7a2 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2033,7 +2033,7 @@ void lim_calculate_tpc(struct mac_context *mac, qdf_freq_t oper_freq, start_freq = 0; struct ch_params ch_params; struct vdev_mlme_obj *mlme_obj; - uint8_t tpe_power; + int8_t tpe_power; bool skip_tpe = false; mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev); @@ -2156,7 +2156,14 @@ void lim_calculate_tpc(struct mac_context *mac, tpe_power = mlme_obj->reg_tpc_obj.eirp_power; else tpe_power = mlme_obj->reg_tpc_obj.tpe[i]; - max_tx_power = QDF_MIN(max_tx_power, (int8_t)tpe_power); + /** + * AP advertises TPE IE tx power as 8-bit unsigned int. + * STA needs to convert it into an 8-bit 2s complement + * signed integer in the range –64 dBm to 63 dBm with a + * 0.5 dB step + */ + tpe_power /= 2; + max_tx_power = QDF_MIN(max_tx_power, tpe_power); pe_debug("TPE: %d", tpe_power); } diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index e8201f66e67f..5adda9196469 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -441,6 +441,9 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds, uint8_t oper_mode; uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); uint8_t ch_width = 0, ch_bw; + tDot11fIEVHTCaps *vht_caps = NULL; + tDot11fIEVHTOperation *vht_op = NULL; + uint8_t bcn_vht_chwidth = 0; /* * Ignore opmode change during channel change The opmode will be updated @@ -459,12 +462,24 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds, return; } - if (!(session->vhtCapability && bcn->VHTOperation.present)) + if (bcn->VHTCaps.present) { + vht_caps = &bcn->VHTCaps; + vht_op = &bcn->VHTOperation; + } else if (bcn->vendor_vht_ie.VHTCaps.present) { + vht_caps = &bcn->vendor_vht_ie.VHTCaps; + vht_op = &bcn->vendor_vht_ie.VHTOperation; + } + + if (!(session->vhtCapability && (vht_op && vht_op->present))) return; + bcn_vht_chwidth = lim_get_vht_ch_width(&bcn->VHTCaps, + &bcn->VHTOperation, + &bcn->HTInfo); + oper_mode = sta_ds->vhtSupportedChannelWidthSet; if ((oper_mode == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) && - (oper_mode < bcn->VHTOperation.chanWidth)) + (oper_mode < bcn_vht_chwidth)) skip_opmode_update = true; if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cb_mode) { @@ -479,24 +494,23 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds, } if (!skip_opmode_update && - (oper_mode != bcn->VHTOperation.chanWidth)) { - pe_debug("received VHTOP CHWidth %d", - bcn->VHTOperation.chanWidth); + (oper_mode != bcn_vht_chwidth)) { + pe_debug("received VHTOP CHWidth %d", bcn_vht_chwidth); pe_debug("MAC - %0x:%0x:%0x:%0x:%0x:%0x", mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2], mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]); - if ((bcn->VHTOperation.chanWidth >= + if ((bcn_vht_chwidth >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) && (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { pe_debug("Updating the CH Width to 160MHz"); sta_ds->vhtSupportedChannelWidthSet = - bcn->VHTOperation.chanWidth; + bcn_vht_chwidth; sta_ds->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; ch_width = eHT_CHANNEL_WIDTH_160MHZ; - } else if (bcn->VHTOperation.chanWidth >= + } else if (bcn_vht_chwidth >= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { pe_debug("Updating the CH Width to 80MHz"); sta_ds->vhtSupportedChannelWidthSet = @@ -504,7 +518,7 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds, sta_ds->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; ch_width = eHT_CHANNEL_WIDTH_80MHZ; - } else if (bcn->VHTOperation.chanWidth == + } else if (bcn_vht_chwidth == WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) { sta_ds->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 81ab4af7735a..db80ce6aa8a4 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2019,8 +2019,8 @@ static QDF_STATUS sap_cac_start_notify(mac_handle_t mac_handle) /* Don't start CAC for non-dfs channel, its violation */ profile = &sap_context->csr_roamProfile; ch_freq = profile->op_freq; - if (!wlan_reg_is_dfs_for_freq(mac->pdev, - ch_freq)) + if (!wlan_reg_is_dfs_for_freq(mac->pdev, ch_freq) && + wlan_reg_get_5g_bonded_channel_state_for_freq(mac->pdev, ch_freq, profile->ch_params.ch_width) != CHANNEL_STATE_DFS) continue; sap_debug("sapdfs: Signaling eSAP_DFS_CAC_START to HDD for sapctx[%pK]", sap_context); diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index e0262ec99646..a8dd5410829e 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -3230,7 +3230,8 @@ qdf_freq_t wlansap_get_chan_band_restrict(struct sap_context *sap_ctx, sap_debug("Restore chan freq: %d, width: %d", restart_freq, restart_ch_width); *csa_reason = CSA_REASON_BAND_RESTRICTED; - } else if (wlan_reg_is_disable_for_freq(mac->pdev, + } else if (wlan_reg_is_disable_in_secondary_list_for_freq( + mac->pdev, sap_ctx->chan_freq)) { sap_debug("channel is disabled"); *csa_reason = CSA_REASON_CHAN_DISABLED; diff --git a/os_if/nan/inc/os_if_nan.h b/os_if/nan/inc/os_if_nan.h index 17f829b13339..f67def17c9bb 100644 --- a/os_if/nan/inc/os_if_nan.h +++ b/os_if/nan/inc/os_if_nan.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -54,12 +55,14 @@ struct ndi_find_vdev_filter { * @data_len: length of data * @is_ndp_allowed: Indicates whether to allow NDP creation. * NDI creation is always allowed. + * @wdev: Wireless device structure pointer * * Return: status of operation */ int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc, const void *data, int data_len, - bool is_ndp_allowed); + bool is_ndp_allowed, + struct wireless_dev *wdev); /** * os_if_nan_register_hdd_callbacks: os_if api to register hdd callbacks diff --git a/os_if/nan/src/os_if_nan.c b/os_if/nan/src/os_if_nan.c index 9a5996463cbd..252dada24b32 100644 --- a/os_if/nan/src/os_if_nan.c +++ b/os_if/nan/src/os_if_nan.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -759,7 +759,6 @@ static int os_if_nan_process_ndp_initiator_req(struct wlan_objmgr_psoc *psoc, * Return: 0 on success or error code on failure */ static int __os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc, - char *iface_name, struct nlattr **tb) { int ret = 0; @@ -767,6 +766,8 @@ static int __os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc, enum nan_datapath_state state; struct wlan_objmgr_vdev *nan_vdev = NULL; struct nan_datapath_responder_req req = {0}; + char *iface_name; + int errno; if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]) { osif_err("ndp_rsp is unavailable"); @@ -775,6 +776,13 @@ static int __os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc, req.ndp_rsp = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]); if (req.ndp_rsp == NAN_DATAPATH_RESPONSE_ACCEPT) { + errno = osif_nla_str(tb, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, + &iface_name); + + if (errno) { + osif_err("NAN data iface not provided"); + return errno; + } /* Check for an existing NAN interface */ nan_vdev = os_if_get_ndi_vdev_by_ifname(psoc, iface_name); if (!nan_vdev) { @@ -902,26 +910,17 @@ responder_req_failed: } static int os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc, - struct nlattr **tb) + struct nlattr **tb, + struct wireless_dev *wdev) { - struct net_device *net_dev; struct osif_vdev_sync *vdev_sync; - char *ifname; int errno; - errno = osif_nla_str(tb, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, &ifname); + errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); if (errno) return errno; - errno = osif_net_dev_from_ifname(psoc, ifname, &net_dev); - if (errno) - return errno; - - errno = osif_vdev_sync_op_start(net_dev, &vdev_sync); - if (errno) - return errno; - - errno = __os_if_nan_process_ndp_responder_req(psoc, ifname, tb); + errno = __os_if_nan_process_ndp_responder_req(psoc, tb); osif_vdev_sync_op_stop(vdev_sync); @@ -1021,7 +1020,8 @@ static int os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc, int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc, const void *data, int data_len, - bool is_ndp_allowed) + bool is_ndp_allowed, + struct wireless_dev *wdev) { uint32_t ndp_cmd_type; uint16_t transaction_id; @@ -1084,7 +1084,7 @@ int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc, osif_err("Unsupported concurrency for NAN datapath"); return -EOPNOTSUPP; } - return os_if_nan_process_ndp_responder_req(psoc, tb); + return os_if_nan_process_ndp_responder_req(psoc, tb, wdev); case QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST: if (!is_ndp_allowed) { osif_err("Unsupported concurrency for NAN datapath"); diff --git a/os_if/pkt_capture/src/os_if_pkt_capture.c b/os_if/pkt_capture/src/os_if_pkt_capture.c index c1e836a57ffc..eae4ca23fa56 100644 --- a/os_if/pkt_capture/src/os_if_pkt_capture.c +++ b/os_if/pkt_capture/src/os_if_pkt_capture.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -150,7 +150,7 @@ QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter, BIT(SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL); } - osif_debug("Monitor mode config %s data tx %d data rx %d mgmt tx %d mgmt rx %d ctrl tx %d ctrl rx %d bi %d\n", + osif_debug("Monitor mode config data tx %d data rx %d mgmt tx %d mgmt rx %d ctrl tx %d ctrl rx %d bi %d\n", frame_filter.data_tx_frame_filter, frame_filter.data_rx_frame_filter, frame_filter.mgmt_tx_frame_filter,