tegra: hwpm: add checks for PMA quiesce state

- Zeroing of PMA trigger registers is unnecessary. Remove corresponding
logic from HWPM teardown function.
- During device open, add a check for PMA/RTR status. This will ensure
that PMA/RTR are ready to start new profiling session. Device open will
fail if RTR and PMA enginestatus is not ready(idle).
- SOC HWPM driver disables and releases all reserved IPs before teardown
steps. Update teardown logic to zero out IP allowlist registers during
teardown.

Jira THWPM-41
Bug 3714516

Change-Id: Iede5a5ed9860e2a73c8e4a04aeedfc061458c793
Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2776229
Reviewed-by: Seema Khowala <seemaj@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-hwpm/+/2797444
This commit is contained in:
Vedashree Vidwans
2022-10-05 11:24:33 -07:00
committed by mobile promotions
parent 7c1ae11f78
commit 913f1b0697
10 changed files with 147 additions and 38 deletions

View File

@@ -57,7 +57,7 @@ fail:
return err;
}
int tegra_hwpm_element_release(struct tegra_soc_hwpm *hwpm,
int tegra_hwpm_element_disable(struct tegra_soc_hwpm *hwpm,
struct hwpm_ip_aperture *element)
{
int err = 0;
@@ -73,13 +73,6 @@ int tegra_hwpm_element_release(struct tegra_soc_hwpm *hwpm,
element->element_index_mask);
goto fail;
}
err = tegra_hwpm_perfmon_release(hwpm, element);
if (err != 0) {
tegra_hwpm_err(hwpm, "Element mask 0x%x release failed",
element->element_index_mask);
goto fail;
}
break;
case IP_ELEMENT_PERFMUX:
case IP_ELEMENT_BROADCAST:
@@ -89,7 +82,37 @@ int tegra_hwpm_element_release(struct tegra_soc_hwpm *hwpm,
element->element_index_mask);
goto fail;
}
break;
case HWPM_ELEMENT_INVALID:
default:
tegra_hwpm_err(hwpm, "Invalid element type %d",
element->element_type);
return -EINVAL;
}
fail:
return err;
}
int tegra_hwpm_element_release(struct tegra_soc_hwpm *hwpm,
struct hwpm_ip_aperture *element)
{
int err = 0;
tegra_hwpm_fn(hwpm, " ");
switch (element->element_type) {
case HWPM_ELEMENT_PERFMON:
case HWPM_ELEMENT_PERFMUX:
err = tegra_hwpm_perfmon_release(hwpm, element);
if (err != 0) {
tegra_hwpm_err(hwpm, "Element mask 0x%x release failed",
element->element_index_mask);
goto fail;
}
break;
case IP_ELEMENT_PERFMUX:
case IP_ELEMENT_BROADCAST:
err = tegra_hwpm_perfmux_release(hwpm, element);
if (err != 0) {
tegra_hwpm_err(hwpm, "Element mask 0x%x release failed",
@@ -364,6 +387,34 @@ static int tegra_hwpm_func_single_element(struct tegra_soc_hwpm *hwpm,
}
}
break;
case TEGRA_HWPM_UNBIND_RESOURCES:
if ((element->element_index_mask &
ip_inst->element_fs_mask) == 0U) {
tegra_hwpm_dbg(hwpm, hwpm_dbg_bind,
"IP %d inst %d a_type %d element type %d"
" start_addr 0x%llx not reserved",
ip_idx, static_inst_idx, a_type,
element->element_type, element->start_abs_pa);
return 0;
}
err = tegra_hwpm_element_disable(hwpm, element);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d element"
" type %d idx %d enable failed",
ip_idx, a_type, static_aperture_idx);
goto fail;
}
err = hwpm->active_chip->zero_alist_regs(
hwpm, ip_inst, element);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d element"
" type %d idx %d zero regs failed",
ip_idx, a_type, static_aperture_idx);
goto fail;
}
break;
case TEGRA_HWPM_RELEASE_IP_STRUCTURES:
if ((element->element_index_mask &
ip_inst->element_fs_mask) == 0U) {
@@ -660,6 +711,7 @@ int tegra_hwpm_func_single_ip(struct tegra_soc_hwpm *hwpm,
case TEGRA_HWPM_GET_ALIST_SIZE:
case TEGRA_HWPM_COMBINE_ALIST:
case TEGRA_HWPM_BIND_RESOURCES:
case TEGRA_HWPM_UNBIND_RESOURCES:
/* Skip unavailable IPs */
if (!chip_ip->reserved) {
tegra_hwpm_dbg(hwpm, hwpm_dbg_allowlist | hwpm_dbg_bind,

View File

@@ -161,6 +161,13 @@ fail:
return ret;
}
int tegra_hwpm_check_status(struct tegra_soc_hwpm *hwpm)
{
tegra_hwpm_fn(hwpm, " ");
return hwpm->active_chip->check_status(hwpm);
}
int tegra_hwpm_disable_triggers(struct tegra_soc_hwpm *hwpm)
{
tegra_hwpm_fn(hwpm, " ");

View File

@@ -110,6 +110,12 @@ int tegra_hwpm_release_resources(struct tegra_soc_hwpm *hwpm)
tegra_hwpm_fn(hwpm, " ");
ret = tegra_hwpm_func_all_ip(hwpm, NULL, TEGRA_HWPM_UNBIND_RESOURCES);
if (ret != 0) {
tegra_hwpm_err(hwpm, "failed to release resources");
return ret;
}
ret = tegra_hwpm_func_all_ip(hwpm, NULL, TEGRA_HWPM_RELEASE_RESOURCES);
if (ret != 0) {
tegra_hwpm_err(hwpm, "failed to release resources");

View File

@@ -163,8 +163,4 @@
#define pmasys_enginestatus_mbu_status_idle_v() (0x00000000U)
#define pmasys_enginestatus_mbu_status_busy_v() (0x00000001U)
#define pmasys_enginestatus_mbu_status_pending_v() (0x00000002U)
#define pmasys_sys_trigger_start_mask_r() (0x0f14a66cU)
#define pmasys_sys_trigger_start_maskb_r() (0x0f14a670U)
#define pmasys_sys_trigger_stop_mask_r() (0x0f14a684U)
#define pmasys_sys_trigger_stop_maskb_r() (0x0f14a688U)
#endif

View File

@@ -20,6 +20,63 @@
#include <hal/t234/hw/t234_pmasys_soc_hwpm.h>
#include <hal/t234/hw/t234_pmmsys_soc_hwpm.h>
int t234_hwpm_check_status(struct tegra_soc_hwpm *hwpm)
{
int err = 0;
u32 reg_val = 0U;
u32 field_mask = 0U;
u32 field_val = 0U;
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
struct hwpm_ip *chip_ip = active_chip->chip_ips[
active_chip->get_rtr_int_idx(hwpm)];
struct hwpm_ip_inst *ip_inst_rtr = &chip_ip->ip_inst_static_array[
T234_HWPM_IP_RTR_STATIC_RTR_INST];
struct hwpm_ip_inst *ip_inst_pma = &chip_ip->ip_inst_static_array[
T234_HWPM_IP_RTR_STATIC_PMA_INST];
struct hwpm_ip_aperture *rtr_perfmux = &ip_inst_rtr->element_info[
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
T234_HWPM_IP_RTR_PERMUX_INDEX];
struct hwpm_ip_aperture *pma_perfmux = &ip_inst_pma->element_info[
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
T234_HWPM_IP_RTR_PERMUX_INDEX];
tegra_hwpm_fn(hwpm, " ");
/* Check ROUTER state */
err = tegra_hwpm_readl(hwpm, rtr_perfmux,
pmmsys_sys0router_enginestatus_r(), &reg_val);
if (err != 0) {
tegra_hwpm_err(hwpm, "hwpm read failed");
return err;
}
if (pmmsys_sys0router_enginestatus_status_v(reg_val) !=
pmmsys_sys0router_enginestatus_status_empty_v()) {
tegra_hwpm_err(hwpm, "Router not ready value 0x%x", reg_val);
return -EINVAL;
}
/* Check PMA state */
field_mask = pmasys_enginestatus_status_m() |
pmasys_enginestatus_rbufempty_m();
field_val = pmasys_enginestatus_status_empty_f() |
pmasys_enginestatus_rbufempty_empty_f();
err = tegra_hwpm_readl(hwpm, pma_perfmux,
pmasys_enginestatus_r(), &reg_val);
if (err != 0) {
tegra_hwpm_err(hwpm, "hwpm read failed");
return err;
}
if ((reg_val & field_mask) != field_val) {
tegra_hwpm_err(hwpm, "PMA not ready value 0x%x", reg_val);
return -EINVAL;
}
return err;
}
int t234_hwpm_disable_triggers(struct tegra_soc_hwpm *hwpm)
{
int err = 0;
@@ -60,31 +117,6 @@ int t234_hwpm_disable_triggers(struct tegra_soc_hwpm *hwpm)
return err;
}
err = tegra_hwpm_writel(hwpm, pma_perfmux,
pmasys_sys_trigger_start_mask_r(), 0);
if (err != 0) {
tegra_hwpm_err(hwpm, "hwpm write failed");
return err;
}
err = tegra_hwpm_writel(hwpm, pma_perfmux,
pmasys_sys_trigger_start_maskb_r(), 0);
if (err != 0) {
tegra_hwpm_err(hwpm, "hwpm write failed");
return err;
}
err = tegra_hwpm_writel(hwpm, pma_perfmux,
pmasys_sys_trigger_stop_mask_r(), 0);
if (err != 0) {
tegra_hwpm_err(hwpm, "hwpm write failed");
return err;
}
err = tegra_hwpm_writel(hwpm, pma_perfmux,
pmasys_sys_trigger_stop_maskb_r(), 0);
if (err != 0) {
tegra_hwpm_err(hwpm, "hwpm write failed");
return err;
}
/* Wait for PERFMONs to idle */
err = tegra_hwpm_timeout_init(hwpm, &timeout, 10U);
if (err != 0) {

View File

@@ -46,6 +46,7 @@ static struct tegra_soc_hwpm_chip t234_chip_info = {
.perfmon_disable = t234_hwpm_perfmon_disable,
.perfmux_disable = tegra_hwpm_perfmux_disable,
.disable_triggers = t234_hwpm_disable_triggers,
.check_status = t234_hwpm_check_status,
.disable_mem_mgmt = t234_hwpm_disable_mem_mgmt,
.enable_mem_mgmt = t234_hwpm_enable_mem_mgmt,
@@ -154,6 +155,11 @@ static bool t234_hwpm_validate_hals(struct tegra_soc_hwpm *hwpm)
return false;
}
if (hwpm->active_chip->check_status == NULL) {
tegra_hwpm_err(hwpm, "check_status uninitialized");
return false;
}
if (hwpm->active_chip->disable_mem_mgmt == NULL) {
tegra_hwpm_err(hwpm, "disable_mem_mgmt HAL uninitialized");
return false;

View File

@@ -86,6 +86,7 @@ int t234_hwpm_init_prod_values(struct tegra_soc_hwpm *hwpm);
int t234_hwpm_disable_cg(struct tegra_soc_hwpm *hwpm);
int t234_hwpm_enable_cg(struct tegra_soc_hwpm *hwpm);
int t234_hwpm_check_status(struct tegra_soc_hwpm *hwpm);
int t234_hwpm_disable_triggers(struct tegra_soc_hwpm *hwpm);
int t234_hwpm_perfmon_enable(struct tegra_soc_hwpm *hwpm,
struct hwpm_ip_aperture *perfmon);

View File

@@ -162,12 +162,13 @@ enum tegra_hwpm_element_type {
enum tegra_hwpm_funcs {
TEGRA_HWPM_INIT_IP_STRUCTURES,
TEGRA_HWPM_MATCH_BASE_ADDRESS,
TEGRA_HWPM_FIND_GIVEN_ADDRESS,
TEGRA_HWPM_UPDATE_IP_INST_MASK,
TEGRA_HWPM_GET_ALIST_SIZE,
TEGRA_HWPM_COMBINE_ALIST,
TEGRA_HWPM_RESERVE_GIVEN_RESOURCE,
TEGRA_HWPM_BIND_RESOURCES,
TEGRA_HWPM_FIND_GIVEN_ADDRESS,
TEGRA_HWPM_UNBIND_RESOURCES,
TEGRA_HWPM_RELEASE_RESOURCES,
TEGRA_HWPM_RELEASE_ROUTER,
TEGRA_HWPM_RELEASE_IP_STRUCTURES
@@ -396,6 +397,7 @@ struct tegra_soc_hwpm_chip {
int (*reserve_rtr)(struct tegra_soc_hwpm *hwpm);
int (*release_rtr)(struct tegra_soc_hwpm *hwpm);
int (*check_status)(struct tegra_soc_hwpm *hwpm);
int (*disable_triggers)(struct tegra_soc_hwpm *hwpm);
int (*perfmon_enable)(struct tegra_soc_hwpm *hwpm,
struct hwpm_ip_aperture *perfmon);

View File

@@ -80,6 +80,7 @@ bool tegra_hwpm_check_alist(struct tegra_soc_hwpm *hwpm,
int tegra_hwpm_setup_hw(struct tegra_soc_hwpm *hwpm);
int tegra_hwpm_setup_sw(struct tegra_soc_hwpm *hwpm);
int tegra_hwpm_disable_triggers(struct tegra_soc_hwpm *hwpm);
int tegra_hwpm_check_status(struct tegra_soc_hwpm *hwpm);
int tegra_hwpm_release_hw(struct tegra_soc_hwpm *hwpm);
void tegra_hwpm_release_sw_setup(struct tegra_soc_hwpm *hwpm);

View File

@@ -412,6 +412,12 @@ static int tegra_hwpm_open(struct inode *inode, struct file *filp)
goto fail;
}
ret = tegra_hwpm_check_status(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "HW not ready for profiling session");
goto fail;
}
ret = tegra_hwpm_setup_sw(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Failed to setup sw");