diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 6f2248f623bd..f8dd1a46856b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -4484,4 +4484,18 @@ int hdd_update_phymode(struct hdd_adapter *adapter, eCsrPhyMode phymode, */ bool hdd_max_sta_vdev_count_reached(struct hdd_context *hdd_ctx); +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +/** + * hdd_beacon_latency_event_cb() - Callback function to get latency level + * @latency_level: latency level received from firmware + * + * Return: None + */ +void hdd_beacon_latency_event_cb(uint32_t latency_level); +#else +static inline void hdd_beacon_latency_event_cb(uint32_t latency_level) +{ +} +#endif + #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c47152b40e13..e2f67a48695b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -14223,6 +14223,11 @@ int hdd_register_cb(struct hdd_context *hdd_ctx) if (QDF_IS_STATUS_ERROR(status)) hdd_err_rl("Register monitor mode callback failed"); + status = sme_set_beacon_latency_event_cb(mac_handle, + hdd_beacon_latency_event_cb); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err_rl("Register beacon latency event callback failed"); + hdd_exit(); return ret; @@ -17760,6 +17765,20 @@ free: return ret; } +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +void hdd_beacon_latency_event_cb(uint32_t latency_level) +{ + struct hdd_context *hdd_ctx; + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hdd_err_rl("Invalid HDD_CTX"); + return; + } + wlan_hdd_set_wlm_mode(hdd_ctx, latency_level); +} +#endif + #ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2) { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index cba9c04a2859..cb2af46fcd8e 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -4223,4 +4223,26 @@ sme_process_monitor_mode_vdev_up_evt(uint8_t vdev_id) } #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +/** + * sme_set_beacon_latency_event_cb() - Register beacon latency IE callback + * @mac_handle: Opaque handle to the MAC context + * @beacon_latency_event_cb: callback to be registered + * + * Return: QDF_STATUS + */ +QDF_STATUS +sme_set_beacon_latency_event_cb(mac_handle_t mac_handle, + void (*beacon_latency_event_cb) + (uint32_t latency_level)); +#else +static inline QDF_STATUS +sme_set_beacon_latency_event_cb(mac_handle_t mac_handle, + void (*beacon_latency_event_cb) + (uint32_t latency_level)) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index b186a87fd8ff..498069dc650e 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -389,6 +389,9 @@ struct sme_context { #ifdef FEATURE_MONITOR_MODE_SUPPORT void (*monitor_mode_cb)(uint8_t vdev_id); #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) + void (*beacon_latency_event_cb)(uint32_t latency_level); +#endif }; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 4b4e4f1c611b..5fbed0c3f86b 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -16263,3 +16263,24 @@ QDF_STATUS sme_process_monitor_mode_vdev_up_evt(uint8_t vdev_id) return QDF_STATUS_SUCCESS; } #endif + +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +QDF_STATUS +sme_set_beacon_latency_event_cb(mac_handle_t mac_handle, + void (*beacon_latency_event_cb) + (uint32_t latency_level)) +{ + QDF_STATUS qdf_status; + struct mac_context *mac = MAC_CONTEXT(mac_handle); + + qdf_status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + sme_err("Failed to acquire sme lock; status: %d", qdf_status); + return qdf_status; + } + mac->sme.beacon_latency_event_cb = beacon_latency_event_cb; + sme_release_global_lock(&mac->sme); + + return qdf_status; +} +#endif diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 3ac9b691206d..c11defd6bb82 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1499,6 +1499,26 @@ int wma_unified_beacon_debug_stats_event_handler(void *handle, uint8_t *cmd_param_info, uint32_t len); +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +/** + * wma_vdev_bcn_latency_event_handler() - Get the latency info received in bcn + * @handle: WMA handle + * @event: data in event + * @len: length + * + * Return: 0 for success or error code + */ +int wma_vdev_bcn_latency_event_handler(void *handle, uint8_t *event, + uint32_t len); +#else +static inline int wma_vdev_bcn_latency_event_handler(void *handle, + uint8_t *event, + uint32_t len) +{ + return 0; +} +#endif + #ifdef FEATURE_WLAN_DIAG_SUPPORT /** * wma_sta_kickout_event()- send sta kickout event diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index fcf765af5334..4fae932594ef 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -4705,6 +4705,46 @@ int wma_unified_beacon_debug_stats_event_handler(void *handle, } #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +int +wma_vdev_bcn_latency_event_handler(void *handle, + uint8_t *event_info, + uint32_t len) +{ + WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *param_buf = NULL; + wmi_vdev_bcn_latency_fixed_param *bcn_latency = NULL; + struct mac_context *mac = + (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); + uint32_t latency_level; + + param_buf = (WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *)event_info; + if (!param_buf) { + wma_err("Invalid bcn latency event"); + return -EINVAL; + } + + bcn_latency = param_buf->fixed_param; + if (!bcn_latency) { + wma_debug("beacon latency event fixed param is NULL"); + return -EINVAL; + } + + /* Map the latency value to the level which host expects + * 1 - normal, 2 - moderate, 3 - low, 4 - ultralow + */ + latency_level = bcn_latency->latency_level + 1; + if (latency_level < 1 || latency_level > 4) { + wma_debug("invalid beacon latency level value"); + return -EINVAL; + } + + /* Call the registered sme callback */ + mac->sme.beacon_latency_event_cb(latency_level); + + return 0; +} +#endif + int wma_chan_info_event_handler(void *handle, uint8_t *event_buf, uint32_t len) { diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 143706116083..8c3c01dd50ef 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3134,6 +3134,12 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, WMA_RX_SERIALIZER_CTX); #endif +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) + wmi_unified_register_event_handler(wma_handle->wmi_handle, + wmi_vdev_bcn_latency_event_id, + wma_vdev_bcn_latency_event_handler, + WMA_RX_SERIALIZER_CTX); +#endif /* register for linkspeed response event */ wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_peer_estimated_linkspeed_event_id,