On 1/10/2025 7:38 AM, Jiang Liu wrote: > Introduce new interface amdgpu_xcp_drm_dev_free() to free a specific > drm_device crreated by amdgpu_xcp_drm_dev_alloc(), which will be used > to do error recovery. > > Signed-off-by: Jiang Liu <gerry@xxxxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c | 65 +++++++++++++++++---- > drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h | 1 + > 2 files changed, 56 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c > index faed84172dd4..0473fe0479d9 100644 > --- a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c > +++ b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c > @@ -45,18 +45,26 @@ static const struct drm_driver amdgpu_xcp_driver = { > > static int8_t pdev_num; > static struct xcp_device *xcp_dev[MAX_XCP_PLATFORM_DEVICE]; > +static DEFINE_MUTEX(xcp_mutex); > > int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev) > { > struct platform_device *pdev; > struct xcp_device *pxcp_dev; > char dev_name[20]; > - int ret; > + int ret, index; > + > + guard(mutex)(&xcp_mutex); > > if (pdev_num >= MAX_XCP_PLATFORM_DEVICE) > return -ENODEV; > > - snprintf(dev_name, sizeof(dev_name), "amdgpu_xcp_%d", pdev_num); > + for (index = 0; index < MAX_XCP_PLATFORM_DEVICE; index++) { > + if (!xcp_dev[index]) > + break; > + } > + > + snprintf(dev_name, sizeof(dev_name), "amdgpu_xcp_%d", index); > pdev = platform_device_register_simple(dev_name, -1, NULL, 0); > if (IS_ERR(pdev)) > return PTR_ERR(pdev); > @@ -72,8 +80,8 @@ int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev) > goto out_devres; > } > > - xcp_dev[pdev_num] = pxcp_dev; > - xcp_dev[pdev_num]->pdev = pdev; > + xcp_dev[index] = pxcp_dev; > + xcp_dev[index]->pdev = pdev; > *ddev = &pxcp_dev->drm; > pdev_num++; > > @@ -88,16 +96,53 @@ int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev) > } > EXPORT_SYMBOL(amdgpu_xcp_drm_dev_alloc); > > +static void __amdgpu_xcp_drm_dev_free(int index) > +{ > + struct platform_device *pdev; > + > + pdev = xcp_dev[index]->pdev; > + devres_release_group(&pdev->dev, NULL); > + platform_device_unregister(pdev); > + xcp_dev[index] = NULL; > + pdev_num--; > +} > + > +void amdgpu_xcp_drm_dev_free(struct drm_device *ddev) > +{ > + int index; > + struct xcp_device *pxcp_dev; > + > + if (ddev == NULL) > + return; > + > + guard(mutex)(&xcp_mutex); > + WARN_ON(!pdev_num); > + > + pxcp_dev = container_of(ddev, struct xcp_device, drm); > + for (index = 0; index < MAX_XCP_PLATFORM_DEVICE; index++) { > + if (xcp_dev[index] == pxcp_dev) { > + __amdgpu_xcp_drm_dev_free(index); > + break; > + } > + } > +} > +EXPORT_SYMBOL(amdgpu_xcp_drm_dev_free); > + > void amdgpu_xcp_drv_release(void) > { > - for (--pdev_num; pdev_num >= 0; --pdev_num) { > - struct platform_device *pdev = xcp_dev[pdev_num]->pdev; > + int index; > > - devres_release_group(&pdev->dev, NULL); > - platform_device_unregister(pdev); > - xcp_dev[pdev_num] = NULL; > + guard(mutex)(&xcp_mutex); > + > + for (index = 0; index < MAX_XCP_PLATFORM_DEVICE; index++) { May be this - before entering or as first check. for (index = 0; pdev_num && index < MAX_XCP_PLATFORM_DEVICE; index++) Thanks, Lijo > + if (xcp_dev[index]) { > + __amdgpu_xcp_drm_dev_free(index); > + if (!pdev_num) > + break; > + } > } > - pdev_num = 0; > + > + WARN_ON(pdev_num != 0); > } > EXPORT_SYMBOL(amdgpu_xcp_drv_release); > > diff --git a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h > index c1c4b679bf95..580a1602c8e3 100644 > --- a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h > +++ b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h > @@ -25,5 +25,6 @@ > #define _AMDGPU_XCP_DRV_H_ > > int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev); > +void amdgpu_xcp_drm_dev_free(struct drm_device *ddev); > void amdgpu_xcp_drv_release(void); > #endif /* _AMDGPU_XCP_DRV_H_ */