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.lawrynow...@linux.intel.com>
> > 
> > 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.

> 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: sta...@vger.kernel.org
> > Signed-off-by: Jacek Lawrynowicz <jacek.lawrynow...@linux.intel.com>
> > Reviewed-by: Stanislaw Gruszka <stanislaw.grus...@linux.intel.com>
> > Signed-off-by: Stanislaw Gruszka <stanislaw.grus...@linux.intel.com>
> > ---
> >   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");
> 

Reply via email to