diff mbox series

drm/framebuffer: Expose only modifiers that support at least a format

Message ID 20181106024434.12322-1-dhinakaran.pandiyan@intel.com (mailing list archive)
State New, archived
Headers show
Series drm/framebuffer: Expose only modifiers that support at least a format | expand

Commit Message

Dhinakaran Pandiyan Nov. 6, 2018, 2:44 a.m. UTC
Allows drivers to pass a larger modifier array, thereby avoiding
declarations of static modifier arrays that are only slight different
for each plane.

Cc: dri-devel@lists.freedesktop.org
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
---
 drivers/gpu/drm/drm_plane.c | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

Comments

Ville Syrjälä Nov. 6, 2018, 2:13 p.m. UTC | #1
On Mon, Nov 05, 2018 at 06:44:34PM -0800, Dhinakaran Pandiyan wrote:
> Allows drivers to pass a larger modifier array, thereby avoiding
> declarations of static modifier arrays that are only slight different
> for each plane.
> 
> Cc: dri-devel@lists.freedesktop.org
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> ---
>  drivers/gpu/drm/drm_plane.c | 35 +++++++++++++++++++++++++++--------
>  1 file changed, 27 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
> index 1fa98bd12003..1546ffbf8e36 100644
> --- a/drivers/gpu/drm/drm_plane.c
> +++ b/drivers/gpu/drm/drm_plane.c
> @@ -179,8 +179,8 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  			     const char *name, ...)
>  {
>  	struct drm_mode_config *config = &dev->mode_config;
> -	unsigned int format_modifier_count = 0;
> -	int ret;
> +	unsigned int format_modifier_count, in_modifier_count = 0;
> +	int ret, i;
>  
>  	/* plane index is used with 32bit bitmasks */
>  	if (WARN_ON(config->num_total_plane >= 32))
> @@ -216,22 +216,43 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  
>  	if (format_modifiers) {
>  		const uint64_t *temp_modifiers = format_modifiers;
> +
>  		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
> -			format_modifier_count++;
> +			in_modifier_count++;
>  	}
>  
> -	plane->modifier_count = format_modifier_count;
> -	plane->modifiers = kmalloc_array(format_modifier_count,
> +	plane->modifiers = kmalloc_array(in_modifier_count,
>  					 sizeof(format_modifiers[0]),
>  					 GFP_KERNEL);
>  
> -	if (format_modifier_count && !plane->modifiers) {
> +	if (in_modifier_count && !plane->modifiers) {
>  		DRM_DEBUG_KMS("out of memory when allocating plane\n");
>  		kfree(plane->format_types);
>  		drm_mode_object_unregister(dev, &plane->base);
>  		return -ENOMEM;
>  	}
>  
> +	for (i = 0, format_modifier_count = 0; i < in_modifier_count; i++) {
> +		int j;
> +
> +		for (j = 0; funcs->format_mod_supported && j < format_count; j++)
> +			if (funcs->format_mod_supported(plane, formats[j],
> +							format_modifiers[i]))
> +				break;
> +
> +		if (j < format_count)
> +			plane->modifiers[format_modifier_count++] =
> +				format_modifiers[i];
> +	}
> +
> +	if (format_modifier_count < in_modifier_count) {
> +		size_t size;
> +
> +		size = format_modifier_count * sizeof(format_modifiers[0]);
> +		plane->modifiers = krealloc(plane->modifiers, size, GFP_KERNEL);

Should check that the realloc actually succeeded.

And I think we might want to give this same treatment to plane->formats[]
as well.

And perhaps we could even throw out plane->modifiers[] and just rely on
the IN_FORMATS blob exclusively? Hmm. Looks like that is not getting fully
populated unless the driver has provided .format_mod_supported(). Not
sure why that is, and not sure what userspace is supposed to do with a
partially filled blob like that. I'm thinking we shouldn't even attach
the property to the plane in that case.

> +	}
> +	plane->modifier_count = format_modifier_count;
> +
>  	if (name) {
>  		va_list ap;
>  
> @@ -251,8 +272,6 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
>  
>  	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
>  	plane->format_count = format_count;
> -	memcpy(plane->modifiers, format_modifiers,
> -	       format_modifier_count * sizeof(format_modifiers[0]));
>  	plane->possible_crtcs = possible_crtcs;
>  	plane->type = type;
>  
> -- 
> 2.14.1
Dhinakaran Pandiyan Nov. 6, 2018, 7:54 p.m. UTC | #2
On Tue, 2018-11-06 at 16:13 +0200, Ville Syrjälä wrote:
> On Mon, Nov 05, 2018 at 06:44:34PM -0800, Dhinakaran Pandiyan wrote:
> > Allows drivers to pass a larger modifier array, thereby avoiding
> > declarations of static modifier arrays that are only slight
> > different
> > for each plane.
> > 
> > Cc: dri-devel@lists.freedesktop.org
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > ---
> >  drivers/gpu/drm/drm_plane.c | 35 +++++++++++++++++++++++++++----
> > ----
> >  1 file changed, 27 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_plane.c
> > b/drivers/gpu/drm/drm_plane.c
> > index 1fa98bd12003..1546ffbf8e36 100644
> > --- a/drivers/gpu/drm/drm_plane.c
> > +++ b/drivers/gpu/drm/drm_plane.c
> > @@ -179,8 +179,8 @@ int drm_universal_plane_init(struct drm_device
> > *dev, struct drm_plane *plane,
> >  			     const char *name, ...)
> >  {
> >  	struct drm_mode_config *config = &dev->mode_config;
> > -	unsigned int format_modifier_count = 0;
> > -	int ret;
> > +	unsigned int format_modifier_count, in_modifier_count = 0;
> > +	int ret, i;
> >  
> >  	/* plane index is used with 32bit bitmasks */
> >  	if (WARN_ON(config->num_total_plane >= 32))
> > @@ -216,22 +216,43 @@ int drm_universal_plane_init(struct
> > drm_device *dev, struct drm_plane *plane,
> >  
> >  	if (format_modifiers) {
> >  		const uint64_t *temp_modifiers = format_modifiers;
> > +
> >  		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
> > -			format_modifier_count++;
> > +			in_modifier_count++;
> >  	}
> >  
> > -	plane->modifier_count = format_modifier_count;
> > -	plane->modifiers = kmalloc_array(format_modifier_count,
> > +	plane->modifiers = kmalloc_array(in_modifier_count,
> >  					 sizeof(format_modifiers[0]),
> >  					 GFP_KERNEL);
> >  
> > -	if (format_modifier_count && !plane->modifiers) {
> > +	if (in_modifier_count && !plane->modifiers) {
> >  		DRM_DEBUG_KMS("out of memory when allocating plane\n");
> >  		kfree(plane->format_types);
> >  		drm_mode_object_unregister(dev, &plane->base);
> >  		return -ENOMEM;
> >  	}
> >  
> > +	for (i = 0, format_modifier_count = 0; i < in_modifier_count;
> > i++) {
> > +		int j;
> > +
> > +		for (j = 0; funcs->format_mod_supported && j <
> > format_count; j++)
> > +			if (funcs->format_mod_supported(plane,
> > formats[j],
> > +							format_modifier
> > s[i]))
> > +				break;
> > +
> > +		if (j < format_count)
> > +			plane->modifiers[format_modifier_count++] =
> > +				format_modifiers[i];
> > +	}
> > +
> > +	if (format_modifier_count < in_modifier_count) {
> > +		size_t size;
> > +
> > +		size = format_modifier_count *
> > sizeof(format_modifiers[0]);
> > +		plane->modifiers = krealloc(plane->modifiers, size,
> > GFP_KERNEL);
> 
> Should check that the realloc actually succeeded.
Didn't see a failure path for new size smaller than old, the return is
the same pointer passed to krealloc().

> 
> And I think we might want to give this same treatment to plane-
> >formats[]
> as well.
> 
> And perhaps we could even throw out plane->modifiers[] and just rely
> on
> the IN_FORMATS blob exclusively? Hmm. Looks like that is not getting
> fully
> populated unless the driver has provided .format_mod_supported(). Not
> sure why that is, and not sure what userspace is supposed to do with
> a
> partially filled blob like that. I'm thinking we shouldn't even
> attach
> the property to the plane in that case.

Shouldn't it copy the modifier array into the blob and mark all formats
as supported? drm_plane_check_pixel_format() seems to allow any valid
format for a modifier in this case.


-DK

> 
> > +	}
> > +	plane->modifier_count = format_modifier_count;
> > +
> >  	if (name) {
> >  		va_list ap;
> >  
> > @@ -251,8 +272,6 @@ int drm_universal_plane_init(struct drm_device
> > *dev, struct drm_plane *plane,
> >  
> >  	memcpy(plane->format_types, formats, format_count *
> > sizeof(uint32_t));
> >  	plane->format_count = format_count;
> > -	memcpy(plane->modifiers, format_modifiers,
> > -	       format_modifier_count * sizeof(format_modifiers[0]));
> >  	plane->possible_crtcs = possible_crtcs;
> >  	plane->type = type;
> >  
> > -- 
> > 2.14.1
> 
>
Ville Syrjälä Nov. 6, 2018, 8:21 p.m. UTC | #3
On Tue, Nov 06, 2018 at 11:54:45AM -0800, Dhinakaran Pandiyan wrote:
> On Tue, 2018-11-06 at 16:13 +0200, Ville Syrjälä wrote:
> > On Mon, Nov 05, 2018 at 06:44:34PM -0800, Dhinakaran Pandiyan wrote:
> > > Allows drivers to pass a larger modifier array, thereby avoiding
> > > declarations of static modifier arrays that are only slight
> > > different
> > > for each plane.
> > > 
> > > Cc: dri-devel@lists.freedesktop.org
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > ---
> > >  drivers/gpu/drm/drm_plane.c | 35 +++++++++++++++++++++++++++----
> > > ----
> > >  1 file changed, 27 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_plane.c
> > > b/drivers/gpu/drm/drm_plane.c
> > > index 1fa98bd12003..1546ffbf8e36 100644
> > > --- a/drivers/gpu/drm/drm_plane.c
> > > +++ b/drivers/gpu/drm/drm_plane.c
> > > @@ -179,8 +179,8 @@ int drm_universal_plane_init(struct drm_device
> > > *dev, struct drm_plane *plane,
> > >  			     const char *name, ...)
> > >  {
> > >  	struct drm_mode_config *config = &dev->mode_config;
> > > -	unsigned int format_modifier_count = 0;
> > > -	int ret;
> > > +	unsigned int format_modifier_count, in_modifier_count = 0;
> > > +	int ret, i;
> > >  
> > >  	/* plane index is used with 32bit bitmasks */
> > >  	if (WARN_ON(config->num_total_plane >= 32))
> > > @@ -216,22 +216,43 @@ int drm_universal_plane_init(struct
> > > drm_device *dev, struct drm_plane *plane,
> > >  
> > >  	if (format_modifiers) {
> > >  		const uint64_t *temp_modifiers = format_modifiers;
> > > +
> > >  		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
> > > -			format_modifier_count++;
> > > +			in_modifier_count++;
> > >  	}
> > >  
> > > -	plane->modifier_count = format_modifier_count;
> > > -	plane->modifiers = kmalloc_array(format_modifier_count,
> > > +	plane->modifiers = kmalloc_array(in_modifier_count,
> > >  					 sizeof(format_modifiers[0]),
> > >  					 GFP_KERNEL);
> > >  
> > > -	if (format_modifier_count && !plane->modifiers) {
> > > +	if (in_modifier_count && !plane->modifiers) {
> > >  		DRM_DEBUG_KMS("out of memory when allocating plane\n");
> > >  		kfree(plane->format_types);
> > >  		drm_mode_object_unregister(dev, &plane->base);
> > >  		return -ENOMEM;
> > >  	}
> > >  
> > > +	for (i = 0, format_modifier_count = 0; i < in_modifier_count;
> > > i++) {
> > > +		int j;
> > > +
> > > +		for (j = 0; funcs->format_mod_supported && j <
> > > format_count; j++)
> > > +			if (funcs->format_mod_supported(plane,
> > > formats[j],
> > > +							format_modifier
> > > s[i]))
> > > +				break;
> > > +
> > > +		if (j < format_count)
> > > +			plane->modifiers[format_modifier_count++] =
> > > +				format_modifiers[i];
> > > +	}
> > > +
> > > +	if (format_modifier_count < in_modifier_count) {
> > > +		size_t size;
> > > +
> > > +		size = format_modifier_count *
> > > sizeof(format_modifiers[0]);
> > > +		plane->modifiers = krealloc(plane->modifiers, size,
> > > GFP_KERNEL);
> > 
> > Should check that the realloc actually succeeded.
> Didn't see a failure path for new size smaller than old, the return is
> the same pointer passed to krealloc().

I don't know if we want to rely on an implementation detail that
hevily. But that does raise the interesting point that trying to
shrink our memory footprint with krealloc() is futile. I suppose
there is still some kind of debugging benefit from the kasan
stuff.

> 
> > 
> > And I think we might want to give this same treatment to plane-
> > >formats[]
> > as well.
> > 
> > And perhaps we could even throw out plane->modifiers[] and just rely
> > on
> > the IN_FORMATS blob exclusively? Hmm. Looks like that is not getting
> > fully
> > populated unless the driver has provided .format_mod_supported(). Not
> > sure why that is, and not sure what userspace is supposed to do with
> > a
> > partially filled blob like that. I'm thinking we shouldn't even
> > attach
> > the property to the plane in that case.
> 
> Shouldn't it copy the modifier array into the blob and mark all formats
> as supported? drm_plane_check_pixel_format() seems to allow any valid
> format for a modifier in this case.

Yeah, I guess that might be the better approach.
Dhinakaran Pandiyan Nov. 6, 2018, 9:55 p.m. UTC | #4
On Tue, 2018-11-06 at 22:21 +0200, Ville Syrjälä wrote:
> On Tue, Nov 06, 2018 at 11:54:45AM -0800, Dhinakaran Pandiyan wrote:
> > On Tue, 2018-11-06 at 16:13 +0200, Ville Syrjälä wrote:
> > > On Mon, Nov 05, 2018 at 06:44:34PM -0800, Dhinakaran Pandiyan
> > > wrote:
> > > > Allows drivers to pass a larger modifier array, thereby
> > > > avoiding
> > > > declarations of static modifier arrays that are only slight
> > > > different
> > > > for each plane.
> > > > 
> > > > Cc: dri-devel@lists.freedesktop.org
> > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Signed-off-by: Dhinakaran Pandiyan <
> > > > dhinakaran.pandiyan@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/drm_plane.c | 35 +++++++++++++++++++++++++++
> > > > ----
> > > > ----
> > > >  1 file changed, 27 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/drm_plane.c
> > > > b/drivers/gpu/drm/drm_plane.c
> > > > index 1fa98bd12003..1546ffbf8e36 100644
> > > > --- a/drivers/gpu/drm/drm_plane.c
> > > > +++ b/drivers/gpu/drm/drm_plane.c
> > > > @@ -179,8 +179,8 @@ int drm_universal_plane_init(struct
> > > > drm_device
> > > > *dev, struct drm_plane *plane,
> > > >  			     const char *name, ...)
> > > >  {
> > > >  	struct drm_mode_config *config = &dev->mode_config;
> > > > -	unsigned int format_modifier_count = 0;
> > > > -	int ret;
> > > > +	unsigned int format_modifier_count, in_modifier_count =
> > > > 0;
> > > > +	int ret, i;
> > > >  
> > > >  	/* plane index is used with 32bit bitmasks */
> > > >  	if (WARN_ON(config->num_total_plane >= 32))
> > > > @@ -216,22 +216,43 @@ int drm_universal_plane_init(struct
> > > > drm_device *dev, struct drm_plane *plane,
> > > >  
> > > >  	if (format_modifiers) {
> > > >  		const uint64_t *temp_modifiers =
> > > > format_modifiers;
> > > > +
> > > >  		while (*temp_modifiers++ !=
> > > > DRM_FORMAT_MOD_INVALID)
> > > > -			format_modifier_count++;
> > > > +			in_modifier_count++;
> > > >  	}
> > > >  
> > > > -	plane->modifier_count = format_modifier_count;
> > > > -	plane->modifiers = kmalloc_array(format_modifier_count,
> > > > +	plane->modifiers = kmalloc_array(in_modifier_count,
> > > >  					 sizeof(format_modifier
> > > > s[0]),
> > > >  					 GFP_KERNEL);
> > > >  
> > > > -	if (format_modifier_count && !plane->modifiers) {
> > > > +	if (in_modifier_count && !plane->modifiers) {
> > > >  		DRM_DEBUG_KMS("out of memory when allocating
> > > > plane\n");
> > > >  		kfree(plane->format_types);
> > > >  		drm_mode_object_unregister(dev, &plane->base);
> > > >  		return -ENOMEM;
> > > >  	}
> > > >  
> > > > +	for (i = 0, format_modifier_count = 0; i <
> > > > in_modifier_count;
> > > > i++) {
> > > > +		int j;
> > > > +
> > > > +		for (j = 0; funcs->format_mod_supported && j <
> > > > format_count; j++)
> > > > +			if (funcs->format_mod_supported(plane,
> > > > formats[j],
> > > > +							format_
> > > > modifier
> > > > s[i]))
> > > > +				break;
> > > > +
> > > > +		if (j < format_count)
> > > > +			plane-
> > > > >modifiers[format_modifier_count++] =
> > > > +				format_modifiers[i];
> > > > +	}
> > > > +
> > > > +	if (format_modifier_count < in_modifier_count) {
> > > > +		size_t size;
> > > > +
> > > > +		size = format_modifier_count *
> > > > sizeof(format_modifiers[0]);
> > > > +		plane->modifiers = krealloc(plane->modifiers,
> > > > size,
> > > > GFP_KERNEL);
> > > 
> > > Should check that the realloc actually succeeded.
> > 
> > Didn't see a failure path for new size smaller than old, the return
> > is
> > the same pointer passed to krealloc().
> 
> I don't know if we want to rely on an implementation detail that
> hevily.
Fair enough.

>  But that does raise the interesting point that trying to
> shrink our memory footprint with krealloc() is futile. I suppose
> there is still some kind of debugging benefit from the kasan
> stuff.
> 
> > 
> > > 
> > > And I think we might want to give this same treatment to plane-
> > > > formats[]
> > > 
> > > as well.
> > > 
> > > And perhaps we could even throw out plane->modifiers[] and just
> > > rely
> > > on
> > > the IN_FORMATS blob exclusively? Hmm. Looks like that is not
> > > getting
> > > fully
> > > populated unless the driver has provided .format_mod_supported().
> > > Not
> > > sure why that is, and not sure what userspace is supposed to do
> > > with
> > > a
> > > partially filled blob like that. I'm thinking we shouldn't even
> > > attach
> > > the property to the plane in that case.
> > 
> > Shouldn't it copy the modifier array into the blob and mark all
> > formats
> > as supported? drm_plane_check_pixel_format() seems to allow any
> > valid
> > format for a modifier in this case.
> 
> Yeah, I guess that might be the better approach.
I'll go with approach in the next version.

-DK
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 1fa98bd12003..1546ffbf8e36 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -179,8 +179,8 @@  int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 			     const char *name, ...)
 {
 	struct drm_mode_config *config = &dev->mode_config;
-	unsigned int format_modifier_count = 0;
-	int ret;
+	unsigned int format_modifier_count, in_modifier_count = 0;
+	int ret, i;
 
 	/* plane index is used with 32bit bitmasks */
 	if (WARN_ON(config->num_total_plane >= 32))
@@ -216,22 +216,43 @@  int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	if (format_modifiers) {
 		const uint64_t *temp_modifiers = format_modifiers;
+
 		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
-			format_modifier_count++;
+			in_modifier_count++;
 	}
 
-	plane->modifier_count = format_modifier_count;
-	plane->modifiers = kmalloc_array(format_modifier_count,
+	plane->modifiers = kmalloc_array(in_modifier_count,
 					 sizeof(format_modifiers[0]),
 					 GFP_KERNEL);
 
-	if (format_modifier_count && !plane->modifiers) {
+	if (in_modifier_count && !plane->modifiers) {
 		DRM_DEBUG_KMS("out of memory when allocating plane\n");
 		kfree(plane->format_types);
 		drm_mode_object_unregister(dev, &plane->base);
 		return -ENOMEM;
 	}
 
+	for (i = 0, format_modifier_count = 0; i < in_modifier_count; i++) {
+		int j;
+
+		for (j = 0; funcs->format_mod_supported && j < format_count; j++)
+			if (funcs->format_mod_supported(plane, formats[j],
+							format_modifiers[i]))
+				break;
+
+		if (j < format_count)
+			plane->modifiers[format_modifier_count++] =
+				format_modifiers[i];
+	}
+
+	if (format_modifier_count < in_modifier_count) {
+		size_t size;
+
+		size = format_modifier_count * sizeof(format_modifiers[0]);
+		plane->modifiers = krealloc(plane->modifiers, size, GFP_KERNEL);
+	}
+	plane->modifier_count = format_modifier_count;
+
 	if (name) {
 		va_list ap;
 
@@ -251,8 +272,6 @@  int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
 	memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
 	plane->format_count = format_count;
-	memcpy(plane->modifiers, format_modifiers,
-	       format_modifier_count * sizeof(format_modifiers[0]));
 	plane->possible_crtcs = possible_crtcs;
 	plane->type = type;