Merge 5e1b73532e on remote branch

Change-Id: I78233e6358a615f989640c7a00855515bd3788e3
This commit is contained in:
Linux Build Service Account 2021-10-24 02:17:47 -07:00
commit ae3b3e5534
21 changed files with 430 additions and 42 deletions

View file

@ -1837,8 +1837,20 @@ void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc,
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
void dp_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl);
/**
* dp_tx_dump_flow_pool_info_compact() - dump flow pool info
* @soc: DP soc context
*
* Return: none
*/
void dp_tx_dump_flow_pool_info_compact(struct dp_soc *soc);
int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool,
bool force);
#else
static inline void dp_tx_dump_flow_pool_info_compact(struct dp_soc *soc)
{
}
#endif /* QCA_LL_TX_FLOW_CONTROL_V2 */
#ifdef QCA_OL_DP_SRNG_LOCK_LESS_ACCESS

View file

@ -7503,7 +7503,7 @@ QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl,
*
* Return: outstanding tx
*/
static uint32_t dp_get_tx_pending(struct cdp_pdev *pdev_handle)
static int32_t dp_get_tx_pending(struct cdp_pdev *pdev_handle)
{
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
@ -10085,6 +10085,8 @@ static QDF_STATUS dp_txrx_dump_stats(struct cdp_soc_t *psoc, uint16_t value,
case CDP_DUMP_TX_FLOW_POOL_INFO:
if (level == QDF_STATS_VERBOSITY_LEVEL_HIGH)
cdp_dump_flow_pool_info((struct cdp_soc_t *)soc);
else
dp_tx_dump_flow_pool_info_compact(soc);
break;
case CDP_DP_NAPI_STATS:
@ -11559,6 +11561,7 @@ static QDF_STATUS dp_runtime_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
struct dp_pdev *pdev;
uint8_t i;
int32_t tx_pending;
pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
if (!pdev) {
@ -11567,9 +11570,11 @@ static QDF_STATUS dp_runtime_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
}
/* Abort if there are any pending TX packets */
if (dp_get_tx_pending(dp_pdev_to_cdp_pdev(pdev)) > 0) {
tx_pending = dp_get_tx_pending(dp_pdev_to_cdp_pdev(pdev));
if (tx_pending) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
FL("Abort suspend due to pending TX packets"));
FL("Abort suspend due to pending TX packets %d"),
tx_pending);
/* perform a force flush if tx is pending */
for (i = 0; i < soc->num_tcl_data_rings; i++) {
@ -12042,6 +12047,7 @@ static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
int timeout = SUSPEND_DRAIN_WAIT;
int drain_wait_delay = 50; /* 50 ms */
int32_t tx_pending;
if (qdf_unlikely(!pdev)) {
dp_err("pdev is NULL");
@ -12049,10 +12055,11 @@ static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
}
/* Abort if there are any pending TX packets */
while (dp_get_tx_pending((struct cdp_pdev *)pdev) > 0) {
while ((tx_pending = dp_get_tx_pending((struct cdp_pdev *)pdev))) {
qdf_sleep(drain_wait_delay);
if (timeout <= 0) {
dp_err("TX frames are pending, abort suspend");
dp_info("TX frames are pending %d, abort suspend",
tx_pending);
return QDF_STATUS_E_TIMEOUT;
}
timeout = timeout - drain_wait_delay;

View file

@ -1199,29 +1199,67 @@ static void dp_rx_fill_gro_info(struct dp_soc *soc, uint8_t *rx_tlv,
*
* @nbuf: pointer to msdu.
* @mpdu_len: mpdu length
* @l3_pad_len: L3 padding length by HW
*
* Return: returns true if nbuf is last msdu of mpdu else retuns false.
*/
static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, uint16_t *mpdu_len)
static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf,
uint16_t *mpdu_len,
uint32_t l3_pad_len)
{
bool last_nbuf;
uint32_t pkt_hdr_size;
if (*mpdu_len > (RX_DATA_BUFFER_SIZE - RX_PKT_TLVS_LEN)) {
pkt_hdr_size = RX_PKT_TLVS_LEN + l3_pad_len;
if ((*mpdu_len + pkt_hdr_size) > RX_DATA_BUFFER_SIZE) {
qdf_nbuf_set_pktlen(nbuf, RX_DATA_BUFFER_SIZE);
last_nbuf = false;
*mpdu_len -= (RX_DATA_BUFFER_SIZE - pkt_hdr_size);
} else {
qdf_nbuf_set_pktlen(nbuf, (*mpdu_len + RX_PKT_TLVS_LEN));
qdf_nbuf_set_pktlen(nbuf, (*mpdu_len + pkt_hdr_size));
last_nbuf = true;
*mpdu_len = 0;
}
*mpdu_len -= (RX_DATA_BUFFER_SIZE - RX_PKT_TLVS_LEN);
return last_nbuf;
}
/**
* dp_get_l3_hdr_pad_len() - get L3 header padding length.
*
* @soc: DP soc handle
* @nbuf: pointer to msdu.
*
* Return: returns padding length in bytes.
*/
static inline uint32_t dp_get_l3_hdr_pad_len(struct dp_soc *soc,
qdf_nbuf_t nbuf)
{
uint32_t l3_hdr_pad = 0;
uint8_t *rx_tlv_hdr;
struct hal_rx_msdu_metadata msdu_metadata;
while (nbuf) {
if (!qdf_nbuf_is_rx_chfrag_cont(nbuf)) {
/* scattered msdu end with continuation is 0 */
rx_tlv_hdr = qdf_nbuf_data(nbuf);
hal_rx_msdu_metadata_get(soc->hal_soc,
rx_tlv_hdr,
&msdu_metadata);
l3_hdr_pad = msdu_metadata.l3_hdr_pad;
break;
}
nbuf = nbuf->next;
}
return l3_hdr_pad;
}
/**
* dp_rx_sg_create() - create a frag_list for MSDUs which are spread across
* multiple nbufs.
* @soc: DP SOC handle
* @nbuf: pointer to the first msdu of an amsdu.
*
* This function implements the creation of RX frag_list for cases
@ -1229,12 +1267,13 @@ static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, uint16_t *mpdu_len)
*
* Return: returns the head nbuf which contains complete frag_list.
*/
qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf)
qdf_nbuf_t dp_rx_sg_create(struct dp_soc *soc, qdf_nbuf_t nbuf)
{
qdf_nbuf_t parent, frag_list, next = NULL;
uint16_t frag_list_len = 0;
uint16_t mpdu_len;
bool last_nbuf;
uint32_t l3_hdr_pad_offset = 0;
/*
* Use msdu len got from REO entry descriptor instead since
@ -1242,6 +1281,7 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf)
* from REO descriptor is right for non-raw RX scatter msdu.
*/
mpdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf);
/*
* this is a case where the complete msdu fits in one single nbuf.
* in this case HW sets both start and end bit and we only need to
@ -1254,6 +1294,8 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf)
return nbuf;
}
l3_hdr_pad_offset = dp_get_l3_hdr_pad_len(soc, nbuf);
/*
* This is a case where we have multiple msdus (A-MSDU) spread across
* multiple nbufs. here we create a fraglist out of these nbufs.
@ -1273,7 +1315,24 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf)
* nbufs will form the frag_list of the parent nbuf.
*/
qdf_nbuf_set_rx_chfrag_start(parent, 1);
last_nbuf = dp_rx_adjust_nbuf_len(parent, &mpdu_len);
/*
* L3 header padding is only needed for the 1st buffer
* in a scattered msdu
*/
last_nbuf = dp_rx_adjust_nbuf_len(parent, &mpdu_len,
l3_hdr_pad_offset);
/*
* HW issue: MSDU cont bit is set but reported MPDU length can fit
* in to single buffer
*
* Increment error stats and avoid SG list creation
*/
if (last_nbuf) {
qdf_nbuf_pull_head(parent,
RX_PKT_TLVS_LEN + l3_hdr_pad_offset);
return parent;
}
/*
* this is where we set the length of the fragments which are
@ -1281,7 +1340,7 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf)
* till we hit the last_nbuf of the list.
*/
do {
last_nbuf = dp_rx_adjust_nbuf_len(nbuf, &mpdu_len);
last_nbuf = dp_rx_adjust_nbuf_len(nbuf, &mpdu_len, 0);
qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN);
frag_list_len += qdf_nbuf_len(nbuf);
@ -1298,7 +1357,8 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf)
qdf_nbuf_append_ext_list(parent, frag_list, frag_list_len);
parent->next = next;
qdf_nbuf_pull_head(parent, RX_PKT_TLVS_LEN);
qdf_nbuf_pull_head(parent,
RX_PKT_TLVS_LEN + l3_hdr_pad_offset);
return parent;
}
@ -2833,7 +2893,7 @@ done:
qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN);
} else if (qdf_nbuf_is_rx_chfrag_cont(nbuf)) {
msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf);
nbuf = dp_rx_sg_create(nbuf);
nbuf = dp_rx_sg_create(soc, nbuf);
next = nbuf->next;
if (qdf_nbuf_is_raw_frame(nbuf)) {

View file

@ -676,6 +676,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
/**
* dp_rx_sg_create() - create a frag_list for MSDUs which are spread across
* multiple nbufs.
* @soc: core txrx main context
* @nbuf: pointer to the first msdu of an amsdu.
*
* This function implements the creation of RX frag_list for cases
@ -683,7 +684,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
*
* Return: returns the head nbuf which contains complete frag_list.
*/
qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf);
qdf_nbuf_t dp_rx_sg_create(struct dp_soc *soc, qdf_nbuf_t nbuf);
/*

View file

@ -606,7 +606,7 @@ more_msdu_link_desc:
rx_tlv_hdr_last = qdf_nbuf_data(tail_nbuf);
if (qdf_unlikely(head_nbuf != tail_nbuf)) {
nbuf = dp_rx_sg_create(head_nbuf);
nbuf = dp_rx_sg_create(soc, head_nbuf);
qdf_nbuf_set_is_frag(nbuf, 1);
DP_STATS_INC(soc, rx.err.reo_err_oor_sg_count, 1);
}
@ -2375,7 +2375,7 @@ done:
* QCN9000 has this support
*/
if (qdf_nbuf_is_rx_chfrag_cont(nbuf)) {
nbuf = dp_rx_sg_create(nbuf);
nbuf = dp_rx_sg_create(soc, nbuf);
next = nbuf->next;
/*
* SG error handling is not done correctly,

View file

@ -5956,6 +5956,8 @@ void dp_txrx_path_stats(struct dp_soc *soc)
pdev->stats.tx.dropped.fw_rem_notx);
DP_PRINT_STATS("Invalid peer on tx path: %u",
pdev->soc->stats.tx.tx_invalid_peer.num);
DP_PRINT_STATS("Tx desc freed in non-completion path: %u",
pdev->soc->stats.tx.tx_comp_exception);
DP_PRINT_STATS("Tx packets sent per interrupt:");
DP_PRINT_STATS("Single Packet: %u",

View file

@ -4900,6 +4900,7 @@ more_data:
!tx_desc->flags)) {
dp_info_rl("Descriptor freed in vdev_detach %d",
tx_desc_id);
DP_STATS_INC(soc, tx.tx_comp_exception, 1);
continue;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2015-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
@ -29,6 +29,8 @@
#include "dp_internal.h"
#define INVALID_FLOW_ID 0xFF
#define MAX_INVALID_BIN 3
#define GLOBAL_FLOW_POOL_STATS_LEN 25
#define FLOW_POOL_LOG_LEN 50
#ifdef QCA_AC_BASED_FLOW_CONTROL
/**
@ -222,6 +224,46 @@ void dp_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl)
qdf_spin_unlock_bh(&soc->flow_pool_array_lock);
}
void dp_tx_dump_flow_pool_info_compact(struct dp_soc *soc)
{
struct dp_txrx_pool_stats *pool_stats = &soc->pool_stats;
struct dp_tx_desc_pool_s *pool = NULL;
char *comb_log_str;
uint32_t comb_log_str_size;
int bytes_written = 0;
int i;
comb_log_str_size = GLOBAL_FLOW_POOL_STATS_LEN +
(FLOW_POOL_LOG_LEN * MAX_TXDESC_POOLS) + 1;
comb_log_str = qdf_mem_malloc(comb_log_str_size);
if (!comb_log_str)
return;
bytes_written = qdf_snprintf(&comb_log_str[bytes_written],
comb_log_str_size, "G:(%d,%d,%d) ",
pool_stats->pool_map_count,
pool_stats->pool_unmap_count,
pool_stats->pkt_drop_no_pool);
for (i = 0; i < MAX_TXDESC_POOLS; i++) {
pool = &soc->tx_desc[i];
if (pool->status > FLOW_POOL_INVALID)
continue;
bytes_written += qdf_snprintf(&comb_log_str[bytes_written],
(bytes_written >= comb_log_str_size) ? 0 :
comb_log_str_size - bytes_written,
"| %d %d: (%d,%d,%d)",
pool->flow_pool_id, pool->status,
pool->pool_size, pool->avail_desc,
pool->pkt_drop_no_desc);
}
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
"FLOW_POOL_STATS %s", comb_log_str);
qdf_mem_free(comb_log_str);
}
/**
* dp_tx_clear_flow_pool_stats() - clear flow pool statistics
*

View file

@ -911,6 +911,8 @@ struct dp_soc_stats {
uint32_t tx_comp_loop_pkt_limit_hit;
/* Head pointer Out of sync at the end of dp_tx_comp_handler */
uint32_t hp_oos2;
/* tx desc freed as part of vdev detach */
uint32_t tx_comp_exception;
} tx;
/* SOC level RX stats */

View file

@ -1067,8 +1067,8 @@ enum qdf_dp_tx_rx_status qdf_dp_get_status_from_a_status(uint8_t status)
void qdf_trace_display(void);
void __printf(3, 4) qdf_snprintf(char *str_buffer, unsigned int size,
char *str_format, ...);
int __printf(3, 4) qdf_snprintf(char *str_buffer, unsigned int size,
char *str_format, ...);
#define QDF_SNPRINTF qdf_snprintf

View file

@ -110,11 +110,18 @@ static tp_qdf_dp_trace_cb qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX + 1];
* string contains printf-like replacement parameters, which follow
* this parameter in the variable argument list.
*
* Return: None
* Return: num of bytes written to buffer
*/
void qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...)
int qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...)
{
snprintf(str_buffer, size, str_format);
va_list args;
int i;
va_start(args, str_format);
i = vsnprintf(str_buffer, size, str_format, args);
va_end(args);
return i;
}
qdf_export_symbol(qdf_snprintf);

View file

@ -97,11 +97,10 @@ static bool vdev_mgr_is_opmode_sap_or_p2p_go(enum QDF_OPMODE op_mode)
return (op_mode == QDF_SAP_MODE || op_mode == QDF_P2P_GO_MODE);
}
static bool vdev_mgr_is_49G_5G_6G_chan_freq(uint16_t chan_freq)
static bool vdev_mgr_is_49G_5G_chan_freq(uint16_t chan_freq)
{
return WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) ||
WLAN_REG_IS_49GHZ_FREQ(chan_freq) ||
WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq);
WLAN_REG_IS_49GHZ_FREQ(chan_freq);
}
#else
static inline bool vdev_mgr_is_opmode_sap_or_p2p_go(enum QDF_OPMODE op_mode)
@ -109,7 +108,7 @@ static inline bool vdev_mgr_is_opmode_sap_or_p2p_go(enum QDF_OPMODE op_mode)
return true;
}
static inline bool vdev_mgr_is_49G_5G_6G_chan_freq(uint16_t chan_freq)
static inline bool vdev_mgr_is_49G_5G_chan_freq(uint16_t chan_freq)
{
return true;
}
@ -151,7 +150,7 @@ static QDF_STATUS vdev_mgr_start_param_update(
op_mode = wlan_vdev_mlme_get_opmode(vdev);
if (vdev_mgr_is_opmode_sap_or_p2p_go(op_mode) &&
vdev_mgr_is_49G_5G_6G_chan_freq(des_chan->ch_freq)) {
vdev_mgr_is_49G_5G_chan_freq(des_chan->ch_freq)) {
tgt_dfs_set_current_channel_for_freq(pdev, des_chan->ch_freq,
des_chan->ch_flags,
des_chan->ch_flagext,

View file

@ -0,0 +1,60 @@
/* 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: declare the thermal public structure
*/
#ifndef _WLAN_THERMAL_PUBLIC_STRUCT_H_
#define _WLAN_THERMAL_PUBLIC_STRUCT_H_
/**
* enum thermal_throttle_level - firmware offload throttle level
* @THERMAL_FULLPERF: no any throtting
* @THERMAL_MITIGATION: throtting tx to do mitigation
* @THERMAL_SHUTOFF: shut down the tx completely
* @THERMAL_UNKNOWN: unknown level from target.
*/
enum thermal_throttle_level {
THERMAL_FULLPERF,
THERMAL_MITIGATION,
THERMAL_SHUTOFF,
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_ */

View file

@ -32,6 +32,7 @@
#include "wlan_mgmt_txrx_utils_api.h"
#include <wlan_dfs_public_struct.h>
#include <wlan_crypto_global_def.h>
#include "wlan_thermal_public_struct.h"
#ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
#include "wmi_unified_pmo_api.h"
#endif
@ -2965,13 +2966,19 @@ wmi_extract_chan_stats(wmi_unified_t wmi_handle, void *evt_buf,
* @wmi_handle: wmi handle
* @evt_buf: Pointer to event buffer
* @temp: Pointer to hold extracted temperature
* @level: Pointer to hold extracted level
* @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
*/
QDF_STATUS wmi_extract_thermal_stats(wmi_unified_t wmi_handle, void *evt_buf,
uint32_t *temp, uint32_t *level,
uint32_t *temp,
enum thermal_throttle_level *level,
uint32_t *therm_throt_levels,
struct thermal_throt_level_stats *tt_stats,
uint32_t *pdev_id);
/**

View file

@ -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
@ -87,4 +87,20 @@ wmi_unified_send_dscp_tip_map_cmd(struct wmi_unified *wmi_handle,
}
#endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */
/**
* 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_ */

View file

@ -5257,6 +5257,9 @@ typedef enum {
#ifdef FEATURE_WLAN_TDLS
wmi_service_tdls_ax_support,
#endif
#endif
#ifdef THERMAL_STATS_SUPPORT
wmi_service_thermal_stats_temp_range_supported,
#endif
wmi_services_max,
} wmi_conv_service_ids;

View file

@ -1796,7 +1796,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, uint32_t *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,
@ -2416,6 +2419,12 @@ QDF_STATUS (*send_dscp_tid_map_cmd)(wmi_unified_t wmi_handle,
uint32_t *dscp_to_tid_map);
#endif
#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,

View file

@ -2225,12 +2225,16 @@ 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, uint32_t *level,
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;
}

View file

@ -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
@ -71,3 +71,18 @@ wmi_unified_send_dscp_tip_map_cmd(struct wmi_unified *wmi_handle,
return QDF_STATUS_E_FAILURE;
}
#endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */
#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 */

View file

@ -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
@ -207,11 +207,65 @@ static void wmi_fwol_attach_dscp_tid_tlv(struct wmi_ops *ops)
}
#endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */
#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 /* THERMAL_STATS_SUPPORT */
void wmi_fwol_attach_tlv(wmi_unified_t wmi_handle)
{
struct wmi_ops *ops = wmi_handle->ops;
wmi_fwol_attach_elna_tlv(ops);
wmi_fwol_attach_dscp_tid_tlv(ops);
wmi_fwol_attach_thermal_stats_tlv(ops);
}

View file

@ -11457,19 +11457,97 @@ static QDF_STATUS extract_scan_radio_cap_service_ready_ext2_tlv(
return QDF_STATUS_SUCCESS;
}
/**
* wmi_tgt_thermal_level_to_host() - Convert target thermal level to host enum
* @level: target thermal level from WMI_THERM_THROT_STATS_EVENTID event
*
* Return: host thermal throt level
*/
static enum thermal_throttle_level
wmi_tgt_thermal_level_to_host(uint32_t level)
{
switch (level) {
case WMI_THERMAL_FULLPERF:
return THERMAL_FULLPERF;
case WMI_THERMAL_MITIGATION:
return THERMAL_MITIGATION;
case WMI_THERMAL_SHUTOFF:
return THERMAL_SHUTOFF;
default:
return THERMAL_UNKNOWN;
}
}
#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
* @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,
uint32_t *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;
@ -11480,12 +11558,17 @@ extract_thermal_stats_tlv(wmi_unified_t wmi_handle,
return QDF_STATUS_E_INVAL;
tt_stats_event = param_buf->fixed_param;
wmi_debug("thermal temperature %d level %d",
tt_stats_event->temp, tt_stats_event->level);
*pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
wmi_handle,
tt_stats_event->pdev_id);
*temp = tt_stats_event->temp;
*level = tt_stats_event->level;
*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;
}
@ -15762,6 +15845,10 @@ static void populate_tlv_service(uint32_t *wmi_service)
#endif
wmi_service[wmi_service_ampdu_tx_buf_size_256_support] =
WMI_SERVICE_AMPDU_TX_BUF_SIZE_256_SUPPORT;
#ifdef THERMAL_STATS_SUPPORT
wmi_service[wmi_service_thermal_stats_temp_range_supported] =
WMI_SERVICE_THERMAL_THROT_STATS_TEMP_RANGE_SUPPORT;
#endif
}
/**