tegra: hwpm: handle enginestatus = quiesce case

The device sampler test doesn't consume all PMA records and initiates
device close. This results in PMA engine status to be set to quiesce
state and tegra_hwpm_release() returning with error.
In such case, HWPM driver should close device completely and return any
resultant error.
Closing HWPM device completely ensures that sw state is reset and ready
for next session. And HWPM reset assert during device close resets HWPM
hardware.

Bug 3714516

Change-Id: I9d800bfb7a38f82a295f45a674d14808975a863e
Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2744657
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Vasuki Shankar <vasukis@nvidia.com>
Reviewed-by: Adeel Raza <araza@nvidia.com>
This commit is contained in:
Vedashree Vidwans
2022-07-14 10:52:52 -07:00
committed by mobile promotions
parent e28906ad68
commit a106a27456

View File

@@ -540,7 +540,7 @@ static ssize_t tegra_hwpm_read(struct file *file,
/* FIXME: Fix double release bug */
static int tegra_hwpm_release(struct inode *inode, struct file *filp)
{
int ret = 0;
int ret = 0, err = 0;
struct tegra_soc_hwpm *hwpm = NULL;
if (!inode) {
@@ -560,11 +560,6 @@ static int tegra_hwpm_release(struct inode *inode, struct file *filp)
tegra_hwpm_fn(hwpm, " ");
/* De-init driver on last close call only */
if (!atomic_dec_and_test(&hwpm->hwpm_in_use)) {
return 0;
}
if (hwpm->device_opened == false) {
/* Device was not opened, do nothing */
return 0;
@@ -573,13 +568,14 @@ static int tegra_hwpm_release(struct inode *inode, struct file *filp)
ret = tegra_hwpm_disable_triggers(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Failed to disable PMA triggers");
goto fail;
err = ret;
}
/* Disable and release reserved IPs */
ret = tegra_hwpm_release_resources(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Failed to release IP apertures");
err = ret;
goto fail;
}
@@ -587,12 +583,14 @@ static int tegra_hwpm_release(struct inode *inode, struct file *filp)
ret = tegra_hwpm_clear_mem_pipeline(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Failed to clear MEM_BYTES pipeline");
err = ret;
goto fail;
}
ret = tegra_hwpm_release_hw(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Failed to release hw");
err = ret;
goto fail;
}
@@ -600,19 +598,26 @@ static int tegra_hwpm_release(struct inode *inode, struct file *filp)
ret = reset_control_assert(hwpm->hwpm_rst);
if (ret < 0) {
tegra_hwpm_err(hwpm, "hwpm reset assert failed");
err = ret;
goto fail;
}
ret = reset_control_assert(hwpm->la_rst);
if (ret < 0) {
tegra_hwpm_err(hwpm, "la reset assert failed");
err = ret;
goto fail;
}
clk_disable_unprepare(hwpm->la_clk);
}
/* De-init driver on last close call only */
if (!atomic_dec_and_test(&hwpm->hwpm_in_use)) {
return 0;
}
hwpm->device_opened = false;
fail:
return ret;
return err;
}
/* File ops for device node */