Skip to content

Commit

Permalink
accel/ivpu/37xx: Fix hangs related to MMIO reset
Browse files Browse the repository at this point in the history
[ Upstream commit 3f7c063 ]

There is no need to call MMIO reset using VPU_37XX_BUTTRESS_VPU_IP_RESET
register. IP will be reset by FLR or by entering d0i3. Also IP reset
during power_up is not needed as the VPU is already in reset.

Removing MMIO reset improves stability as it a partial device reset
that is not safe in some corner cases.

This change also brings back ivpu_boot_pwr_domain_disable() that
helps to properly power down VPU when it is hung by a buggy workload.

Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Fixes: 828d630 ("accel/ivpu: Don't enter d0i3 during FLR")
Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231115111004.1304092-1-jacek.lawrynowicz@linux.intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
jlawryno authored and gregkh committed Dec 3, 2023
1 parent e9fd34a commit 790c480
Showing 1 changed file with 22 additions and 24 deletions.
46 changes: 22 additions & 24 deletions drivers/accel/ivpu/ivpu_hw_37xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,16 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
return ret;
}

static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev)
{
ivpu_boot_dpu_active_drive(vdev, false);
ivpu_boot_pwr_island_isolation_drive(vdev, true);
ivpu_boot_pwr_island_trickle_drive(vdev, false);
ivpu_boot_pwr_island_drive(vdev, false);

return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0);
}

static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
{
u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES);
Expand Down Expand Up @@ -634,25 +644,17 @@ static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev)

static int ivpu_hw_37xx_reset(struct ivpu_device *vdev)
{
int ret;
u32 val;

if (IVPU_WA(punit_disabled))
return 0;
int ret = 0;

ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
if (ret) {
ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
return ret;
if (ivpu_boot_pwr_domain_disable(vdev)) {
ivpu_err(vdev, "Failed to disable power domain\n");
ret = -EIO;
}

val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET);
val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val);
REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val);

ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
if (ret)
ivpu_err(vdev, "Timed out waiting for RESET completion\n");
if (ivpu_pll_disable(vdev)) {
ivpu_err(vdev, "Failed to disable PLL\n");
ret = -EIO;
}

return ret;
}
Expand Down Expand Up @@ -685,10 +687,6 @@ static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev)
{
int ret;

ret = ivpu_hw_37xx_reset(vdev);
if (ret)
ivpu_warn(vdev, "Failed to reset HW: %d\n", ret);

ret = ivpu_hw_37xx_d0i3_disable(vdev);
if (ret)
ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
Expand Down Expand Up @@ -756,11 +754,11 @@ static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev)
{
int ret = 0;

if (!ivpu_hw_37xx_is_idle(vdev) && ivpu_hw_37xx_reset(vdev))
ivpu_err(vdev, "Failed to reset the VPU\n");
if (!ivpu_hw_37xx_is_idle(vdev))
ivpu_warn(vdev, "VPU not idle during power down\n");

if (ivpu_pll_disable(vdev)) {
ivpu_err(vdev, "Failed to disable PLL\n");
if (ivpu_hw_37xx_reset(vdev)) {
ivpu_err(vdev, "Failed to reset VPU\n");
ret = -EIO;
}

Expand Down

0 comments on commit 790c480

Please sign in to comment.