[PATCH v3 1/4] drm/amd: Add support for prepare() and complete() callbacks

Deucher, Alexander Alexander.Deucher at amd.com
Tue Oct 3 21:11:35 UTC 2023


[Public]

> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces at lists.freedesktop.org> On Behalf Of Mario
> Limonciello
> Sent: Tuesday, October 3, 2023 4:55 PM
> To: amd-gfx at lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland at amd.com>; Limonciello, Mario
> <Mario.Limonciello at amd.com>
> Subject: [PATCH v3 1/4] drm/amd: Add support for prepare() and complete()
> callbacks
>
> Linux PM core has a prepare() callback run before suspend and complete()
> callback ran after resume() for devices to use.  Add plumbing to bring
> prepare() to amdgpu.
>
> The idea with the new vfuncs for amdgpu is that all IP blocks that memory
> allocations during suspend should do the allocation from this call instead of
> the suspend() callback.
>
> By moving the allocations to prepare() the system suspend will be failed before
> any IP block has done any suspend code.
>
> If the suspend fails, then do any cleanups in the complete() callback.
>
> Signed-off-by: Mario Limonciello <mario.limonciello at amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h        |  2 ++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 39
> ++++++++++++++++++++--
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c    | 11 +++---
>  3 files changed, 46 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 73e825d20259..5d651552822c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1415,6 +1415,8 @@ void amdgpu_driver_postclose_kms(struct
> drm_device *dev,  void amdgpu_driver_release_kms(struct drm_device *dev);
>
>  int amdgpu_device_ip_suspend(struct amdgpu_device *adev);
> +int amdgpu_device_prepare(struct drm_device *dev); void
> +amdgpu_device_complete(struct drm_device *dev);
>  int amdgpu_device_suspend(struct drm_device *dev, bool fbcon);  int
> amdgpu_device_resume(struct drm_device *dev, bool fbcon);
>  u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc); diff --git
> a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index bad2b5577e96..f53cf675c3ce 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -4259,6 +4259,43 @@ static int amdgpu_device_evict_resources(struct
> amdgpu_device *adev)
>  /*
>   * Suspend & resume.
>   */
> +/**
> + * amdgpu_device_prepare - prepare for device suspend
> + *
> + * @dev: drm dev pointer
> + *
> + * Prepare to put the hw in the suspend state (all asics).
> + * Returns 0 for success or an error on failure.
> + * Called at driver suspend.
> + */
> +int amdgpu_device_prepare(struct drm_device *dev) {
> +     struct amdgpu_device *adev = drm_to_adev(dev);
> +     int r;
> +
> +     if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
> +             return 0;
> +
> +     adev->in_suspend = true;
> +
> +     return 0;
> +}
> +
> +/**
> + * amdgpu_device_complete - complete the device after resume
> + *
> + * @dev: drm dev pointer
> + *
> + * Clean up any actions that the prepare step did.
> + * Called after driver resume.
> + */
> +void amdgpu_device_complete(struct drm_device *dev) {
> +     struct amdgpu_device *adev = drm_to_adev(dev);
> +
> +     adev->in_suspend = false;
> +}
> +
>  /**
>   * amdgpu_device_suspend - initiate device suspend
>   *
> @@ -4277,8 +4314,6 @@ int amdgpu_device_suspend(struct drm_device
> *dev, bool fbcon)
>       if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
>               return 0;
>
> -     adev->in_suspend = true;
> -

We also set this to false in amdgpu_device_resume() so that should be fixed up as well.  But, I'm not sure we want to move this out of amdgpu_device_suspend().  There are places we use amdgpu_device_suspend/resume() outside of pmops that also rely on these being set.  Those places may need to be fixed up if we do.  IIRC, the switcheroo code uses this.

Alex

>       /* Evict the majority of BOs before grabbing the full access */
>       r = amdgpu_device_evict_resources(adev);
>       if (r)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index e3471293846f..4c6fb852516a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -2425,8 +2425,9 @@ static int amdgpu_pmops_prepare(struct device
> *dev)
>       /* Return a positive number here so
>        * DPM_FLAG_SMART_SUSPEND works properly
>        */
> -     if (amdgpu_device_supports_boco(drm_dev))
> -             return pm_runtime_suspended(dev);
> +     if (amdgpu_device_supports_boco(drm_dev) &&
> +         pm_runtime_suspended(dev))
> +             return 1;
>
>       /* if we will not support s3 or s2i for the device
>        *  then skip suspend
> @@ -2435,12 +2436,14 @@ static int amdgpu_pmops_prepare(struct device
> *dev)
>           !amdgpu_acpi_is_s3_active(adev))
>               return 1;
>
> -     return 0;
> +     return amdgpu_device_prepare(drm_dev);
>  }
>
>  static void amdgpu_pmops_complete(struct device *dev)  {
> -     /* nothing to do */
> +     struct drm_device *drm_dev = dev_get_drvdata(dev);
> +
> +     amdgpu_device_complete(drm_dev);
>  }
>
>  static int amdgpu_pmops_suspend(struct device *dev)
> --
> 2.34.1



More information about the amd-gfx mailing list