diff mbox series

accel/ivpu/37xx: Fix hangs related to MMIO reset

Message ID 20231115111004.1304092-1-jacek.lawrynowicz@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series accel/ivpu/37xx: Fix hangs related to MMIO reset | expand

Commit Message

Jacek Lawrynowicz Nov. 15, 2023, 11:10 a.m. UTC
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: 828d63042aec ("accel/ivpu: Don't enter d0i3 during FLR")
---
 drivers/accel/ivpu/ivpu_hw_37xx.c | 46 +++++++++++++++----------------
 1 file changed, 22 insertions(+), 24 deletions(-)

Comments

Jeffrey Hugo Nov. 17, 2023, 3:35 p.m. UTC | #1
On 11/15/2023 4:10 AM, Jacek Lawrynowicz wrote:
> 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: 828d63042aec ("accel/ivpu: Don't enter d0i3 during FLR")

Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Jacek Lawrynowicz Nov. 21, 2023, 8:30 a.m. UTC | #2
Applied to drm-misc-fixes

On 15.11.2023 12:10, Jacek Lawrynowicz wrote:
> 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: 828d63042aec ("accel/ivpu: Don't enter d0i3 during FLR")
> ---
>  drivers/accel/ivpu/ivpu_hw_37xx.c | 46 +++++++++++++++----------------
>  1 file changed, 22 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
> index 5c0246b9e522..4ccf1994b97a 100644
> --- a/drivers/accel/ivpu/ivpu_hw_37xx.c
> +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
> @@ -502,6 +502,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);
> @@ -600,25 +610,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;
>  }
> @@ -651,10 +653,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);
> @@ -722,11 +720,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;
>  	}
>
diff mbox series

Patch

diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
index 5c0246b9e522..4ccf1994b97a 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
+++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
@@ -502,6 +502,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);
@@ -600,25 +610,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;
 }
@@ -651,10 +653,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);
@@ -722,11 +720,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;
 	}