@@ -8655,26 +8655,35 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
intel_dmc_ucode_init(i915);
i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
+ if (!i915->display.wq.modeset) {
+ ret = -ENOMEM;
+ goto cleanup_vga_client_pw_domain_dmc;
+ }
+
i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
+ if (!i915->display.wq.flip) {
+ ret = -ENOMEM;
+ goto cleanup_modeset;
+ }
intel_mode_config_init(i915);
ret = intel_cdclk_init(i915);
if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
+ goto cleanup_flip;
ret = intel_color_init(i915);
if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
+ goto cleanup_flip;
ret = intel_dbuf_init(i915);
if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
+ goto cleanup_flip;
ret = intel_bw_init(i915);
if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
+ goto cleanup_flip;
init_llist_head(&i915->display.atomic_helper.free_list);
INIT_WORK(&i915->display.atomic_helper.free_work,
@@ -8686,6 +8695,10 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
return 0;
+cleanup_flip:
+ destroy_workqueue(i915->display.wq.flip);
+cleanup_modeset:
+ destroy_workqueue(i915->display.wq.modeset);
cleanup_vga_client_pw_domain_dmc:
intel_dmc_ucode_fini(i915);
intel_power_domains_driver_remove(i915);
Add checks for the return value of alloc_workqueue and alloc_ordered_workqueue as they may return NULL pointer and cause NULL pointer dereference. Moreover, destroy them when fails later in order to avoid memory leak. Because in `drivers/gpu/drm/i915/i915_driver.c`, if intel_modeset_init_noirq fails, its workqueues will not be destroyed. Fixes: c26a058680dc ("drm/i915: Use a high priority wq for nonblocking plane updates") Fixes: 757fffcfdffb ("drm/i915: Put all non-blocking modesets onto an ordered wq") Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn> --- drivers/gpu/drm/i915/display/intel_display.c | 21 ++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)