Re: [PATCH v4 2/3] drm/amd: Stop evicting resources on APUs in suspend

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

 



On Thu, Feb 8, 2024 at 1:48 AM Mario Limonciello
<mario.limonciello@xxxxxxx> wrote:
>
> commit 5095d5418193 ("drm/amd: Evict resources during PM ops prepare()
> callback") intentionally moved the eviction of resources to earlier in
> the suspend process, but this introduced a subtle change that it occurs
> before adev->in_s0ix or adev->in_s3 are set. This meant that APUs
> actually started to evict resources at suspend time as well.
>
> Explicitly set s0ix or s3 in the prepare() stage, and unset them if the
> prepare() stage failed.
>
> Reported-by: Jürg Billeter <j@xxxxxxxxx>
> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3132#note_2271038
> Fixes: 5095d5418193 ("drm/amd: Evict resources during PM ops prepare() callback")
> Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx>

Acked-by: Alex Deucher <alexander.deucher@xxxxxxx>

> ---
> v3->v4:
>     * New function to set s0ix/s3 and explicitly unset in cleanup
> v2->v3:
>     * Whitespace
> v1->v2:
>     * Add and use new in_prepare member
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h        |  2 ++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c   | 15 +++++++++++++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +++++++++--
>  3 files changed, 26 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 3d8a48f46b01..f6c38a974bae 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1547,9 +1547,11 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
>  #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
>  bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev);
>  bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
> +void amdgpu_choose_low_power_state(struct amdgpu_device *adev);
>  #else
>  static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
>  static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; }
> +static void amdgpu_choose_low_power_state(struct amdgpu_device *adev) { }
>  #endif
>
>  #if defined(CONFIG_DRM_AMD_DC)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> index 2deebece810e..cc21ed67a330 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> @@ -1519,4 +1519,19 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
>  #endif /* CONFIG_AMD_PMC */
>  }
>
> +/**
> + * amdgpu_choose_low_power_state
> + *
> + * @adev: amdgpu_device_pointer
> + *
> + * Choose the target low power state for the GPU
> + */
> +void amdgpu_choose_low_power_state(struct amdgpu_device *adev)
> +{
> +       if (amdgpu_acpi_is_s0ix_active(adev))
> +               adev->in_s0ix = true;
> +       else if (amdgpu_acpi_is_s3_active(adev))
> +               adev->in_s3 = true;
> +}
> +
>  #endif /* CONFIG_SUSPEND */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 2bc460cb993d..dab03865c827 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -4518,13 +4518,15 @@ int amdgpu_device_prepare(struct drm_device *dev)
>         struct amdgpu_device *adev = drm_to_adev(dev);
>         int i, r;
>
> +       amdgpu_choose_low_power_state(adev);
> +
>         if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
>                 return 0;
>
>         /* Evict the majority of BOs before starting suspend sequence */
>         r = amdgpu_device_evict_resources(adev);
>         if (r)
> -               return r;
> +               goto unprepare;
>
>         for (i = 0; i < adev->num_ip_blocks; i++) {
>                 if (!adev->ip_blocks[i].status.valid)
> @@ -4533,10 +4535,15 @@ int amdgpu_device_prepare(struct drm_device *dev)
>                         continue;
>                 r = adev->ip_blocks[i].version->funcs->prepare_suspend((void *)adev);
>                 if (r)
> -                       return r;
> +                       goto unprepare;
>         }
>
>         return 0;
> +
> +unprepare:
> +       adev->in_s0ix = adev->in_s3 = false;
> +
> +       return r;
>  }
>
>  /**
> --
> 2.34.1
>




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux