Re: [PATCH v5 3/7] drm/amd: Split up UVD suspend into prepare and suspend steps
On Fri, Oct 6, 2023 at 3:07 PM Mario Limonciello wrote: > > amdgpu_uvd_suspend() allocates memory and copies objects into that > allocated memory. This fails under memory pressure. Instead move > majority of this code into a prepare step when swap can still be > allocated. > > Signed-off-by: Mario Limonciello > --- > v4->v5: > * New patch > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 12 > drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 1 + > drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 9 + > drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 9 + > drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 9 + > drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 9 + > drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 9 + > 7 files changed, 54 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c > index b7441654e6fa..a53c4ba8b3fe 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c > @@ -418,12 +418,11 @@ int amdgpu_uvd_entity_init(struct amdgpu_device *adev) > return 0; > } > > -int amdgpu_uvd_suspend(struct amdgpu_device *adev) > +int amdgpu_uvd_prepare(struct amdgpu_device *adev) amdgpu_uvd_prepare_suspend() so it's more obvious what this is for. Other than that, looks good to me. Alex > { > unsigned int size; > void *ptr; > int i, j, idx; > - bool in_ras_intr = amdgpu_ras_intr_triggered(); > > cancel_delayed_work_sync(>uvd.idle_work); > > @@ -452,7 +451,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) > > if (drm_dev_enter(adev_to_drm(adev), )) { > /* re-write 0 since err_event_athub will corrupt VCPU > buffer */ > - if (in_ras_intr) > + if (amdgpu_ras_intr_triggered()) > memset(adev->uvd.inst[j].saved_bo, 0, size); > else > memcpy_fromio(adev->uvd.inst[j].saved_bo, > ptr, size); > @@ -461,7 +460,12 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) > } > } > > - if (in_ras_intr) > + return 0; > +} > + > +int amdgpu_uvd_suspend(struct amdgpu_device *adev) > +{ > + if (amdgpu_ras_intr_triggered()) > DRM_WARN("UVD VCPU state may lost due to RAS > ERREVENT_ATHUB_INTERRUPT\n"); > > return 0; > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h > index 9f89bb7cd60b..72228425e021 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h > @@ -74,6 +74,7 @@ struct amdgpu_uvd { > int amdgpu_uvd_sw_init(struct amdgpu_device *adev); > int amdgpu_uvd_sw_fini(struct amdgpu_device *adev); > int amdgpu_uvd_entity_init(struct amdgpu_device *adev); > +int amdgpu_uvd_prepare(struct amdgpu_device *adev); > int amdgpu_uvd_suspend(struct amdgpu_device *adev); > int amdgpu_uvd_resume(struct amdgpu_device *adev); > int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, > diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c > b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c > index 5534c769b655..869e9948fa36 100644 > --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c > +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c > @@ -706,6 +706,14 @@ static int uvd_v3_1_hw_fini(void *handle) > return 0; > } > > +static int uvd_v3_1_prepare(void *handle) > +{ > + struct amdgpu_device *adev = (struct amdgpu_device *)handle; > + > + return amdgpu_uvd_prepare(adev); > + > +} > + > static int uvd_v3_1_suspend(void *handle) > { > int r; > @@ -806,6 +814,7 @@ static const struct amd_ip_funcs uvd_v3_1_ip_funcs = { > .sw_fini = uvd_v3_1_sw_fini, > .hw_init = uvd_v3_1_hw_init, > .hw_fini = uvd_v3_1_hw_fini, > + .prepare = uvd_v3_1_prepare, > .suspend = uvd_v3_1_suspend, > .resume = uvd_v3_1_resume, > .is_idle = uvd_v3_1_is_idle, > diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c > b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c > index c108b8381795..e589c17af371 100644 > --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c > +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c > @@ -220,6 +220,14 @@ static int uvd_v4_2_hw_fini(void *handle) > return 0; > } > > +static int uvd_v4_2_prepare(void *handle) > +{ > + struct amdgpu_device *adev = (struct amdgpu_device *)handle; > + > + return amdgpu_uvd_prepare(adev); > + > +} > + > static int uvd_v4_2_suspend(void *handle) > { > int r; > @@ -756,6 +764,7 @@ static const struct amd_ip_funcs uvd_v4_2_ip_funcs = { > .sw_fini = uvd_v4_2_sw_fini, > .hw_init = uvd_v4_2_hw_init, > .hw_fini = uvd_v4_2_hw_fini, > + .prepare = uvd_v4_2_prepare, > .suspend = uvd_v4_2_suspend, > .resume = uvd_v4_2_resume, > .is_idle =
[PATCH v5 3/7] drm/amd: Split up UVD suspend into prepare and suspend steps
amdgpu_uvd_suspend() allocates memory and copies objects into that allocated memory. This fails under memory pressure. Instead move majority of this code into a prepare step when swap can still be allocated. Signed-off-by: Mario Limonciello --- v4->v5: * New patch --- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 12 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 1 + drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 9 + drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 9 + drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 9 + drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 9 + drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 9 + 7 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index b7441654e6fa..a53c4ba8b3fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -418,12 +418,11 @@ int amdgpu_uvd_entity_init(struct amdgpu_device *adev) return 0; } -int amdgpu_uvd_suspend(struct amdgpu_device *adev) +int amdgpu_uvd_prepare(struct amdgpu_device *adev) { unsigned int size; void *ptr; int i, j, idx; - bool in_ras_intr = amdgpu_ras_intr_triggered(); cancel_delayed_work_sync(>uvd.idle_work); @@ -452,7 +451,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) if (drm_dev_enter(adev_to_drm(adev), )) { /* re-write 0 since err_event_athub will corrupt VCPU buffer */ - if (in_ras_intr) + if (amdgpu_ras_intr_triggered()) memset(adev->uvd.inst[j].saved_bo, 0, size); else memcpy_fromio(adev->uvd.inst[j].saved_bo, ptr, size); @@ -461,7 +460,12 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) } } - if (in_ras_intr) + return 0; +} + +int amdgpu_uvd_suspend(struct amdgpu_device *adev) +{ + if (amdgpu_ras_intr_triggered()) DRM_WARN("UVD VCPU state may lost due to RAS ERREVENT_ATHUB_INTERRUPT\n"); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h index 9f89bb7cd60b..72228425e021 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h @@ -74,6 +74,7 @@ struct amdgpu_uvd { int amdgpu_uvd_sw_init(struct amdgpu_device *adev); int amdgpu_uvd_sw_fini(struct amdgpu_device *adev); int amdgpu_uvd_entity_init(struct amdgpu_device *adev); +int amdgpu_uvd_prepare(struct amdgpu_device *adev); int amdgpu_uvd_suspend(struct amdgpu_device *adev); int amdgpu_uvd_resume(struct amdgpu_device *adev); int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c index 5534c769b655..869e9948fa36 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c @@ -706,6 +706,14 @@ static int uvd_v3_1_hw_fini(void *handle) return 0; } +static int uvd_v3_1_prepare(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return amdgpu_uvd_prepare(adev); + +} + static int uvd_v3_1_suspend(void *handle) { int r; @@ -806,6 +814,7 @@ static const struct amd_ip_funcs uvd_v3_1_ip_funcs = { .sw_fini = uvd_v3_1_sw_fini, .hw_init = uvd_v3_1_hw_init, .hw_fini = uvd_v3_1_hw_fini, + .prepare = uvd_v3_1_prepare, .suspend = uvd_v3_1_suspend, .resume = uvd_v3_1_resume, .is_idle = uvd_v3_1_is_idle, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index c108b8381795..e589c17af371 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -220,6 +220,14 @@ static int uvd_v4_2_hw_fini(void *handle) return 0; } +static int uvd_v4_2_prepare(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return amdgpu_uvd_prepare(adev); + +} + static int uvd_v4_2_suspend(void *handle) { int r; @@ -756,6 +764,7 @@ static const struct amd_ip_funcs uvd_v4_2_ip_funcs = { .sw_fini = uvd_v4_2_sw_fini, .hw_init = uvd_v4_2_hw_init, .hw_fini = uvd_v4_2_hw_fini, + .prepare = uvd_v4_2_prepare, .suspend = uvd_v4_2_suspend, .resume = uvd_v4_2_resume, .is_idle = uvd_v4_2_is_idle, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index d7e31e48a2b8..65aa23bc2d91 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -218,6 +218,14 @@ static int uvd_v5_0_hw_fini(void *handle) return 0; } +static int uvd_v5_0_prepare(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device