[PATCH] drm/sun4i: Check that the plane coordinates are not negative
Boris Brezillon
boris.brezillon at free-electrons.com
Fri Sep 30 09:33:48 PDT 2016
On Fri, 30 Sep 2016 19:22:11 +0300
Ville Syrjälä <ville.syrjala at linux.intel.com> wrote:
> On Fri, Sep 30, 2016 at 06:08:26PM +0200, Boris Brezillon wrote:
> > On Fri, 30 Sep 2016 16:33:20 +0200
> > Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> >
> > > Our planes cannot be set at negative coordinates. Make sure we reject such
> > > configuration.
> > >
> > > Reported-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> > > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > > ---
> > > drivers/gpu/drm/sun4i/sun4i_layer.c | 3 +++
> > > 1 file changed, 3 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> > > index f0035bf5efea..f5463c4c2cde 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> > > @@ -29,6 +29,9 @@ struct sun4i_plane_desc {
> > > static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
> > > struct drm_plane_state *state)
> > > {
> > > + if ((state->crtc_x < 0) || (state->crtc_y < 0))
> > > + return -EINVAL;
> > > +
> >
> > Hm, I think it's a perfectly valid use case from the DRM framework and
> > DRM user PoV: you may want to place your plane at a negative CRTC
> > offset (which means part of the plane will be hidden).
> >
> > Maybe I'm wrong, but it seems you can support that by adapting the
> > start address of your framebuffer pointer and the layer size.
> >
> > Have you tried doing something like that?
>
> You shouldn't even be looking at the user provided coordinates. Also
> you can't return an error from the atomic update hook. The void return
> value should have been a decent hint ;)
Note that Maxime is not returning a value from the atomic update
implementation (it's done in the atomic_check implem), and I'm not
checking crtc_x,y consistency at all (which is obviously wrong), I'm
just blindly patching the values in sun4i_backend helpers.
> The right fix would be
> to move all the error handling into the atomic check hook, which
> probably should just call the helper to clip the coordinates and
> whatnot. Then the update hook can just use at the clipped
> coordinates when programming the hw registers.
That's probably the best approach indeed, but that means having our
private sun4i_plane_state struct where we would store the patched
crtc_{w,h,x,y} info.
Anyway, before we do that, that's probably better to check if it really
works on this HW (which is why I sent this informal patch).
>
> >
> > --->8---
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
> > index 3ab560450a82..6b68804f3035 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_backend.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
> > @@ -110,15 +110,30 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
> > {
> > struct drm_plane_state *state = plane->state;
> > struct drm_framebuffer *fb = state->fb;
> > + int crtc_w, crtc_h, crtc_x, crtc_y;
> >
> > DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
> >
> > + crtc_x = state->crtc_x;
> > + crtc_y = state->crtc_y;
> > + crtc_w = state->crtc_w;
> > + crtc_h = state->crtc_h;
> > +
> > + if (crtc_x < 0) {
> > + crtc_w += crtx_x;
> > + crtc_x = 0;
> > + }
> > +
> > + if (crtc_y < 0) {
> > + crtc_h += crtx_y;
> > + crtc_y = 0;
> > + }
> > +
> > if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
> > DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
> > state->crtc_w, state->crtc_h);
> > regmap_write(backend->regs, SUN4I_BACKEND_DISSIZE_REG,
> > - SUN4I_BACKEND_DISSIZE(state->crtc_w,
> > - state->crtc_h));
> > + SUN4I_BACKEND_DISSIZE(crtc_w, crtc_h));
> > }
> >
> > /* Set the line width */
> > @@ -130,15 +145,13 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
> > DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
> > state->crtc_w, state->crtc_h);
> > regmap_write(backend->regs, SUN4I_BACKEND_LAYSIZE_REG(layer),
> > - SUN4I_BACKEND_LAYSIZE(state->crtc_w,
> > - state->crtc_h));
> > + SUN4I_BACKEND_LAYSIZE(crtc_w, crtc_h));
> >
> > /* Set base coordinates */
> > DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
> > state->crtc_x, state->crtc_y);
> > regmap_write(backend->regs, SUN4I_BACKEND_LAYCOOR_REG(layer),
> > - SUN4I_BACKEND_LAYCOOR(state->crtc_x,
> > - state->crtc_y));
> > + SUN4I_BACKEND_LAYCOOR(crtc_x, crtc_y));
> >
> > return 0;
> > }
> > @@ -198,6 +211,12 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
> > paddr += (state->src_x >> 16) * bpp;
> > paddr += (state->src_y >> 16) * fb->pitches[0];
> >
> > + if (state->crtc_x < 0)
> > + paddr -= bpp * state->crtc_x;
> > +
> > + if (state->crtc_y < 0)
> > + paddr -= fb->pitches[0] * state->crtc_y;
> > +
> > DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
> >
> > /* Write the 32 lower bits of the address (in bits) */
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
More information about the linux-arm-kernel
mailing list