Re: [PATCH] accel/ivpu: Don't enter d0i3 during FLR

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/17/2023 2:43 AM, Stanislaw Gruszka wrote:
On Fri, Oct 06, 2023 at 09:25:29AM -0600, Jeffrey Hugo wrote:
On 10/3/2023 12:42 AM, Stanislaw Gruszka wrote:
From: Jacek Lawrynowicz <jacek.lawrynowicz@xxxxxxxxxxxxxxx>

Fix a bug on some platforms where FLR causes complete system
hang when CPU is low power states (C8 or above).

Why does FLR cause a complete system hang?

This HW bug is still under debug and it is not yet root caused.

Ouch.  Good luck with that.


Why does avoiding d0i3 fix the
issue?  Feels like there could be a lot more detail here.

We only know that we should avoid entering D0i3.

I will change the log this way:

Avoid HW bug on some platforms where we enter D0i3 state
and CPU is in low power states (C8 or above).

Regards
Stanislaw

Fixes: 852be13f3bd3 ("accel/ivpu: Add PM support")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@xxxxxxxxxxxxxxx>
Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@xxxxxxxxxxxxxxx>
Signed-off-by: Stanislaw Gruszka <stanislaw.gruszka@xxxxxxxxxxxxxxx>
---
   drivers/accel/ivpu/ivpu_drv.c     | 11 ++++++++---
   drivers/accel/ivpu/ivpu_drv.h     |  1 +
   drivers/accel/ivpu/ivpu_hw.h      |  8 ++++++++
   drivers/accel/ivpu/ivpu_hw_37xx.c |  1 +
   drivers/accel/ivpu/ivpu_hw_40xx.c |  1 +
   drivers/accel/ivpu/ivpu_pm.c      |  3 ++-
   6 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c
index 3f4efa07ce7c..1eb232e903e8 100644
--- a/drivers/accel/ivpu/ivpu_drv.c
+++ b/drivers/accel/ivpu/ivpu_drv.c
@@ -367,14 +367,19 @@ int ivpu_boot(struct ivpu_device *vdev)
   	return 0;
   }
-int ivpu_shutdown(struct ivpu_device *vdev)
+void ivpu_prepare_for_reset(struct ivpu_device *vdev)
   {
-	int ret;
-
   	ivpu_hw_irq_disable(vdev);
   	disable_irq(vdev->irq);
   	ivpu_ipc_disable(vdev);
   	ivpu_mmu_disable(vdev);
+}
+
+int ivpu_shutdown(struct ivpu_device *vdev)
+{
+	int ret;
+
+	ivpu_prepare_for_reset(vdev);
   	ret = ivpu_hw_power_down(vdev);
   	if (ret)
diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h
index 98380c1db9fa..a3b45032e6cf 100644
--- a/drivers/accel/ivpu/ivpu_drv.h
+++ b/drivers/accel/ivpu/ivpu_drv.h
@@ -158,6 +158,7 @@ void ivpu_file_priv_put(struct ivpu_file_priv **link);
   int ivpu_boot(struct ivpu_device *vdev);
   int ivpu_shutdown(struct ivpu_device *vdev);
+void ivpu_prepare_for_reset(struct ivpu_device *vdev);
   static inline u8 ivpu_revision(struct ivpu_device *vdev)
   {
diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h
index ab341237bcf9..1079e06255ba 100644
--- a/drivers/accel/ivpu/ivpu_hw.h
+++ b/drivers/accel/ivpu/ivpu_hw.h
@@ -13,6 +13,7 @@ struct ivpu_hw_ops {
   	int (*power_up)(struct ivpu_device *vdev);
   	int (*boot_fw)(struct ivpu_device *vdev);
   	int (*power_down)(struct ivpu_device *vdev);
+	int (*reset)(struct ivpu_device *vdev);
   	bool (*is_idle)(struct ivpu_device *vdev);
   	void (*wdt_disable)(struct ivpu_device *vdev);
   	void (*diagnose_failure)(struct ivpu_device *vdev);
@@ -91,6 +92,13 @@ static inline int ivpu_hw_power_down(struct ivpu_device *vdev)
   	return vdev->hw->ops->power_down(vdev);
   };
+static inline int ivpu_hw_reset(struct ivpu_device *vdev)
+{
+	ivpu_dbg(vdev, PM, "HW reset\n");
+
+	return vdev->hw->ops->reset(vdev);
+};
+
   static inline void ivpu_hw_wdt_disable(struct ivpu_device *vdev)
   {
   	vdev->hw->ops->wdt_disable(vdev);
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
index edd4d860f135..1e842739e937 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
+++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
@@ -1036,6 +1036,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = {
   	.power_up = ivpu_hw_37xx_power_up,
   	.is_idle = ivpu_hw_37xx_is_idle,
   	.power_down = ivpu_hw_37xx_power_down,
+	.reset = ivpu_hw_37xx_reset,
   	.boot_fw = ivpu_hw_37xx_boot_fw,
   	.wdt_disable = ivpu_hw_37xx_wdt_disable,
   	.diagnose_failure = ivpu_hw_37xx_diagnose_failure,
diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c
index a48cd36f9931..d7b8ec0410af 100644
--- a/drivers/accel/ivpu/ivpu_hw_40xx.c
+++ b/drivers/accel/ivpu/ivpu_hw_40xx.c
@@ -1186,6 +1186,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = {
   	.power_up = ivpu_hw_40xx_power_up,
   	.is_idle = ivpu_hw_40xx_is_idle,
   	.power_down = ivpu_hw_40xx_power_down,
+	.reset = ivpu_hw_40xx_reset,
   	.boot_fw = ivpu_hw_40xx_boot_fw,
   	.wdt_disable = ivpu_hw_40xx_wdt_disable,
   	.diagnose_failure = ivpu_hw_40xx_diagnose_failure,
diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
index 28a0d1111e12..da46f95b008a 100644
--- a/drivers/accel/ivpu/ivpu_pm.c
+++ b/drivers/accel/ivpu/ivpu_pm.c
@@ -261,7 +261,8 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev)
   	ivpu_dbg(vdev, PM, "Pre-reset..\n");
   	atomic_inc(&vdev->pm->reset_counter);
   	atomic_set(&vdev->pm->in_reset, 1);
-	ivpu_shutdown(vdev);
+	ivpu_prepare_for_reset(vdev);
+	ivpu_hw_reset(vdev);
   	ivpu_pm_prepare_cold_boot(vdev);
   	ivpu_jobs_abort_all(vdev);
   	ivpu_dbg(vdev, PM, "Pre-reset done.\n");





[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux