diff mbox series

[v2,1/6] drm/plane: Make format_mod_supported truly optional

Message ID 20211222090552.25972-2-jose.exposito89@gmail.com (mailing list archive)
State New, archived
Headers show
Series Add missing format_mod_supported functions | expand

Commit Message

José Expósito Dec. 22, 2021, 9:05 a.m. UTC
The documentation for "drm_plane_funcs.format_mod_supported" reads:

  This *optional* hook is used for the DRM to determine if the given
  format/modifier combination is valid for the plane. This allows the
  DRM to generate the correct format bitmask (which formats apply to
  which modifier), and to validate modifiers at atomic_check time.

  *If not present*, then any modifier in the plane's modifier
  list is allowed with any of the plane's formats.

However, where the function is not present, an invalid IN_FORMATS blob
property with modifiers but no formats is exposed to user-space.

This breaks the latest Weston [1]. For testing purposes, I extracted the
affected code to a standalone program [2].

Make "create_in_format_blob" behave as documented.

[1] https://gitlab.freedesktop.org/wayland/weston/-/blob/9.0/libweston/backend-drm/kms.c#L431
[2] https://github.com/JoseExposito/drm-sandbox/blob/main/in_formats.c

Signed-off-by: José Expósito <jose.exposito89@gmail.com>
---
 drivers/gpu/drm/drm_plane.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

Comments

Simon Ser Dec. 23, 2021, 10:10 a.m. UTC | #1
On Wednesday, December 22nd, 2021 at 10:05, José Expósito <jose.exposito89@gmail.com> wrote:

> Make "create_in_format_blob" behave as documented.

LGTM, nice!

Reviewed-by: Simon Ser <contact@emersion.fr>

CC Ville just in case
Ville Syrjälä Dec. 23, 2021, 11:56 a.m. UTC | #2
On Wed, Dec 22, 2021 at 10:05:47AM +0100, José Expósito wrote:
> The documentation for "drm_plane_funcs.format_mod_supported" reads:
> 
>   This *optional* hook is used for the DRM to determine if the given
>   format/modifier combination is valid for the plane. This allows the
>   DRM to generate the correct format bitmask (which formats apply to
>   which modifier), and to validate modifiers at atomic_check time.
> 
>   *If not present*, then any modifier in the plane's modifier
>   list is allowed with any of the plane's formats.
> 
> However, where the function is not present, an invalid IN_FORMATS blob
> property with modifiers but no formats is exposed to user-space.
> 
> This breaks the latest Weston [1]. For testing purposes, I extracted the
> affected code to a standalone program [2].
> 
> Make "create_in_format_blob" behave as documented.
> 
> [1] https://gitlab.freedesktop.org/wayland/weston/-/blob/9.0/libweston/backend-drm/kms.c#L431
> [2] https://github.com/JoseExposito/drm-sandbox/blob/main/in_formats.c
> 
> Signed-off-by: José Expósito <jose.exposito89@gmail.com>
> ---
>  drivers/gpu/drm/drm_plane.c | 8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
> index 82afb854141b..c1186b7215ee 100644
> --- a/drivers/gpu/drm/drm_plane.c
> +++ b/drivers/gpu/drm/drm_plane.c
> @@ -202,17 +202,13 @@ static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane
>  
>  	memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
>  
> -	/* If we can't determine support, just bail */
> -	if (!plane->funcs->format_mod_supported)
> -		goto done;
> -
>  	mod = modifiers_ptr(blob_data);
>  	for (i = 0; i < plane->modifier_count; i++) {
>  		for (j = 0; j < plane->format_count; j++) {
> -			if (plane->funcs->format_mod_supported(plane,
> +			if (!plane->funcs->format_mod_supported ||
> +			    plane->funcs->format_mod_supported(plane,
>  							       plane->format_types[j],
>  							       plane->modifiers[i])) {

So instead of skipping the whole loop you just skip doing anything
inside the loop? Can't see how that achieves anything at all.

https://patchwork.freedesktop.org/series/83018/
is what I had in mind earlier but no one reviewed it and 
the discussion veered off track IIRC.
Simon Ser Dec. 23, 2021, 1:42 p.m. UTC | #3
On Thursday, December 23rd, 2021 at 12:56, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:

> > -	/* If we can't determine support, just bail */
> > -	if (!plane->funcs->format_mod_supported)
> > -		goto done;
> > -
> >  	mod = modifiers_ptr(blob_data);
> >  	for (i = 0; i < plane->modifier_count; i++) {
> >  		for (j = 0; j < plane->format_count; j++) {
> > -			if (plane->funcs->format_mod_supported(plane,
> > +			if (!plane->funcs->format_mod_supported ||
> > +			    plane->funcs->format_mod_supported(plane,
> >  							       plane->format_types[j],
> >  							       plane->modifiers[i])) {
>
> So instead of skipping the whole loop you just skip doing anything
> inside the loop? Can't see how that achieves anything at all.

No, the check is skipped when the function isn't populated by the driver.
Ville Syrjälä Dec. 23, 2021, 3:03 p.m. UTC | #4
On Thu, Dec 23, 2021 at 01:42:32PM +0000, Simon Ser wrote:
> On Thursday, December 23rd, 2021 at 12:56, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> 
> > > -	/* If we can't determine support, just bail */
> > > -	if (!plane->funcs->format_mod_supported)
> > > -		goto done;
> > > -
> > >  	mod = modifiers_ptr(blob_data);
> > >  	for (i = 0; i < plane->modifier_count; i++) {
> > >  		for (j = 0; j < plane->format_count; j++) {
> > > -			if (plane->funcs->format_mod_supported(plane,
> > > +			if (!plane->funcs->format_mod_supported ||
> > > +			    plane->funcs->format_mod_supported(plane,
> > >  							       plane->format_types[j],
> > >  							       plane->modifiers[i])) {
> >
> > So instead of skipping the whole loop you just skip doing anything
> > inside the loop? Can't see how that achieves anything at all.
> 
> No, the check is skipped when the function isn't populated by the driver.

Ah right. So we advertise all modifiers in that case. Looks like
drm_plane_check_pixel_format() does support that model, so seems OK.

Another related thing that might be worth checking is whether
drivers generally do anything to validate the modifiers in
the addfb2 ioctl. Looks like i915 and amdgpu are the only ones
to use drm_any_plane_has_format() for that, so all the other
drivers must either be checking it manually (or they're just
potentially broken when handed unexpected modifiers by evil
userspace).
José Expósito Dec. 23, 2021, 4:57 p.m. UTC | #5
Thanks for your reviews :) I'll wait a couple of days to see
if somebody else wants to comment and I'll send v3 adding the
reviewed by tags and fixing the compiler warning.

On Thu, Dec 23, 2021 at 05:03:19PM +0200, Ville Syrjälä wrote:
> Another related thing that might be worth checking is whether
> drivers generally do anything to validate the modifiers in
> the addfb2 ioctl. Looks like i915 and amdgpu are the only ones
> to use drm_any_plane_has_format() for that, so all the other
> drivers must either be checking it manually (or they're just
> potentially broken when handed unexpected modifiers by evil
> userspace).

I'm pretty new to this subsystem, so please correct me if I'm 
wrong, but after looking into a couple of drivers I think you
are right, this check is missing in some drivers.

This possible bug reminds me of this ToDo task [1]:

> Many drivers wrap drm_gem_fb_create() only to check for valid formats. For
> atomic drivers we could check for valid formats by calling
> drm_plane_check_pixel_format() against all planes, and pass if any plane
> supports the format. For non-atomic that's not possible since like the format
> list for the primary plane is fake and we'd therefor reject valid formats.

I had a look to the Raspberry Pi driver (mainly because I'm trying
to understand it) and it looks like the check is missing. Other
drivers, for example Mali, are checking the format modifier manually.

I'll try to do some actual testing during Christmas and see
how it goes.

José Expósito

[1] https://www.kernel.org/doc/html/latest/gpu/todo.html#drm-framebuffer-funcs-and-drm-mode-config-funcs-fb-create-cleanup
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 82afb854141b..c1186b7215ee 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -202,17 +202,13 @@  static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane
 
 	memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
 
-	/* If we can't determine support, just bail */
-	if (!plane->funcs->format_mod_supported)
-		goto done;
-
 	mod = modifiers_ptr(blob_data);
 	for (i = 0; i < plane->modifier_count; i++) {
 		for (j = 0; j < plane->format_count; j++) {
-			if (plane->funcs->format_mod_supported(plane,
+			if (!plane->funcs->format_mod_supported ||
+			    plane->funcs->format_mod_supported(plane,
 							       plane->format_types[j],
 							       plane->modifiers[i])) {
-
 				mod->formats |= 1ULL << j;
 			}
 		}