Series is: Reviewed-by: Alex Deucher <[email protected]>
On Fri, Oct 9, 2026 at 5:08 AM Jesse Zhang <[email protected]> wrote: > > amdgpu_cs_parser_bos() allocates an HMM range for every userptr entry of > the BO list and looks up the user pages. Those ranges are only freed when > amdgpu_cs_parser_bos() itself fails or when amdgpu_cs_submit() checks > them under the notifier lock. If amdgpu_cs_patch_jobs(), > amdgpu_cs_vm_handling(), amdgpu_cs_sync_rings() or the early part of > amdgpu_cs_submit() fails, nothing frees them: neither > amdgpu_cs_parser_fini() nor amdgpu_bo_list_free() touch e->range. > > Each such CS then leaks the range, its hmm_pfns array (8 bytes per page > of the userptr BO) and the BO reference the range holds. An IB on a ring > that patches the CS in place (e.g. VCN) with an unmapped va_start fails > in amdgpu_cs_patch_ibs() and takes this path. > > Free the ranges on those error paths. Ranges amdgpu_cs_submit() already > dropped are NULL, so freeing them again is a no-op. > > Fixes: fec8fdb54e8f ("drm/amdgpu: fix userptr HMM range handling v2") > Signed-off-by: Jesse Zhang <[email protected]> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 15 +++++++++++---- > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c > index d059e0c92866..d3c1b4b9472f 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c > @@ -1435,6 +1435,7 @@ static void amdgpu_cs_parser_fini(struct > amdgpu_cs_parser *parser) > int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file > *filp) > { > struct amdgpu_device *adev = drm_to_adev(dev); > + struct amdgpu_bo_list_entry *e; > struct amdgpu_cs_parser parser; > int r; > > @@ -1475,25 +1476,31 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void > *data, struct drm_file *filp) > > r = amdgpu_cs_patch_jobs(&parser); > if (r) > - goto error_fini; > + goto error_free_user_pages; > > r = amdgpu_cs_vm_handling(&parser); > if (r) > - goto error_fini; > + goto error_free_user_pages; > > r = amdgpu_cs_sync_rings(&parser); > if (r) > - goto error_fini; > + goto error_free_user_pages; > > trace_amdgpu_cs_ibs(&parser); > > r = amdgpu_cs_submit(&parser, data); > if (r) > - goto error_fini; > + goto error_free_user_pages; > > amdgpu_cs_parser_fini(&parser); > return 0; > > +error_free_user_pages: > + /* amdgpu_cs_submit() only drops the ranges once it got that far. */ > + amdgpu_bo_list_for_each_userptr_entry(e, parser.bo_list) { > + amdgpu_hmm_range_free(e->range); > + e->range = NULL; > + } > error_fini: > amdgpu_cs_parser_fini(&parser); > return r; > -- > 2.50.1 >
