Skip to content

Commit 437eccb

Browse files
committed
Merge tag 'drm-misc-fixes-2026-03-19' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
A doc warning fix and a memory leak fix for vmwgfx, a deadlock fix and interrupt handling fixes for imagination, a locking fix for pagemap_until, a UAF fix for drm_dev_unplug, and a multi-channel audio handling fix for dw-hdmi-qp. Signed-off-by: Dave Airlie <[email protected]> From: Maxime Ripard <[email protected]> Link: https://patch.msgid.link/20260319-lush-righteous-malamute-e7bb98@houat
2 parents d551d2e + cffcb42 commit 437eccb

8 files changed

Lines changed: 114 additions & 80 deletions

File tree

drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ static int dw_hdmi_qp_config_audio_infoframe(struct dw_hdmi_qp *hdmi,
848848

849849
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1);
850850
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS1, &buffer[3], 1);
851-
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[4], 1);
851+
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[7], 1);
852852

853853
/* Enable ACR, AUDI, AMD */
854854
dw_hdmi_qp_mod(hdmi,

drivers/gpu/drm/drm_file.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ static void drm_events_release(struct drm_file *file_priv)
233233
void drm_file_free(struct drm_file *file)
234234
{
235235
struct drm_device *dev;
236+
int idx;
236237

237238
if (!file)
238239
return;
@@ -249,9 +250,11 @@ void drm_file_free(struct drm_file *file)
249250

250251
drm_events_release(file);
251252

252-
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
253+
if (drm_core_check_feature(dev, DRIVER_MODESET) &&
254+
drm_dev_enter(dev, &idx)) {
253255
drm_fb_release(file);
254256
drm_property_destroy_user_blobs(dev, file);
257+
drm_dev_exit(idx);
255258
}
256259

257260
if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))

drivers/gpu/drm/drm_mode_config.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -577,10 +577,13 @@ void drm_mode_config_cleanup(struct drm_device *dev)
577577
*/
578578
WARN_ON(!list_empty(&dev->mode_config.fb_list));
579579
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
580-
struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
580+
if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) {
581+
struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
581582

582-
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
583-
drm_framebuffer_print_info(&p, 1, fb);
583+
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
584+
drm_framebuffer_print_info(&p, 1, fb);
585+
}
586+
list_del_init(&fb->filp_head);
584587
drm_framebuffer_free(&fb->base.refcount);
585588
}
586589

drivers/gpu/drm/drm_pagemap_util.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,14 @@ static void drm_pagemap_cache_fini(void *arg)
6565
drm_dbg(cache->shrinker->drm, "Destroying dpagemap cache.\n");
6666
spin_lock(&cache->lock);
6767
dpagemap = cache->dpagemap;
68-
if (!dpagemap) {
69-
spin_unlock(&cache->lock);
70-
goto out;
71-
}
68+
cache->dpagemap = NULL;
69+
if (dpagemap && !drm_pagemap_shrinker_cancel(dpagemap))
70+
dpagemap = NULL;
71+
spin_unlock(&cache->lock);
7272

73-
if (drm_pagemap_shrinker_cancel(dpagemap)) {
74-
cache->dpagemap = NULL;
75-
spin_unlock(&cache->lock);
73+
if (dpagemap)
7674
drm_pagemap_destroy(dpagemap, false);
77-
}
7875

79-
out:
8076
mutex_destroy(&cache->lookup_mutex);
8177
kfree(cache);
8278
}

drivers/gpu/drm/imagination/pvr_device.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -225,29 +225,12 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
225225
}
226226

227227
if (pvr_dev->has_safety_events) {
228-
int err;
229-
230-
/*
231-
* Ensure the GPU is powered on since some safety events (such
232-
* as ECC faults) can happen outside of job submissions, which
233-
* are otherwise the only time a power reference is held.
234-
*/
235-
err = pvr_power_get(pvr_dev);
236-
if (err) {
237-
drm_err_ratelimited(drm_dev,
238-
"%s: could not take power reference (%d)\n",
239-
__func__, err);
240-
return ret;
241-
}
242-
243228
while (pvr_device_safety_irq_pending(pvr_dev)) {
244229
pvr_device_safety_irq_clear(pvr_dev);
245230
pvr_device_handle_safety_events(pvr_dev);
246231

247232
ret = IRQ_HANDLED;
248233
}
249-
250-
pvr_power_put(pvr_dev);
251234
}
252235

253236
return ret;

drivers/gpu/drm/imagination/pvr_power.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ pvr_power_request_pwr_off(struct pvr_device *pvr_dev)
9090
}
9191

9292
static int
93-
pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)
93+
pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset, bool rpm_suspend)
9494
{
95-
if (!hard_reset) {
96-
int err;
95+
int err;
9796

97+
if (!hard_reset) {
9898
cancel_delayed_work_sync(&pvr_dev->watchdog.work);
9999

100100
err = pvr_power_request_idle(pvr_dev);
@@ -106,29 +106,47 @@ pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)
106106
return err;
107107
}
108108

109-
return pvr_fw_stop(pvr_dev);
109+
if (rpm_suspend) {
110+
/* This also waits for late processing of GPU or firmware IRQs in other cores */
111+
disable_irq(pvr_dev->irq);
112+
}
113+
114+
err = pvr_fw_stop(pvr_dev);
115+
if (err && rpm_suspend)
116+
enable_irq(pvr_dev->irq);
117+
118+
return err;
110119
}
111120

112121
static int
113-
pvr_power_fw_enable(struct pvr_device *pvr_dev)
122+
pvr_power_fw_enable(struct pvr_device *pvr_dev, bool rpm_resume)
114123
{
115124
int err;
116125

126+
if (rpm_resume)
127+
enable_irq(pvr_dev->irq);
128+
117129
err = pvr_fw_start(pvr_dev);
118130
if (err)
119-
return err;
131+
goto out;
120132

121133
err = pvr_wait_for_fw_boot(pvr_dev);
122134
if (err) {
123135
drm_err(from_pvr_device(pvr_dev), "Firmware failed to boot\n");
124136
pvr_fw_stop(pvr_dev);
125-
return err;
137+
goto out;
126138
}
127139

128140
queue_delayed_work(pvr_dev->sched_wq, &pvr_dev->watchdog.work,
129141
msecs_to_jiffies(WATCHDOG_TIME_MS));
130142

131143
return 0;
144+
145+
out:
146+
if (rpm_resume)
147+
disable_irq(pvr_dev->irq);
148+
149+
return err;
132150
}
133151

134152
bool
@@ -361,7 +379,7 @@ pvr_power_device_suspend(struct device *dev)
361379
return -EIO;
362380

363381
if (pvr_dev->fw_dev.booted) {
364-
err = pvr_power_fw_disable(pvr_dev, false);
382+
err = pvr_power_fw_disable(pvr_dev, false, true);
365383
if (err)
366384
goto err_drm_dev_exit;
367385
}
@@ -391,7 +409,7 @@ pvr_power_device_resume(struct device *dev)
391409
goto err_drm_dev_exit;
392410

393411
if (pvr_dev->fw_dev.booted) {
394-
err = pvr_power_fw_enable(pvr_dev);
412+
err = pvr_power_fw_enable(pvr_dev, true);
395413
if (err)
396414
goto err_power_off;
397415
}
@@ -510,15 +528,24 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
510528
}
511529

512530
/* Disable IRQs for the duration of the reset. */
513-
disable_irq(pvr_dev->irq);
531+
if (hard_reset) {
532+
disable_irq(pvr_dev->irq);
533+
} else {
534+
/*
535+
* Soft reset is triggered as a response to a FW command to the Host and is
536+
* processed from the threaded IRQ handler. This code cannot (nor needs to)
537+
* wait for any IRQ processing to complete.
538+
*/
539+
disable_irq_nosync(pvr_dev->irq);
540+
}
514541

515542
do {
516543
if (hard_reset) {
517544
pvr_queue_device_pre_reset(pvr_dev);
518545
queues_disabled = true;
519546
}
520547

521-
err = pvr_power_fw_disable(pvr_dev, hard_reset);
548+
err = pvr_power_fw_disable(pvr_dev, hard_reset, false);
522549
if (!err) {
523550
if (hard_reset) {
524551
pvr_dev->fw_dev.booted = false;
@@ -541,7 +568,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
541568

542569
pvr_fw_irq_clear(pvr_dev);
543570

544-
err = pvr_power_fw_enable(pvr_dev);
571+
err = pvr_power_fw_enable(pvr_dev, false);
545572
}
546573

547574
if (err && hard_reset)

0 commit comments

Comments
 (0)