From: Louis Chauvet louis.chauvet@bootlin.com
commit c367b772e6d89d8c7b560c7df7e3803ce6b8bcea upstream.
Add drmm_alloc_ordered_workqueue(), a helper that provides managed ordered workqueue cleanup. The workqueue will be destroyed with the final reference of the DRM device.
Reviewed-by: Thomas Zimmermann tzimmermann@suse.de Reviewed-by: Maxime Ripard mripard@kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20250116-google-vkms-managed-v... Signed-off-by: Louis Chauvet louis.chauvet@bootlin.com Signed-off-by: Mikhail Dmitrichenko mdmitrichenko@astralinux.ru --- drivers/gpu/drm/drm_managed.c | 8 ++++++++ include/drm/drm_managed.h | 12 ++++++++++++ 2 files changed, 20 insertions(+)
diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index 79ce86a5bd67..cc4c463daae7 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -310,3 +310,11 @@ void __drmm_mutex_release(struct drm_device *dev, void *res) mutex_destroy(lock); } EXPORT_SYMBOL(__drmm_mutex_release); + +void __drmm_workqueue_release(struct drm_device *device, void *res) +{ + struct workqueue_struct *wq = res; + + destroy_workqueue(wq); +} +EXPORT_SYMBOL(__drmm_workqueue_release); diff --git a/include/drm/drm_managed.h b/include/drm/drm_managed.h index f547b09ca023..53017cc609ac 100644 --- a/include/drm/drm_managed.h +++ b/include/drm/drm_managed.h @@ -127,4 +127,16 @@ void __drmm_mutex_release(struct drm_device *dev, void *res); drmm_add_action_or_reset(dev, __drmm_mutex_release, lock); \ }) \
+void __drmm_workqueue_release(struct drm_device *device, void *wq); + +#define drmm_alloc_ordered_workqueue(dev, fmt, flags, args...) \ + ({ \ + struct workqueue_struct *wq = alloc_ordered_workqueue(fmt, flags, ##args); \ + wq ? ({ \ + int ret = drmm_add_action_or_reset(dev, __drmm_workqueue_release, wq); \ + ret ? ERR_PTR(ret) : wq; \ + }) : \ + wq; \ + }) + #endif
From: Michal Wajdeczko michal.wajdeczko@intel.com
commit 67979060740f7f978c8cb580ccea6c91154150f9 upstream.
If we fail to allocate a workqueue we will leak kzalloc'ed group object since it was designed to be kfree'ed in the drmm cleanup action, but we didn't have a chance to register this action yet.
To avoid this leak allocate a group object using drmm_kzalloc() and start using predefined drmm action to release the workqueue.
Signed-off-by: Michal Wajdeczko michal.wajdeczko@intel.com Reviewed-by: Matthew Brost matthew.brost@intel.com Link: https://lore.kernel.org/r/20250627184143.1480-1-michal.wajdeczko@intel.com Signed-off-by: Mikhail Dmitrichenko mdmitrichenko@astralinux.ru --- drivers/gpu/drm/xe/xe_hw_engine_group.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_group.c b/drivers/gpu/drm/xe/xe_hw_engine_group.c index 82750520a90a..9ace3993caee 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_group.c +++ b/drivers/gpu/drm/xe/xe_hw_engine_group.c @@ -12,15 +12,6 @@ #include "xe_hw_engine_group.h" #include "xe_vm.h"
-static void -hw_engine_group_free(struct drm_device *drm, void *arg) -{ - struct xe_hw_engine_group *group = arg; - - destroy_workqueue(group->resume_wq); - kfree(group); -} - static void hw_engine_group_resume_lr_jobs_func(struct work_struct *w) { @@ -53,7 +44,7 @@ hw_engine_group_alloc(struct xe_device *xe) struct xe_hw_engine_group *group; int err;
- group = kzalloc(sizeof(*group), GFP_KERNEL); + group = drmm_kzalloc(&xe->drm, sizeof(*group), GFP_KERNEL); if (!group) return ERR_PTR(-ENOMEM);
@@ -61,14 +52,14 @@ hw_engine_group_alloc(struct xe_device *xe) if (!group->resume_wq) return ERR_PTR(-ENOMEM);
+ err = drmm_add_action_or_reset(&xe->drm, __drmm_workqueue_release, group->resume_wq); + if (err) + return ERR_PTR(err); + init_rwsem(&group->mode_sem); INIT_WORK(&group->resume_work, hw_engine_group_resume_lr_jobs_func); INIT_LIST_HEAD(&group->exec_queue_list);
- err = drmm_add_action_or_reset(&xe->drm, hw_engine_group_free, group); - if (err) - return ERR_PTR(err); - return group; }
From: Shuicheng Lin shuicheng.lin@intel.com
commit 4846856c3a4afa882b6d1b842ed2fad6f3781f4d upstream.
Memory allocated with drmm_kzalloc() should not be freed using kfree(), as it is managed by the DRM subsystem. The memory will be automatically freed when the associated drm_device is released. These 3 group pointers are allocated using drmm_kzalloc() in hw_engine_group_alloc(), so they don't require manual deallocation.
Fixes: 67979060740f ("drm/xe/hw_engine_group: Fix potential leak") Signed-off-by: Shuicheng Lin shuicheng.lin@intel.com Reviewed-by: Matthew Brost matthew.brost@intel.com Signed-off-by: Michal Wajdeczko michal.wajdeczko@intel.com Link: https://lore.kernel.org/r/20250724193854.1124510-2-shuicheng.lin@intel.com (cherry picked from commit f98de826b418885a21ece67f0f5b921ae759b7bf) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Mikhail Dmitrichenko mdmitrichenko@astralinux.ru --- v2: upstream commit 67979060740f7f978c8cb580ccea6c91154150f9 was included in PATCH v2 2/3 because it also doesn't present in 6.12 and commit 4846856c3a4afa882b6d1b842ed2fad6f3781f4d fixes issue from 67979060740f7f978c8cb580ccea6c91154150f9. Upstream commit c367b772e6d89d8c7b560c7df7e3803ce6b8bcea was included in PATCH v2 1/3 because changes from 67979060740f7f978c8cb580ccea6c91154150f9 require __drmm_workqueue_release. drivers/gpu/drm/xe/xe_hw_engine_group.c | 28 ++++++------------------- 1 file changed, 6 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_group.c b/drivers/gpu/drm/xe/xe_hw_engine_group.c index 9ace3993caee..eef3a6479bfd 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_group.c +++ b/drivers/gpu/drm/xe/xe_hw_engine_group.c @@ -75,25 +75,18 @@ int xe_hw_engine_setup_groups(struct xe_gt *gt) enum xe_hw_engine_id id; struct xe_hw_engine_group *group_rcs_ccs, *group_bcs, *group_vcs_vecs; struct xe_device *xe = gt_to_xe(gt); - int err;
group_rcs_ccs = hw_engine_group_alloc(xe); - if (IS_ERR(group_rcs_ccs)) { - err = PTR_ERR(group_rcs_ccs); - goto err_group_rcs_ccs; - } + if (IS_ERR(group_rcs_ccs)) + return PTR_ERR(group_rcs_ccs);
group_bcs = hw_engine_group_alloc(xe); - if (IS_ERR(group_bcs)) { - err = PTR_ERR(group_bcs); - goto err_group_bcs; - } + if (IS_ERR(group_bcs)) + return PTR_ERR(group_bcs);
group_vcs_vecs = hw_engine_group_alloc(xe); - if (IS_ERR(group_vcs_vecs)) { - err = PTR_ERR(group_vcs_vecs); - goto err_group_vcs_vecs; - } + if (IS_ERR(group_vcs_vecs)) + return PTR_ERR(group_vcs_vecs);
for_each_hw_engine(hwe, gt, id) { switch (hwe->class) { @@ -116,15 +109,6 @@ int xe_hw_engine_setup_groups(struct xe_gt *gt) }
return 0; - -err_group_vcs_vecs: - kfree(group_vcs_vecs); -err_group_bcs: - kfree(group_bcs); -err_group_rcs_ccs: - kfree(group_rcs_ccs); - - return err; }
/**
linux-stable-mirror@lists.linaro.org