diff --git a/Kbuild b/Kbuild
index 02704aa418cd..004d3e47406a 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2603,6 +2603,7 @@ cppflags-y += -DANI_OS_TYPE_ANDROID=6 \
-Werror\
-D__linux__
+cppflags-$(CONFIG_THERMAL_STATS_SUPPORT) += -DTHERMAL_STATS_SUPPORT
cppflags-$(CONFIG_PTT_SOCK_SVC_ENABLE) += -DPTT_SOCK_SVC_ENABLE
cppflags-$(CONFIG_FEATURE_WLAN_WAPI) += -DFEATURE_WLAN_WAPI
cppflags-$(CONFIG_FEATURE_WLAN_WAPI) += -DATH_SUPPORT_WAPI
diff --git a/components/fw_offload/core/inc/wlan_fw_offload_main.h b/components/fw_offload/core/inc/wlan_fw_offload_main.h
index 756c0cff1c22..1c40671c85a0 100644
--- a/components/fw_offload/core/inc/wlan_fw_offload_main.h
+++ b/components/fw_offload/core/inc/wlan_fw_offload_main.h
@@ -51,10 +51,12 @@
/**
* enum wlan_fwol_southbound_event - fw offload south bound event type
* @WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE: get eLNA bypass response
+ * @WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE: get Thermal Stats response
*/
enum wlan_fwol_southbound_event {
WLAN_FWOL_EVT_INVALID = 0,
WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE,
+ WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE,
WLAN_FWOL_EVT_LAST,
WLAN_FWOL_EVT_MAX = WLAN_FWOL_EVT_LAST - 1
};
@@ -116,6 +118,7 @@ struct wlan_fwol_coex_config {
* @priority_apps: Priority of the apps mitigation to consider by fw
* @priority_wpps: Priority of the wpps mitigation to consider by fw
* @thermal_action: thermal action as defined enum thermal_mgmt_action_code
+ * @therm_stats_offset: thermal temp offset as set in gThermalStatsTempOffset
*/
struct wlan_fwol_thermal_temp {
bool thermal_mitigation_enable;
@@ -128,6 +131,9 @@ struct wlan_fwol_thermal_temp {
uint8_t priority_apps;
uint8_t priority_wpps;
enum thermal_mgmt_action_code thermal_action;
+#ifdef THERMAL_STATS_SUPPORT
+ uint8_t therm_stats_offset;
+#endif
};
/**
@@ -275,18 +281,30 @@ struct wlan_fwol_cfg {
bool disable_hw_assist;
};
+/**
+ * struct wlan_fwol_capability_info - FW offload capability component
+ * @fw_thermal_stats_cap: Thermal Stats Fw capability
+ **/
+struct wlan_fwol_capability_info {
+#ifdef THERMAL_STATS_SUPPORT
+ bool fw_thermal_stats_cap;
+#endif
+};
+
/**
* struct wlan_fwol_psoc_obj - FW offload psoc priv object
* @cfg: cfg items
* @cbs: callback functions
* @tx_ops: tx operations for target interface
* @rx_ops: rx operations for target interface
+ * @capability_info: fwol capability info
*/
struct wlan_fwol_psoc_obj {
struct wlan_fwol_cfg cfg;
struct wlan_fwol_callbacks cbs;
struct wlan_fwol_tx_ops tx_ops;
struct wlan_fwol_rx_ops rx_ops;
+ struct wlan_fwol_capability_info capability_info;
};
/**
@@ -294,6 +312,7 @@ struct wlan_fwol_psoc_obj {
* @psoc: psoc handle
* @event_id: event ID
* @get_elna_bypass_response: get eLNA bypass response
+ * @get_thermal_stats_response: get thermal stats response
*/
struct wlan_fwol_rx_event {
struct wlan_objmgr_psoc *psoc;
@@ -301,6 +320,9 @@ struct wlan_fwol_rx_event {
union {
#ifdef WLAN_FEATURE_ELNA
struct get_elna_bypass_response get_elna_bypass_response;
+#endif
+#ifdef THERMAL_STATS_SUPPORT
+ struct thermal_throttle_info get_thermal_stats_response;
#endif
};
};
diff --git a/components/fw_offload/core/src/wlan_fw_offload_main.c b/components/fw_offload/core/src/wlan_fw_offload_main.c
index 88539722502a..bc429b87fe7f 100644
--- a/components/fw_offload/core/src/wlan_fw_offload_main.c
+++ b/components/fw_offload/core/src/wlan_fw_offload_main.c
@@ -111,6 +111,22 @@ fwol_init_coex_config_in_cfg(struct wlan_objmgr_psoc *psoc,
CFG_BLE_SCAN_COEX_POLICY);
}
+#ifdef THERMAL_STATS_SUPPORT
+static void
+fwol_init_thermal_stats_in_cfg(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_thermal_temp *thermal_temp)
+{
+ thermal_temp->therm_stats_offset =
+ cfg_get(psoc, CFG_THERMAL_STATS_TEMP_OFFSET);
+}
+#else
+static void
+fwol_init_thermal_stats_in_cfg(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_thermal_temp *thermal_temp)
+{
+}
+#endif
+
static void
fwol_init_thermal_temp_in_cfg(struct wlan_objmgr_psoc *psoc,
struct wlan_fwol_thermal_temp *thermal_temp)
@@ -155,7 +171,7 @@ fwol_init_thermal_temp_in_cfg(struct wlan_objmgr_psoc *psoc,
cfg_get(psoc, CFG_THERMAL_WPPS_PRIOITY);
thermal_temp->thermal_action =
cfg_get(psoc, CFG_THERMAL_MGMT_ACTION);
-
+ fwol_init_thermal_stats_in_cfg(psoc, thermal_temp);
}
QDF_STATUS fwol_init_neighbor_report_cfg(struct wlan_objmgr_psoc *psoc,
@@ -622,6 +638,59 @@ fwol_process_get_elna_bypass_resp(struct wlan_fwol_rx_event *event)
}
#endif /* WLAN_FEATURE_ELNA */
+#ifdef THERMAL_STATS_SUPPORT
+/**
+ * fwol_process_get_thermal_stats_resp() - Process get thermal stats response
+ * @event: response event
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+static QDF_STATUS
+fwol_process_get_thermal_stats_resp(struct wlan_fwol_rx_event *event)
+{
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+ struct wlan_objmgr_psoc *psoc;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_callbacks *cbs;
+ struct thermal_throttle_info *resp;
+
+ if (!event) {
+ fwol_err("Event buffer is NULL");
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ psoc = event->psoc;
+ if (!psoc) {
+ fwol_err("psoc is NULL");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ cbs = &fwol_obj->cbs;
+ if (cbs && cbs->get_thermal_stats_callback) {
+ resp = &event->get_thermal_stats_response;
+ cbs->get_thermal_stats_callback(cbs->get_thermal_stats_context,
+ resp);
+ } else {
+ fwol_err("NULL pointer for callback");
+ status = QDF_STATUS_E_IO;
+ }
+
+ return status;
+}
+#else
+static QDF_STATUS
+fwol_process_get_thermal_stats_resp(struct wlan_fwol_rx_event *event)
+{
+ return QDF_STATUS_E_NOSUPPORT;
+}
+#endif /* THERMAL_STATS_SUPPORT */
+
QDF_STATUS fwol_process_event(struct scheduler_msg *msg)
{
QDF_STATUS status;
@@ -641,6 +710,9 @@ QDF_STATUS fwol_process_event(struct scheduler_msg *msg)
case WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE:
status = fwol_process_get_elna_bypass_resp(event);
break;
+ case WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE:
+ status = fwol_process_get_thermal_stats_resp(event);
+ break;
default:
status = QDF_STATUS_E_INVAL;
break;
diff --git a/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h b/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h
index e91b21dda32d..afcca4faa1dc 100644
--- a/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h
+++ b/components/fw_offload/dispatcher/inc/cfg_thermal_temp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018,2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018,2020-2021 The Linux Foundation. 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
@@ -430,6 +430,31 @@
CFG_VALUE_OR_DEFAULT, \
"Thermal management action")
+/*
+ * gThermalStatsTempOffset - Configure the thermal stats offset
+ *
+ * @Min: 0
+ * @Max: 10
+ * @Default: 5
+ *
+ * This ini will configure Thermal temperature offset value for capturing
+ * thermal stats in thermal range.
+ * Thermal STATS start capturing from temperature threshold to temperature
+ * threshold + offset.
+ * If the value 0 is given then then thermal STATS capture is disabled
+ *
+ * Usage: External
+ *
+ *
+ */
+#define CFG_THERMAL_STATS_TEMP_OFFSET CFG_INI_UINT( \
+ "gThermalStatsTempOffset", \
+ 0, \
+ 10, \
+ 5, \
+ CFG_VALUE_OR_DEFAULT, \
+ "Thermal Stats Temperature Offset")
+
#define CFG_THERMAL_TEMP_ALL \
CFG(CFG_THERMAL_TEMP_MIN_LEVEL0) \
CFG(CFG_THERMAL_TEMP_MAX_LEVEL0) \
@@ -450,6 +475,7 @@
CFG(CFG_THERMAL_SAMPLING_TIME) \
CFG(CFG_THERMAL_APPS_PRIORITY) \
CFG(CFG_THERMAL_WPPS_PRIOITY) \
- CFG(CFG_THERMAL_MGMT_ACTION)
+ CFG(CFG_THERMAL_MGMT_ACTION) \
+ CFG(CFG_THERMAL_STATS_TEMP_OFFSET)
#endif
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h b/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
index 10f253a8bb90..cf3c30aec0e0 100644
--- a/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021 The Linux Foundation. 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
@@ -24,6 +24,8 @@
#define _WLAN_FWOL_PUBLIC_STRUCTS_H_
#include "wlan_objmgr_psoc_obj.h"
+#include "wlan_thermal_public_struct.h"
+#include "wmi_unified.h"
#ifdef WLAN_FEATURE_ELNA
/**
@@ -57,10 +59,28 @@ struct get_elna_bypass_response {
};
#endif
+/**
+ * struct thermal_throttle_info - thermal throttle info from Target
+ * @temperature: current temperature in c Degree
+ * @level: target thermal level info
+ * @pdev_id: pdev id
+ * @therm_throt_levels: Number of thermal throttle levels
+ * @level_info: Thermal Stats for each level
+ */
+struct thermal_throttle_info {
+ uint32_t temperature;
+ enum thermal_throttle_level level;
+ uint32_t pdev_id;
+ uint32_t therm_throt_levels;
+ struct thermal_throt_level_stats level_info[WMI_THERMAL_STATS_TEMP_THRESH_LEVEL_MAX];
+};
+
/**
* struct wlan_fwol_callbacks - fw offload callbacks
* @get_elna_bypass_callback: callback for get eLNA bypass
* @get_elna_bypass_context: context for get eLNA bypass
+ * @get_thermal_stats_callback: callback for get thermal stats
+ * @get_thermal_stats_context: context for get thermal stats
*/
struct wlan_fwol_callbacks {
#ifdef WLAN_FEATURE_ELNA
@@ -68,6 +88,11 @@ struct wlan_fwol_callbacks {
struct get_elna_bypass_response *response);
void *get_elna_bypass_context;
#endif
+#ifdef THERMAL_STATS_SUPPORT
+ void (*get_thermal_stats_callback)(void *context,
+ struct thermal_throttle_info *response);
+ void *get_thermal_stats_context;
+#endif
};
/**
@@ -77,6 +102,7 @@ struct wlan_fwol_callbacks {
* @reg_evt_handler: register event handler
* @unreg_evt_handler: unregister event handler
* @send_dscp_up_map_to_fw: send dscp-to-up map values to FW
+ * @get_thermal_stats: send get_thermal_stats cmd to FW
*/
struct wlan_fwol_tx_ops {
#ifdef WLAN_FEATURE_ELNA
@@ -94,17 +120,27 @@ struct wlan_fwol_tx_ops {
struct wlan_objmgr_psoc *psoc,
uint32_t *dscp_to_up_map);
#endif
+#ifdef THERMAL_STATS_SUPPORT
+ QDF_STATUS (*get_thermal_stats)(struct wlan_objmgr_psoc *psoc,
+ enum thermal_stats_request_type req_type,
+ uint8_t therm_stats_offset);
+#endif
};
/**
* struct wlan_fwol_rx_ops - structure of rx func pointers
* @get_elna_bypass_resp: get eLNA bypass response
+ * @get_thermal_stats_resp: thermal stats cmd response callback to fwol
*/
struct wlan_fwol_rx_ops {
#ifdef WLAN_FEATURE_ELNA
QDF_STATUS (*get_elna_bypass_resp)(struct wlan_objmgr_psoc *psoc,
struct get_elna_bypass_response *resp);
#endif
+#ifdef THERMAL_STATS_SUPPORT
+ QDF_STATUS (*get_thermal_stats_resp)(struct wlan_objmgr_psoc *psoc,
+ struct thermal_throttle_info *resp);
+#endif
};
#endif /* _WLAN_FWOL_PUBLIC_STRUCTS_H_ */
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
index 44f6148f4e99..e69674368565 100644
--- a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
@@ -608,6 +608,26 @@ QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw(
}
#endif
+/**
+ * ucfg_fwol_update_fw_cap_info - API to update fwol capability info
+ * @psoc: pointer to psoc object
+ * @caps: pointer to wlan_fwol_capability_info struct
+ *
+ * Used to update fwol capability info.
+ *
+ * Return: void
+ */
+void ucfg_fwol_update_fw_cap_info(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_capability_info *caps);
+
+#ifdef THERMAL_STATS_SUPPORT
+QDF_STATUS ucfg_fwol_send_get_thermal_stats_cmd(struct wlan_objmgr_psoc *psoc,
+ enum thermal_stats_request_type req_type,
+ void (*callback)(void *context,
+ struct thermal_throttle_info *response),
+ void *context);
+#endif /* THERMAL_STATS_SUPPORT */
+
/**
* ucfg_fwol_configure_global_params - API to configure global params
* @psoc: pointer to psoc object
diff --git a/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c b/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c
index a8f88506b934..984f9ad846bf 100644
--- a/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c
+++ b/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c
@@ -166,9 +166,67 @@ static void tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
}
#endif /* WLAN_FEATURE_ELNA */
+#ifdef THERMAL_STATS_SUPPORT
+static QDF_STATUS
+tgt_fwol_get_thermal_stats_resp(struct wlan_objmgr_psoc *psoc,
+ struct thermal_throttle_info *resp)
+{
+ QDF_STATUS status;
+ struct scheduler_msg msg = {0};
+ struct wlan_fwol_rx_event *event;
+
+ event = qdf_mem_malloc(sizeof(*event));
+ if (!event)
+ return QDF_STATUS_E_NOMEM;
+
+ status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FWOL_SB_ID);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ fwol_err("Failed to get psoc ref");
+ fwol_release_rx_event(event);
+ return status;
+ }
+
+ event->psoc = psoc;
+ event->event_id = WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE;
+ event->get_thermal_stats_response = *resp;
+ msg.type = WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE;
+ msg.bodyptr = event;
+ msg.callback = fwol_process_event;
+ msg.flush_callback = fwol_flush_callback;
+ status = scheduler_post_message(QDF_MODULE_ID_FWOL,
+ QDF_MODULE_ID_FWOL,
+ QDF_MODULE_ID_TARGET_IF, &msg);
+
+ if (QDF_IS_STATUS_SUCCESS(status))
+ return QDF_STATUS_SUCCESS;
+
+ fwol_err("failed to send WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE msg");
+ fwol_flush_callback(&msg);
+
+ return status;
+}
+
+static void
+tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops *rx_ops)
+{
+ rx_ops->get_thermal_stats_resp = tgt_fwol_get_thermal_stats_resp;
+}
+#else
+static void
+tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops *rx_ops)
+{
+}
+#endif
+
+static void tgt_fwol_register_thermal_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
+{
+ tgt_fwol_register_thermal_stats_resp(rx_ops);
+}
+
QDF_STATUS tgt_fwol_register_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
{
tgt_fwol_register_elna_rx_ops(rx_ops);
+ tgt_fwol_register_thermal_rx_ops(rx_ops);
return QDF_STATUS_SUCCESS;
}
diff --git a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
index 4d966aaeaaa5..af4dbf45abe1 100644
--- a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
+++ b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
@@ -1001,6 +1001,96 @@ QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev,
}
#endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */
+void ucfg_fwol_update_fw_cap_info(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_capability_info *caps)
+{
+ struct wlan_fwol_psoc_obj *fwol_obj;
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get fwol obj");
+ return;
+ }
+
+ qdf_mem_copy(&fwol_obj->capability_info, caps,
+ sizeof(fwol_obj->capability_info));
+}
+
+#ifdef THERMAL_STATS_SUPPORT
+static QDF_STATUS
+ucfg_fwol_get_cap(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_capability_info *cap_info)
+{
+ struct wlan_fwol_psoc_obj *fwol_obj;
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get fwol obj");
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ if (!cap_info) {
+ fwol_err("Failed to get fwol obj");
+ return QDF_STATUS_E_FAILURE;
+ }
+ *cap_info = fwol_obj->capability_info;
+
+ return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS ucfg_fwol_send_get_thermal_stats_cmd(struct wlan_objmgr_psoc *psoc,
+ enum thermal_stats_request_type req_type,
+ void (*callback)(void *context,
+ struct thermal_throttle_info *response),
+ void *context)
+{
+ QDF_STATUS status;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_tx_ops *tx_ops;
+ struct wlan_fwol_thermal_temp thermal_temp = {0};
+ struct wlan_fwol_capability_info cap_info;
+ struct wlan_fwol_callbacks *cbs;
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ status = ucfg_fwol_get_thermal_temp(psoc, &thermal_temp);
+ if (QDF_IS_STATUS_ERROR(status))
+ return QDF_STATUS_E_INVAL;
+
+ status = ucfg_fwol_get_cap(psoc, &cap_info);
+ if (QDF_IS_STATUS_ERROR(status))
+ return QDF_STATUS_E_INVAL;
+
+ if (!thermal_temp.therm_stats_offset ||
+ !cap_info.fw_thermal_stats_cap) {
+ fwol_err("Command Disabled in Ini gThermalStatsTempOffset %d or not enabled in FW %d",
+ thermal_temp.therm_stats_offset,
+ cap_info.fw_thermal_stats_cap);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ /* Registering Callback for the Request command */
+ if (callback && context) {
+ cbs = &fwol_obj->cbs;
+ cbs->get_thermal_stats_callback = callback;
+ cbs->get_thermal_stats_context = context;
+ }
+
+ tx_ops = &fwol_obj->tx_ops;
+ if (tx_ops && tx_ops->get_thermal_stats)
+ status = tx_ops->get_thermal_stats(psoc, req_type,
+ thermal_temp.therm_stats_offset);
+ else
+ status = QDF_STATUS_E_INVAL;
+
+ return status;
+}
+#endif /* THERMAL_STATS_SUPPORT */
+
QDF_STATUS ucfg_fwol_configure_global_params(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev)
{
diff --git a/components/target_if/fw_offload/src/target_if_fwol.c b/components/target_if/fw_offload/src/target_if_fwol.c
index 11b651068c8f..124418889085 100644
--- a/components/target_if/fw_offload/src/target_if_fwol.c
+++ b/components/target_if/fw_offload/src/target_if_fwol.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021 The Linux Foundation. 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
@@ -240,10 +240,203 @@ target_if_fwol_register_dscp_up_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
}
#endif
+#ifdef THERMAL_STATS_SUPPORT
+/**
+ * target_if_fwol_get_thermal_stats() - send get thermal stats request to FW
+ * @psoc: pointer to PSOC object
+ * @req_type: get thermal stats request type
+ * @therm_stats_offset: thermal temp stats offset for each temp range
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+static QDF_STATUS
+target_if_fwol_get_thermal_stats(struct wlan_objmgr_psoc *psoc,
+ enum thermal_stats_request_type req_type,
+ uint8_t therm_stats_offset)
+{
+ QDF_STATUS status;
+ wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+
+ if (!wmi_handle) {
+ target_if_err("Invalid wmi_handle");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ status = wmi_unified_send_get_thermal_stats_cmd(wmi_handle, req_type,
+ therm_stats_offset);
+ if (status)
+ target_if_err("Failed to send get thermal stats cmd %d",
+ status);
+
+ return status;
+}
+
+static void
+target_if_fwol_register_thermal_stats_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
+{
+ tx_ops->get_thermal_stats = target_if_fwol_get_thermal_stats;
+}
+
+static QDF_STATUS
+target_if_fwol_handle_thermal_lvl_stats_evt(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_rx_ops *rx_ops,
+ struct thermal_throttle_info *info)
+{
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+ if (rx_ops->get_thermal_stats_resp && info->therm_throt_levels)
+ status = rx_ops->get_thermal_stats_resp(psoc, info);
+
+ return status;
+}
+
+static bool
+target_if_fwol_is_thermal_stats_enable(struct wlan_fwol_psoc_obj *fwol_obj)
+{
+ return (fwol_obj->capability_info.fw_thermal_stats_cap &&
+ fwol_obj->cfg.thermal_temp_cfg.therm_stats_offset);
+}
+
+/**
+ * target_if_fwol_thermal_throttle_event_handler() - handler for thermal
+ * throttle event
+ * @scn: scn handle
+ * @event_buf: pointer to the event buffer
+ * @len: length of the buffer
+ *
+ * Return: 0 on success
+ */
+static int
+target_if_fwol_thermal_throttle_event_handler(ol_scn_t scn, uint8_t *event_buf,
+ uint32_t len)
+{
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
+ struct thermal_throttle_info info = {0};
+ struct wlan_objmgr_psoc *psoc;
+ wmi_unified_t wmi_handle;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_rx_ops *rx_ops;
+
+ target_if_debug("scn:%pK, data:%pK, datalen:%d", scn, event_buf, len);
+ if (!scn || !event_buf)
+ return -EINVAL;
+
+ psoc = target_if_get_psoc_from_scn_hdl(scn);
+ if (!psoc) {
+ target_if_err("null psoc");
+ return -EINVAL;
+ }
+
+ wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+ if (!wmi_handle) {
+ target_if_err("Invalid wmi_handle");
+ return -EINVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ target_if_err("Failed to get FWOL Obj");
+ return -EINVAL;
+ }
+
+ status = wmi_extract_thermal_stats(wmi_handle,
+ event_buf,
+ &info.temperature,
+ &info.level,
+ &info.therm_throt_levels,
+ info.level_info,
+ &info.pdev_id);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ target_if_debug("Failed to convert thermal target level");
+ return -EINVAL;
+ }
+ rx_ops = &fwol_obj->rx_ops;
+ if (!rx_ops) {
+ target_if_debug("rx_ops Null");
+ return -EINVAL;
+ }
+
+ status = target_if_fwol_handle_thermal_lvl_stats_evt(psoc, rx_ops,
+ &info);
+ if (QDF_IS_STATUS_ERROR(status))
+ target_if_debug("thermal stats level response failed.");
+
+ return 0;
+}
+
+/**
+ * target_if_fwol_register_thermal_throttle_handler() - Register handler for
+ * thermal throttle stats firmware event
+ * @psoc: psoc object
+ *
+ * Return: void
+ */
+static void
+target_if_fwol_register_thermal_throttle_handler(struct wlan_objmgr_psoc *psoc)
+{
+ QDF_STATUS status;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ target_if_err("Failed to get FWOL Obj");
+ return;
+ }
+ if (!target_if_fwol_is_thermal_stats_enable(fwol_obj)) {
+ target_if_debug("thermal stats offload not enabled");
+ return;
+ }
+ status = wmi_unified_register_event_handler(
+ get_wmi_unified_hdl_from_psoc(psoc),
+ wmi_tt_stats_event_id,
+ target_if_fwol_thermal_throttle_event_handler,
+ WMI_RX_SERIALIZER_CTX);
+ if (QDF_IS_STATUS_ERROR(status))
+ target_if_debug("Failed to register thermal stats event cb");
+}
+
+/**
+ * target_if_fwol_unregister_thermal_stats_handler() - Register handler for
+ * thermal throttle stats firmware event
+ * @psoc: psoc object
+ *
+ * Return: void
+ */
+static void
+target_if_fwol_unregister_thermal_throttle_handler(
+ struct wlan_objmgr_psoc *psoc)
+{
+ QDF_STATUS status;
+
+ status = wmi_unified_unregister_event_handler(
+ get_wmi_unified_hdl_from_psoc(psoc),
+ wmi_tt_stats_event_id);
+ if (QDF_IS_STATUS_ERROR(status))
+ target_if_debug("Failed to unregister thermal stats event cb");
+}
+
+#else
+static void
+target_if_fwol_register_thermal_throttle_handler(struct wlan_objmgr_psoc *psoc)
+{
+}
+
+static void
+target_if_fwol_unregister_thermal_throttle_handler(
+ struct wlan_objmgr_psoc *psoc)
+{
+}
+static void
+target_if_fwol_register_thermal_stats_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
+{
+}
+#endif
+
QDF_STATUS target_if_fwol_register_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg)
{
target_if_fwol_register_elna_event_handler(psoc, arg);
+ target_if_fwol_register_thermal_throttle_handler(psoc);
return QDF_STATUS_SUCCESS;
}
@@ -253,6 +446,7 @@ target_if_fwol_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg)
{
target_if_fwol_unregister_elna_event_handler(psoc, arg);
+ target_if_fwol_unregister_thermal_throttle_handler(psoc);
return QDF_STATUS_SUCCESS;
}
@@ -261,6 +455,7 @@ QDF_STATUS target_if_fwol_register_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
{
target_if_fwol_register_elna_tx_ops(tx_ops);
target_if_fwol_register_dscp_up_tx_ops(tx_ops);
+ target_if_fwol_register_thermal_stats_tx_ops(tx_ops);
tx_ops->reg_evt_handler = target_if_fwol_register_event_handler;
tx_ops->unreg_evt_handler = target_if_fwol_unregister_event_handler;
diff --git a/configs/default_defconfig b/configs/default_defconfig
index b5ff35d4aab8..84d823a15564 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -207,6 +207,8 @@ CONFIG_QCOM_TDLS := y
CONFIG_WLAN_SYSFS := y
+CONFIG_THERMAL_STATS_SUPPORT := y
+
ifeq ($(CONFIG_WLAN_SYSFS), y)
CONFIG_WLAN_SYSFS_STA_INFO := y
CONFIG_WLAN_SYSFS_CHANNEL := y
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index bde9ab586ca4..044204bbcddd 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -2213,6 +2213,9 @@ struct hdd_context {
qdf_work_t twt_en_dis_work;
#endif
bool dump_in_progress;
+#ifdef THERMAL_STATS_SUPPORT
+ bool is_therm_stats_in_progress;
+#endif
};
/**
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 80e0c50c269c..677abe3abf00 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -196,6 +196,7 @@
#include "wlan_cm_roam_ucfg_api.h"
#include
#include "qdf_lock.h"
+#include "wlan_hdd_thermal.h"
#ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
@@ -13887,6 +13888,17 @@ static int hdd_init_mws_coex(struct hdd_context *hdd_ctx)
}
#endif
+#ifdef THERMAL_STATS_SUPPORT
+static void hdd_thermal_stats_cmd_init(struct hdd_context *hdd_ctx)
+{
+ hdd_send_get_thermal_stats_cmd(hdd_ctx, thermal_stats_init, NULL, NULL);
+}
+#else
+static void hdd_thermal_stats_cmd_init(struct hdd_context *hdd_ctx)
+{
+}
+#endif
+
/**
* hdd_features_init() - Init features
* @hdd_ctx: HDD context
@@ -14001,6 +14013,7 @@ static int hdd_features_init(struct hdd_context *hdd_ctx)
wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
ALLOWED_KEYMGMT_6G_MASK);
}
+ hdd_thermal_stats_cmd_init(hdd_ctx);
hdd_exit();
return 0;
diff --git a/core/hdd/src/wlan_hdd_thermal.c b/core/hdd/src/wlan_hdd_thermal.c
index 950eeb911cc2..18015a1cd5a2 100644
--- a/core/hdd/src/wlan_hdd_thermal.c
+++ b/core/hdd/src/wlan_hdd_thermal.c
@@ -36,8 +36,12 @@
#include
#include "wlan_fwol_ucfg_api.h"
#include
+#include "os_if_fwol.h"
+#include "wlan_osif_request_manager.h"
+#include "wlan_fwol_public_structs.h"
#define DC_OFF_PERCENT_WPPS 50
+#define WLAN_WAIT_TIME_GET_THERM_LVL 1000
const struct nla_policy
wlan_hdd_thermal_mitigation_policy
@@ -143,6 +147,223 @@ hdd_send_thermal_mitigation_val(struct hdd_context *hdd_ctx, uint32_t level,
return QDF_STATUS_SUCCESS;
}
+#ifdef THERMAL_STATS_SUPPORT
+QDF_STATUS
+hdd_send_get_thermal_stats_cmd(struct hdd_context *hdd_ctx,
+ enum thermal_stats_request_type request_type,
+ void (*callback)(void *context,
+ struct thermal_throttle_info *response),
+ void *context)
+{
+ int ret;
+
+ if (!hdd_ctx->psoc) {
+ hdd_err_rl("NULL pointer for psoc");
+ return QDF_STATUS_E_INVAL;
+ }
+
+
+ /* Send Get Thermal Stats cmd to FW */
+ ret = os_if_fwol_get_thermal_stats_req(hdd_ctx->psoc, request_type,
+ callback, context);
+ if (ret)
+ return QDF_STATUS_E_FAILURE;
+
+ return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_get_thermal_stats_cb() - Get thermal stats callback
+ * @context: Call context
+ * @response: Pointer to response structure
+ *
+ * Return: void
+ */
+static void
+hdd_get_thermal_stats_cb(void *context,
+ struct thermal_throttle_info *response)
+{
+ struct osif_request *request;
+ struct thermal_throttle_info *priv;
+
+ request = osif_request_get(context);
+ if (!request) {
+ osif_err("Obsolete request");
+ return;
+ }
+
+ priv = osif_request_priv(request);
+ qdf_mem_copy(priv, response, sizeof(struct thermal_throttle_info));
+
+ osif_request_complete(request);
+ osif_request_put(request);
+}
+
+#define THERMAL_MIN_TEMP QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE
+#define THERMAL_MAX_TEMP QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE
+#define THERMAL_DWELL_TIME QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME
+#define THERMAL_LVL_COUNT QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER
+
+/**
+ * hdd_get_curr_thermal_stats_val() - Indicate thermal stats
+ * to upper layer when query vendor command
+ * @wiphy: Pointer to wireless phy
+ * @hdd_ctx: hdd context
+ *
+ * Return: 0 for success
+ */
+static int
+hdd_get_curr_thermal_stats_val(struct wiphy *wiphy,
+ struct hdd_context *hdd_ctx)
+{
+ int ret = 0;
+ uint8_t i = 0;
+ struct osif_request *request = NULL;
+ int skb_len = 0;
+ struct thermal_throttle_info *priv;
+ struct thermal_throttle_info *get_tt_stats = NULL;
+ struct sk_buff *skb = NULL;
+ void *cookie;
+ struct nlattr *therm_attr;
+ struct nlattr *tt_levels;
+ static const struct osif_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_GET_THERM_LVL,
+ .dealloc = NULL,
+ };
+
+ if (hdd_ctx->is_therm_stats_in_progress) {
+ hdd_err("request already in progress");
+ return -EINVAL;
+ }
+
+ request = osif_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = osif_request_cookie(request);
+ hdd_ctx->is_therm_stats_in_progress = true;
+ ret = hdd_send_get_thermal_stats_cmd(hdd_ctx, thermal_stats_req,
+ hdd_get_thermal_stats_cb,
+ cookie);
+ if (QDF_IS_STATUS_ERROR(ret)) {
+ hdd_err("Failure while sending command to fw");
+ ret = -EAGAIN;
+ goto completed;
+ }
+
+ ret = osif_request_wait_for_response(request);
+ if (ret) {
+ hdd_err("Timed out while retrieving thermal stats");
+ ret = -EAGAIN;
+ goto completed;
+ }
+
+ get_tt_stats = osif_request_priv(request);
+ if (!get_tt_stats) {
+ hdd_err("invalid get_tt_stats");
+ ret = -EINVAL;
+ goto completed;
+ }
+
+ skb_len = NLMSG_HDRLEN + (get_tt_stats->therm_throt_levels) *
+ (NLA_HDRLEN + (NLA_HDRLEN +
+ sizeof(get_tt_stats->level_info[i].start_temp_level) +
+ NLA_HDRLEN +
+ sizeof(get_tt_stats->level_info[i].end_temp_level) +
+ NLA_HDRLEN +
+ sizeof(get_tt_stats->level_info[i].total_time_ms_lo) +
+ NLA_HDRLEN +
+ sizeof(get_tt_stats->level_info[i].num_entry)));
+
+ skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+ skb_len);
+ if (!skb) {
+ hdd_err_rl("cfg80211_vendor_cmd_alloc_reply_skb failed");
+ ret = -ENOMEM;
+ goto completed;
+ }
+
+ therm_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_THERMAL_STATS);
+ if (!therm_attr) {
+ hdd_err_rl("nla_nest_start failed for attr failed");
+ ret = -EINVAL;
+ goto completed;
+ }
+
+ for (i = 0; i < get_tt_stats->therm_throt_levels; i++) {
+ tt_levels = nla_nest_start(skb, i);
+ if (!tt_levels) {
+ hdd_err_rl("nla_nest_start failed for thermal level %d",
+ i);
+ ret = -EINVAL;
+ goto completed;
+ }
+
+ hdd_debug("level %d, Temp Range: %d - %d, Dwell time %d, Counter %d",
+ i, get_tt_stats->level_info[i].start_temp_level,
+ get_tt_stats->level_info[i].end_temp_level,
+ get_tt_stats->level_info[i].total_time_ms_lo,
+ get_tt_stats->level_info[i].num_entry);
+
+ if (nla_put_u32(skb, THERMAL_MIN_TEMP,
+ get_tt_stats->level_info[i].start_temp_level) ||
+ nla_put_u32(skb, THERMAL_MAX_TEMP,
+ get_tt_stats->level_info[i].end_temp_level) ||
+ nla_put_u32(skb, THERMAL_DWELL_TIME,
+ (get_tt_stats->level_info[i].total_time_ms_lo)) ||
+ nla_put_u32(skb, THERMAL_LVL_COUNT,
+ get_tt_stats->level_info[i].num_entry)) {
+ hdd_err("nla put failure");
+ kfree_skb(skb);
+ ret = -EINVAL;
+ hdd_ctx->is_therm_stats_in_progress = false;
+ break;
+ }
+ nla_nest_end(skb, tt_levels);
+ }
+ nla_nest_end(skb, therm_attr);
+ wlan_cfg80211_vendor_cmd_reply(skb);
+
+completed:
+ hdd_ctx->is_therm_stats_in_progress = false;
+ osif_request_put(request);
+
+ return ret;
+}
+
+#undef THERMAL_MIN_TEMP
+#undef THERMAL_MAX_TEMP
+#undef THERMAL_DWELL_TIME
+#undef THERMAL_LVL_COUNT
+
+static QDF_STATUS
+hdd_send_thermal_stats_clear_cmd(struct hdd_context *hdd_ctx)
+{
+ QDF_STATUS status;
+
+ status = hdd_send_get_thermal_stats_cmd(hdd_ctx,
+ thermal_stats_clear, NULL,
+ NULL);
+
+ return status;
+}
+#else
+static int
+hdd_get_curr_thermal_stats_val(struct wiphy *wiphy,
+ struct hdd_context *hdd_ctx)
+{
+ return -EINVAL;
+}
+
+static QDF_STATUS
+hdd_send_thermal_stats_clear_cmd(struct hdd_context *hdd_ctx)
+{
+ return QDF_STATUS_E_NOSUPPORT;
+}
+#endif /* THERMAL_STATS_SUPPORT */
+
/**
* __wlan_hdd_cfg80211_set_thermal_mitigation_policy() - Set the thermal policy
* @wiphy: Pointer to wireless phy
@@ -162,9 +383,14 @@ __wlan_hdd_cfg80211_set_thermal_mitigation_policy(struct wiphy *wiphy,
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX + 1];
uint32_t level, cmd_type;
QDF_STATUS status;
+ int ret;
hdd_enter();
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (ret)
+ return -EINVAL;
+
if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
hdd_err_rl("Command not allowed in FTM mode");
return -EPERM;
@@ -184,23 +410,35 @@ __wlan_hdd_cfg80211_set_thermal_mitigation_policy(struct wiphy *wiphy,
}
cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE]);
- if (cmd_type != QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL) {
- hdd_err_rl("invalid thermal cmd value");
- return -EINVAL;
+ switch (cmd_type) {
+ case QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL:
+ if (!tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]) {
+ hdd_err_rl("attr thermal throttle set failed");
+ return -EINVAL;
+ }
+ level = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]);
+
+ hdd_debug("thermal mitigation level from userspace %d", level);
+ status = hdd_send_thermal_mitigation_val(hdd_ctx, level,
+ THERMAL_MONITOR_APPS);
+ ret = qdf_status_to_os_return(status);
+ break;
+ case QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS:
+ ret = hdd_get_curr_thermal_stats_val(wiphy, hdd_ctx);
+ break;
+ case QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS:
+ status = hdd_send_thermal_stats_clear_cmd(hdd_ctx);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ hdd_err("Failure while sending command to fw");
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ ret = -EINVAL;
}
- if (!tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]) {
- hdd_err_rl("attr thermal throttle set failed");
- return -EINVAL;
- }
- level =
- nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]);
-
- hdd_debug("thermal mitigation level from userspace %d", level);
- status = hdd_send_thermal_mitigation_val(hdd_ctx, level,
- THERMAL_MONITOR_APPS);
hdd_exit();
- return qdf_status_to_os_return(status);
+ return ret;
}
/**
diff --git a/core/hdd/src/wlan_hdd_thermal.h b/core/hdd/src/wlan_hdd_thermal.h
index 3bfcbd490361..a18abe7f19ae 100644
--- a/core/hdd/src/wlan_hdd_thermal.h
+++ b/core/hdd/src/wlan_hdd_thermal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021 The Linux Foundation. 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
@@ -195,4 +195,13 @@ int wlan_hdd_pld_set_thermal_mitigation(struct device *dev,
}
#endif /* FEATURE_THERMAL_VENDOR_COMMANDS */
+
+#ifdef THERMAL_STATS_SUPPORT
+QDF_STATUS
+hdd_send_get_thermal_stats_cmd(struct hdd_context *hdd_ctx,
+ enum thermal_stats_request_type request_type,
+ void (*callback)(void *context,
+ struct thermal_throttle_info *response),
+ void *context);
+#endif /* THERMAL_STATS_SUPPORT */
#endif /* __HDD_THERMAL_H */
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 4c330b267eaa..16812d9723fb 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -114,6 +114,7 @@
#endif
#include "wlan_pkt_capture_ucfg_api.h"
+#include "wlan_fwol_ucfg_api.h"
#define WMA_LOG_COMPLETION_TIMER 3000 /* 3 seconds */
#define WMI_TLV_HEADROOM 128
@@ -5804,10 +5805,52 @@ static void wma_set_mlme_caps(struct wlan_objmgr_psoc *psoc)
wma_err("Failed to set sae roam support");
}
+#ifdef THERMAL_STATS_SUPPORT
+static void wma_set_thermal_stats_fw_cap(tp_wma_handle wma,
+ struct wlan_fwol_capability_info *cap)
+{
+ cap->fw_thermal_stats_cap = wmi_service_enabled(wma->wmi_handle,
+ wmi_service_thermal_stats_temp_range_supported);
+}
+#else
+static void wma_set_thermal_stats_fw_cap(tp_wma_handle wma,
+ struct wlan_fwol_capability_info *cap)
+{
+}
+#endif
+
+/**
+ * wma_set_fwol_caps() - Populate fwol component related capabilities
+ * to the fwol component
+ *
+ * @psoc: Pointer to psoc object
+ *
+ * Return: None
+ */
+static void wma_set_fwol_caps(struct wlan_objmgr_psoc *psoc)
+{
+ tp_wma_handle wma;
+ struct wlan_fwol_capability_info cap_info;
+ wma = cds_get_context(QDF_MODULE_ID_WMA);
+
+ if (!wma) {
+ wma_err_rl("wma Null");
+ return;
+ }
+ if (!psoc) {
+ wma_err_rl("psoc Null");
+ return;
+ }
+
+ wma_set_thermal_stats_fw_cap(wma, &cap_info);
+ ucfg_fwol_update_fw_cap_info(psoc, &cap_info);
+}
+
static void wma_set_component_caps(struct wlan_objmgr_psoc *psoc)
{
wma_set_pmo_caps(psoc);
wma_set_mlme_caps(psoc);
+ wma_set_fwol_caps(psoc);
}
#if defined(WLAN_FEATURE_GTK_OFFLOAD) && defined(WLAN_POWER_MANAGEMENT_OFFLOAD)
diff --git a/os_if/fw_offload/inc/os_if_fwol.h b/os_if/fw_offload/inc/os_if_fwol.h
index 8ecbc0ff2145..2c938c1a94c1 100644
--- a/os_if/fw_offload/inc/os_if_fwol.h
+++ b/os_if/fw_offload/inc/os_if_fwol.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021 The Linux Foundation. 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
@@ -26,6 +26,7 @@
#define __OS_IF_FWOL_H__
#include "wlan_objmgr_vdev_obj.h"
+#include "wlan_fwol_public_structs.h"
#ifdef WLAN_FEATURE_ELNA
/**
@@ -82,4 +83,12 @@ static inline int os_if_fwol_send_dscp_up_map_to_fw(
}
#endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */
+#ifdef THERMAL_STATS_SUPPORT
+int os_if_fwol_get_thermal_stats_req(struct wlan_objmgr_psoc *psoc,
+ enum thermal_stats_request_type req,
+ void (*callback)(void *context,
+ struct thermal_throttle_info *response),
+ void *context);
+#endif /* THERMAL_STATS_SUPPORT */
+
#endif /* __OS_IF_FWOL_H__ */
diff --git a/os_if/fw_offload/src/os_if_fwol.c b/os_if/fw_offload/src/os_if_fwol.c
index 90ee99744f5e..de2dd43d8f31 100644
--- a/os_if/fw_offload/src/os_if_fwol.c
+++ b/os_if/fw_offload/src/os_if_fwol.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021 The Linux Foundation. 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
@@ -145,3 +145,23 @@ int os_if_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev,
return qdf_status_to_os_return(status);
}
#endif
+
+#ifdef THERMAL_STATS_SUPPORT
+int os_if_fwol_get_thermal_stats_req(struct wlan_objmgr_psoc *psoc,
+ enum thermal_stats_request_type req,
+ void (*callback)(void *context,
+ struct thermal_throttle_info *response),
+ void *context)
+{
+ QDF_STATUS status;
+
+
+ status = ucfg_fwol_send_get_thermal_stats_cmd(psoc, req, callback,
+ context);
+ if (!QDF_IS_STATUS_SUCCESS(status))
+ osif_err("Failed to send get thermal stats cmd to FW, %d",
+ status);
+
+ return qdf_status_to_os_return(status);
+}
+#endif