From 913f1b069782f583353206fd8eb0d6c06c74f7e8 Mon Sep 17 00:00:00 2001 From: Vedashree Vidwans Date: Wed, 5 Oct 2022 11:24:33 -0700 Subject: [PATCH] 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 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2776229 Reviewed-by: Seema Khowala GVS: Gerrit_Virtual_Submit Reviewed-on: https://git-master.nvidia.com/r/c/linux-hwpm/+/2797444 --- drivers/tegra/hwpm/common/aperture.c | 68 +++++++++++++-- drivers/tegra/hwpm/common/init.c | 7 ++ drivers/tegra/hwpm/common/resource.c | 6 ++ .../hwpm/hal/t234/hw/t234_pmasys_soc_hwpm.h | 4 - drivers/tegra/hwpm/hal/t234/t234_aperture.c | 82 +++++++++++++------ drivers/tegra/hwpm/hal/t234/t234_interface.c | 6 ++ drivers/tegra/hwpm/hal/t234/t234_internal.h | 1 + drivers/tegra/hwpm/include/tegra_hwpm.h | 4 +- .../tegra/hwpm/include/tegra_hwpm_common.h | 1 + drivers/tegra/hwpm/os/linux/ioctl.c | 6 ++ 10 files changed, 147 insertions(+), 38 deletions(-) diff --git a/drivers/tegra/hwpm/common/aperture.c b/drivers/tegra/hwpm/common/aperture.c index bf681ce..56e3f19 100644 --- a/drivers/tegra/hwpm/common/aperture.c +++ b/drivers/tegra/hwpm/common/aperture.c @@ -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, diff --git a/drivers/tegra/hwpm/common/init.c b/drivers/tegra/hwpm/common/init.c index 15d5744..9f99825 100644 --- a/drivers/tegra/hwpm/common/init.c +++ b/drivers/tegra/hwpm/common/init.c @@ -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, " "); diff --git a/drivers/tegra/hwpm/common/resource.c b/drivers/tegra/hwpm/common/resource.c index 0760946..41d9c46 100644 --- a/drivers/tegra/hwpm/common/resource.c +++ b/drivers/tegra/hwpm/common/resource.c @@ -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"); diff --git a/drivers/tegra/hwpm/hal/t234/hw/t234_pmasys_soc_hwpm.h b/drivers/tegra/hwpm/hal/t234/hw/t234_pmasys_soc_hwpm.h index 3dc8377..ca2d7c6 100644 --- a/drivers/tegra/hwpm/hal/t234/hw/t234_pmasys_soc_hwpm.h +++ b/drivers/tegra/hwpm/hal/t234/hw/t234_pmasys_soc_hwpm.h @@ -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 diff --git a/drivers/tegra/hwpm/hal/t234/t234_aperture.c b/drivers/tegra/hwpm/hal/t234/t234_aperture.c index e794524..dc52402 100644 --- a/drivers/tegra/hwpm/hal/t234/t234_aperture.c +++ b/drivers/tegra/hwpm/hal/t234/t234_aperture.c @@ -20,6 +20,63 @@ #include #include +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(), ®_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(), ®_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) { diff --git a/drivers/tegra/hwpm/hal/t234/t234_interface.c b/drivers/tegra/hwpm/hal/t234/t234_interface.c index 55af2ae..f200319 100644 --- a/drivers/tegra/hwpm/hal/t234/t234_interface.c +++ b/drivers/tegra/hwpm/hal/t234/t234_interface.c @@ -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; diff --git a/drivers/tegra/hwpm/hal/t234/t234_internal.h b/drivers/tegra/hwpm/hal/t234/t234_internal.h index 686c75c..62cd5be 100644 --- a/drivers/tegra/hwpm/hal/t234/t234_internal.h +++ b/drivers/tegra/hwpm/hal/t234/t234_internal.h @@ -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); diff --git a/drivers/tegra/hwpm/include/tegra_hwpm.h b/drivers/tegra/hwpm/include/tegra_hwpm.h index 99d60e2..59415b7 100644 --- a/drivers/tegra/hwpm/include/tegra_hwpm.h +++ b/drivers/tegra/hwpm/include/tegra_hwpm.h @@ -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); diff --git a/drivers/tegra/hwpm/include/tegra_hwpm_common.h b/drivers/tegra/hwpm/include/tegra_hwpm_common.h index 9e57aab..87ea2d5 100644 --- a/drivers/tegra/hwpm/include/tegra_hwpm_common.h +++ b/drivers/tegra/hwpm/include/tegra_hwpm_common.h @@ -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); diff --git a/drivers/tegra/hwpm/os/linux/ioctl.c b/drivers/tegra/hwpm/os/linux/ioctl.c index 5959e3f..f724264 100644 --- a/drivers/tegra/hwpm/os/linux/ioctl.c +++ b/drivers/tegra/hwpm/os/linux/ioctl.c @@ -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");