Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a7b37ca authored by Boris Brezillon's avatar Boris Brezillon
Browse files

drm: atmel-hlcdc: add a ->cleanup_fb() operation



Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
operation is interrupted after the ->prepare_fb() call.

Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Fixes 2389fc13 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
Reviewed-by: default avatarNicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: default avatarNicolas Ferre <nicolas.ferre@atmel.com>
parent f9fd2ada
Loading
Loading
Loading
Loading
+49 −3
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
 * @xstride: value to add to the pixel pointer between each line
 * @pstride: value to add to the pixel pointer between each pixel
 * @nplanes: number of planes (deduced from pixel_format)
 * @prepared: plane update has been prepared
 */
struct atmel_hlcdc_plane_state {
	struct drm_plane_state base;
@@ -64,6 +65,7 @@ struct atmel_hlcdc_plane_state {
	int xstride[ATMEL_HLCDC_MAX_PLANES];
	int pstride[ATMEL_HLCDC_MAX_PLANES];
	int nplanes;
	bool prepared;
};

static inline struct atmel_hlcdc_plane_state *
@@ -714,12 +716,54 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
					const struct drm_plane_state *new_state)
{
	/*
	 * FIXME: we should avoid this const -> non-const cast but it's
	 * currently the only solution we have to modify the ->prepared
	 * state and rollback the update request.
	 * Ideally, we should rework the code to attach all the resources
	 * to atmel_hlcdc_plane_state (including the DMA desc allocation),
	 * but this require a complete rework of the atmel_hlcdc_layer
	 * code.
	 */
	struct drm_plane_state *s = (struct drm_plane_state *)new_state;
	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
	struct atmel_hlcdc_plane_state *state =
			drm_plane_state_to_atmel_hlcdc_plane_state(s);
	int ret;

	if (!new_state->fb)
		return 0;
	ret = atmel_hlcdc_layer_update_start(&plane->layer);
	if (!ret)
		state->prepared = true;

	return ret;
}

static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
				const struct drm_plane_state *old_state)
{
	/*
	 * FIXME: we should avoid this const -> non-const cast but it's
	 * currently the only solution we have to modify the ->prepared
	 * state and rollback the update request.
	 * Ideally, we should rework the code to attach all the resources
	 * to atmel_hlcdc_plane_state (including the DMA desc allocation),
	 * but this require a complete rework of the atmel_hlcdc_layer
	 * code.
	 */
	struct drm_plane_state *s = (struct drm_plane_state *)old_state;
	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
	struct atmel_hlcdc_plane_state *state =
			drm_plane_state_to_atmel_hlcdc_plane_state(s);

	/*
	 * The Request has already been applied or cancelled, nothing to do
	 * here.
	 */
	if (!state->prepared)
		return;

	return atmel_hlcdc_layer_update_start(&plane->layer);
	atmel_hlcdc_layer_update_rollback(&plane->layer);
	state->prepared = false;
}

static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
@@ -844,6 +888,7 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,

static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
	.prepare_fb = atmel_hlcdc_plane_prepare_fb,
	.cleanup_fb = atmel_hlcdc_plane_cleanup_fb,
	.atomic_check = atmel_hlcdc_plane_atomic_check,
	.atomic_update = atmel_hlcdc_plane_atomic_update,
	.atomic_disable = atmel_hlcdc_plane_atomic_disable,
@@ -883,6 +928,7 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
		return NULL;

	copy->disc_updated = false;
	copy->prepared = false;

	if (copy->base.fb)
		drm_framebuffer_reference(copy->base.fb);