Skip to content

Commit

Permalink
drm: atmel-hlcdc: add a ->cleanup_fb() operation
Browse files Browse the repository at this point in the history
Add a ->cleanup_fb() operation to avoid memory leaks when the atomic
operation is interrupted after the ->prepare_fb() call.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Fixes 2389fc1 ("drm: atmel-hlcdc: Atomic mode-setting conversion")
Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Nicolas Ferre <nicolas.ferre@atmel.com>
  • Loading branch information
Boris Brezillon committed Apr 14, 2016
1 parent f9fd2ad commit 1a7b37c
Showing 1 changed file with 49 additions and 3 deletions.
52 changes: 49 additions & 3 deletions drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 *
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 1a7b37c

Please sign in to comment.