summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2019-02-20 19:51:37 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2019-03-18 11:24:32 -0400
commite482ae9b5fdc01a343f22f52930e85a6cfdf85eb (patch)
tree8fcd79f282738625611ba8cbd1e4f87c5104e2d8
parent97eb9eaeb95ba8eb3c7a77a7ec7786d47a1bcaee (diff)
drm: writeback: Fix leak of writeback job
Writeback jobs are allocated when the WRITEBACK_FB_ID is set, and deleted when the jobs complete. This results in both a memory leak of the job and a leak of the framebuffer if the atomic commit returns before the job is queued for processing, for instance if the atomic check fails or if the commit runs in test-only mode. Fix this by implementing the drm_writeback_cleanup_job() function and calling it from __drm_atomic_helper_connector_destroy_state(). As writeback jobs are removed from the state when they're queued for processing, any job left in the state when the state gets destroyed needs to be cleaned up. The existing declaration of the drm_writeback_cleanup_job() function without an implementation hints that this problem was considered, but never addressed. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Brian Starkey <brian.starkey@arm.com> Acked-by: Liviu Dudau <liviu.dudau@arm.com>
-rw-r--r--drivers/gpu/drm/drm_atomic_state_helper.c4
-rw-r--r--drivers/gpu/drm/drm_writeback.c14
2 files changed, 15 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 4985384e51f6..59ffb6b9c745 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -30,6 +30,7 @@
30#include <drm/drm_connector.h> 30#include <drm/drm_connector.h>
31#include <drm/drm_atomic.h> 31#include <drm/drm_atomic.h>
32#include <drm/drm_device.h> 32#include <drm/drm_device.h>
33#include <drm/drm_writeback.h>
33 34
34#include <linux/slab.h> 35#include <linux/slab.h>
35#include <linux/dma-fence.h> 36#include <linux/dma-fence.h>
@@ -412,6 +413,9 @@ __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
412 413
413 if (state->commit) 414 if (state->commit)
414 drm_crtc_commit_put(state->commit); 415 drm_crtc_commit_put(state->commit);
416
417 if (state->writeback_job)
418 drm_writeback_cleanup_job(state->writeback_job);
415} 419}
416EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state); 420EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
417 421
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 338b993d7c9f..1b497d3530b5 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -273,6 +273,15 @@ void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector,
273} 273}
274EXPORT_SYMBOL(drm_writeback_queue_job); 274EXPORT_SYMBOL(drm_writeback_queue_job);
275 275
276void drm_writeback_cleanup_job(struct drm_writeback_job *job)
277{
278 if (job->fb)
279 drm_framebuffer_put(job->fb);
280
281 kfree(job);
282}
283EXPORT_SYMBOL(drm_writeback_cleanup_job);
284
276/* 285/*
277 * @cleanup_work: deferred cleanup of a writeback job 286 * @cleanup_work: deferred cleanup of a writeback job
278 * 287 *
@@ -285,10 +294,9 @@ static void cleanup_work(struct work_struct *work)
285 struct drm_writeback_job *job = container_of(work, 294 struct drm_writeback_job *job = container_of(work,
286 struct drm_writeback_job, 295 struct drm_writeback_job,
287 cleanup_work); 296 cleanup_work);
288 drm_framebuffer_put(job->fb);
289 kfree(job);
290}
291 297
298 drm_writeback_cleanup_job(job);
299}
292 300
293/** 301/**
294 * drm_writeback_signal_completion - Signal the completion of a writeback job 302 * drm_writeback_signal_completion - Signal the completion of a writeback job