diff --git a/umac/thermal/dispatcher/inc/wlan_thermal_public_struct.h b/umac/thermal/dispatcher/inc/wlan_thermal_public_struct.h index 1a1899d057..f0a5a7e9b6 100644 --- a/umac/thermal/dispatcher/inc/wlan_thermal_public_struct.h +++ b/umac/thermal/dispatcher/inc/wlan_thermal_public_struct.h @@ -1,4 +1,4 @@ -/* 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 above @@ -35,4 +35,28 @@ enum thermal_throttle_level { THERMAL_UNKNOWN, }; +enum thermal_stats_request_type { + thermal_stats_none = 0, + thermal_stats_init, + thermal_stats_req, + thermal_stats_clear, + thermal_stats_current_all_sensors_temp, +}; + +/** + * thermal_throt_level_stats - thermal throttle info from Target + * @start_temp_level: Start temperature range to capture thermal stats + * @end_temp_level: End temperature range to capture thermal stats + * @total_time_ms_lo: Start time for every thermal stats level in msec + * @total_time_ms_hi: End time for every thermal stats level in msec + * @num_entry: Thermal stats counter for every time temp level for this range + */ +struct thermal_throt_level_stats { + uint32_t start_temp_level; + uint32_t end_temp_level; + uint32_t total_time_ms_lo; + uint32_t total_time_ms_hi; + uint32_t num_entry; +}; + #endif /* _WLAN_THERMAL_PUBLIC_STRUCT_H_ */ diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 349983373d..9616103d87 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -3017,6 +3017,9 @@ wmi_extract_chan_stats(wmi_unified_t wmi_handle, void *evt_buf, * @evt_buf: Pointer to event buffer * @temp: Pointer to hold extracted temperature * @level: Pointer to hold extracted level in host enum + * @therm_throt_levels: Pointer to hold extracted number of level in thermal + * stats + * @tt_lvl_stats_event: Pointer to hold extracted thermal stats for each level * @pdev_id: Pointer to hold extracted pdev_id * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure @@ -3024,6 +3027,8 @@ wmi_extract_chan_stats(wmi_unified_t wmi_handle, void *evt_buf, QDF_STATUS wmi_extract_thermal_stats(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *temp, enum thermal_throttle_level *level, + uint32_t *therm_throt_levels, + struct thermal_throt_level_stats *tt_stats, uint32_t *pdev_id); /** diff --git a/wmi/inc/wmi_unified_fwol_api.h b/wmi/inc/wmi_unified_fwol_api.h index d88264cec6..c851b37f4d 100644 --- a/wmi/inc/wmi_unified_fwol_api.h +++ b/wmi/inc/wmi_unified_fwol_api.h @@ -102,4 +102,21 @@ wmi_unified_send_set_mdns_config_cmd(struct wmi_unified *wmi_handle, struct mdns_config_info *mdns_info); #endif /* WLAN_FEATURE_MDNS_OFFLOAD */ +/** + * wmi_unified_send_get_thermal_stats_cmd() - Send WMI get thermal stats req + * @wmi_handle: wmi handle + * @req_type: Request type + * @temp_offset: temperature offset for setting the range for thermal stats + + * Send WMI get thermal stats req command to firmware. + * + * Return: QDF_STATUS + */ +#ifdef THERMAL_STATS_SUPPORT +QDF_STATUS +wmi_unified_send_get_thermal_stats_cmd(struct wmi_unified *wmi_handle, + enum thermal_stats_request_type req_type, + uint8_t temp_offset); +#endif /* THERMAL_STATS_SUPPORT */ + #endif /* _WMI_UNIFIED_FWOL_API_H_ */ diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 78947ceb6f..e700621630 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -5287,6 +5287,9 @@ typedef enum { wmi_service_aoa_for_rcc_supported, #ifdef WLAN_FEATURE_P2P_P2P_STA wmi_service_p2p_p2p_cc_support, +#endif +#ifdef THERMAL_STATS_SUPPORT + wmi_service_thermal_stats_temp_range_supported, #endif wmi_services_max, } wmi_conv_service_ids; diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index b611f4c528..28dbacfe46 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1897,7 +1897,10 @@ QDF_STATUS (*extract_mib_stats)(wmi_unified_t wmi_handle, void *evt_buf, #endif QDF_STATUS (*extract_thermal_stats)(wmi_unified_t wmi_handle, void *evt_buf, - uint32_t *temp, enum thermal_throttle_level *level, uint32_t *pdev_id); + uint32_t *temp, enum thermal_throttle_level *level, + uint32_t *therm_throt_levels, + struct thermal_throt_level_stats *tt_temp_range_stats_event, + uint32_t *pdev_id); QDF_STATUS (*extract_thermal_level_stats)(wmi_unified_t wmi_handle, void *evt_buf, uint8_t idx, uint32_t *levelcount, @@ -2504,6 +2507,12 @@ QDF_STATUS (*send_set_mdns_config_cmd)(wmi_unified_t wmi_handle, struct mdns_config_info *mdns_info); #endif /* WLAN_FEATURE_MDNS_OFFLOAD */ +#ifdef THERMAL_STATS_SUPPORT +QDF_STATUS (*send_get_thermal_stats_cmd)(wmi_unified_t wmi_handle, + enum thermal_stats_request_type req, + uint8_t temp_offset); +#endif /* THERMAL_STATS_SUPPORT */ + QDF_STATUS (*send_pdev_get_pn_cmd)(wmi_unified_t wmi_handle, struct peer_request_pn_param *pn_params); QDF_STATUS (*extract_get_pn_data)(wmi_unified_t wmi_handle, diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 1a99c3037b..32a39f20b4 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -2282,11 +2282,14 @@ wmi_extract_chan_stats(wmi_unified_t wmi_handle, void *evt_buf, QDF_STATUS wmi_extract_thermal_stats(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *temp, enum thermal_throttle_level *level, + uint32_t *therm_throt_levels, + struct thermal_throt_level_stats *tt_stats, uint32_t *pdev_id) { if (wmi_handle->ops->extract_thermal_stats) return wmi_handle->ops->extract_thermal_stats(wmi_handle, - evt_buf, temp, level, pdev_id); + evt_buf, temp, level, therm_throt_levels, + tt_stats, pdev_id); return QDF_STATUS_E_FAILURE; } diff --git a/wmi/src/wmi_unified_fwol_api.c b/wmi/src/wmi_unified_fwol_api.c index e50941d38c..a2b82578eb 100644 --- a/wmi/src/wmi_unified_fwol_api.c +++ b/wmi/src/wmi_unified_fwol_api.c @@ -84,3 +84,18 @@ wmi_unified_send_set_mdns_config_cmd(struct wmi_unified *wmi_handle, return QDF_STATUS_E_FAILURE; } #endif /* WLAN_FEATURE_MDNS_OFFLOAD */ + +#ifdef THERMAL_STATS_SUPPORT +QDF_STATUS +wmi_unified_send_get_thermal_stats_cmd(struct wmi_unified *wmi_handle, + enum thermal_stats_request_type req_type, + uint8_t temp_offset) +{ + if (wmi_handle->ops->send_get_thermal_stats_cmd) + return wmi_handle->ops->send_get_thermal_stats_cmd(wmi_handle, + req_type, + temp_offset); + + return QDF_STATUS_E_FAILURE; +} +#endif /* THERMAL_STATS_SUPPORT */ \ No newline at end of file diff --git a/wmi/src/wmi_unified_fwol_tlv.c b/wmi/src/wmi_unified_fwol_tlv.c index 08735f97df..bb2e9d37c3 100644 --- a/wmi/src/wmi_unified_fwol_tlv.c +++ b/wmi/src/wmi_unified_fwol_tlv.c @@ -427,6 +427,60 @@ static void wmi_fwol_attach_mdns_tlv(struct wmi_ops *ops) } #endif /* WLAN_FEATURE_MDNS_OFFLOAD */ +#ifdef THERMAL_STATS_SUPPORT +/** + * send_get_thermal_stats_cmd_tlv() - send get thermal stats cmd to fw + * @wmi_handle: wmi handle + * @req_type: req type + * @temp_offset: temperature offset + * + * Send WMI_REQUEST_THERMAL_STATS_CMDID to fw. + * + * Return: QDF_STATUS + */ +static QDF_STATUS +send_get_thermal_stats_cmd_tlv(wmi_unified_t wmi_handle, + enum thermal_stats_request_type req_type, + uint8_t temp_offset) +{ + wmi_buf_t buf; + wmi_thermal_stats_cmd_fixed_param *cmd; + uint16_t len = sizeof(*cmd); + QDF_STATUS ret; + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + wmi_err("Failed to allocate wmi buffer"); + return QDF_STATUS_E_NOMEM; + } + + cmd = (wmi_thermal_stats_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_thermal_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_thermal_stats_cmd_fixed_param)); + cmd->thermal_action = req_type; + cmd->thermal_offset = temp_offset; + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_REQUEST_THERMAL_STATS_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) { + wmi_err("Failed to send get thermal stats cmd = %d", ret); + wmi_buf_free(buf); + } + + return ret; +} + +static void wmi_fwol_attach_thermal_stats_tlv(struct wmi_ops *ops) +{ + ops->send_get_thermal_stats_cmd = send_get_thermal_stats_cmd_tlv; +} +#else +static void wmi_fwol_attach_thermal_stats_tlv(struct wmi_ops *ops) +{ +} +#endif /* FW_THERMAL_THROTTLE_SUPPORT */ + void wmi_fwol_attach_tlv(wmi_unified_t wmi_handle) { struct wmi_ops *ops = wmi_handle->ops; @@ -434,5 +488,5 @@ void wmi_fwol_attach_tlv(wmi_unified_t wmi_handle) wmi_fwol_attach_elna_tlv(ops); wmi_fwol_attach_dscp_tid_tlv(ops); wmi_fwol_attach_mdns_tlv(ops); - + wmi_fwol_attach_thermal_stats_tlv(ops); } diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index a687300f06..4143030c77 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -12078,19 +12078,76 @@ wmi_tgt_thermal_level_to_host(uint32_t level) } } +#ifdef THERMAL_STATS_SUPPORT +static void +populate_thermal_stats(WMI_THERM_THROT_STATS_EVENTID_param_tlvs *param_buf, + uint32_t *therm_throt_levels, + struct thermal_throt_level_stats *tt_temp_range_stats) +{ + uint8_t lvl_idx; + wmi_therm_throt_stats_event_fixed_param *tt_stats_event; + wmi_thermal_throt_temp_range_stats *wmi_tt_stats; + + tt_stats_event = param_buf->fixed_param; + *therm_throt_levels = (tt_stats_event->therm_throt_levels > + WMI_THERMAL_STATS_TEMP_THRESH_LEVEL_MAX) ? + WMI_THERMAL_STATS_TEMP_THRESH_LEVEL_MAX : + tt_stats_event->therm_throt_levels; + + wmi_tt_stats = param_buf->temp_range_stats; + if (!wmi_tt_stats) { + wmi_err("wmi_tt_stats Null"); + return; + } + + for (lvl_idx = 0; lvl_idx < *therm_throt_levels; lvl_idx++) { + tt_temp_range_stats[lvl_idx].start_temp_level = + wmi_tt_stats[lvl_idx].start_temp_level; + tt_temp_range_stats[lvl_idx].end_temp_level = + wmi_tt_stats[lvl_idx].end_temp_level; + tt_temp_range_stats[lvl_idx].total_time_ms_lo = + wmi_tt_stats[lvl_idx].total_time_ms_lo; + tt_temp_range_stats[lvl_idx].total_time_ms_hi = + wmi_tt_stats[lvl_idx].total_time_ms_hi; + tt_temp_range_stats[lvl_idx].num_entry = + wmi_tt_stats[lvl_idx].num_entry; + wmi_debug("level %d, start temp %d, end temp %d, total time low %d, total time high %d, counter %d", + lvl_idx, wmi_tt_stats[lvl_idx].start_temp_level, + wmi_tt_stats[lvl_idx].end_temp_level, + wmi_tt_stats[lvl_idx].total_time_ms_lo, + wmi_tt_stats[lvl_idx].total_time_ms_hi, + wmi_tt_stats[lvl_idx].num_entry); + } +} +#else +static void +populate_thermal_stats(WMI_THERM_THROT_STATS_EVENTID_param_tlvs *param_buf, + uint32_t *therm_throt_levels, + struct thermal_throt_level_stats *tt_temp_range_stats) +{ +} +#endif + /** * extract_thermal_stats_tlv() - extract thermal stats from event * @wmi_handle: wmi handle * @param evt_buf: Pointer to event buffer * @param temp: Pointer to hold extracted temperature * @param level: Pointer to hold extracted level in host enum + * @param therm_throt_levels: Pointer to hold extracted thermal throttle temp + * range + * @param tt_temp_range_stats_event: Pointer to hold extracted thermal stats for + * every level * * Return: 0 for success or error code */ static QDF_STATUS extract_thermal_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *temp, - enum thermal_throttle_level *level, uint32_t *pdev_id) + enum thermal_throttle_level *level, + uint32_t *therm_throt_levels, + struct thermal_throt_level_stats *tt_temp_range_stats_event, + uint32_t *pdev_id) { WMI_THERM_THROT_STATS_EVENTID_param_tlvs *param_buf; wmi_therm_throt_stats_event_fixed_param *tt_stats_event; @@ -12109,6 +12166,10 @@ extract_thermal_stats_tlv(wmi_unified_t wmi_handle, *temp = tt_stats_event->temp; *level = wmi_tgt_thermal_level_to_host(tt_stats_event->level); + if (tt_stats_event->therm_throt_levels) + populate_thermal_stats(param_buf, therm_throt_levels, + tt_temp_range_stats_event); + return QDF_STATUS_SUCCESS; } @@ -17123,6 +17184,10 @@ static void populate_tlv_service(uint32_t *wmi_service) wmi_service[wmi_service_p2p_p2p_cc_support] = WMI_SERVICE_P2P_P2P_CONCURRENCY_SUPPORT; #endif +#ifdef THERMAL_STATS_SUPPORT + wmi_service[wmi_service_thermal_stats_temp_range_supported] = + WMI_SERVICE_THERMAL_THROT_STATS_TEMP_RANGE_SUPPORT; +#endif } /**