Re: [PATCH v3 3/8] media: renesas: vsp1: Fix code checks in frame size enumeration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Laurent

On Fri, Jul 04, 2025 at 03:18:07AM +0300, Laurent Pinchart wrote:
> The media bus code passed to the .enum_frame_size() operation for the
> sink pad is required to be supported by the device, but not to match the
> current format. All entities that use the vsp1_subdev_enum_frame_size()
> helper, as well as the SRU and UDS entities that implement the operation
> manually, perform the check incorrectly.
>
> Fix the issue by implementing the correct code check in the
> vsp1_subdev_enum_frame_size(). For the SRU and UDS, to avoid duplicating
> code, use the vsp1_subdev_enum_frame_size() as a base and override the
> enumerated size on the source pad with entity-specific constraints.
>
> While at it, include the missing <linux/mutex.h> as the code locks
> mutexes.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx>
> ---
> Changes since v1:
>
> - Include <linux/cleanup.h> and <linux/mutex.h>
> ---
>  .../media/platform/renesas/vsp1/vsp1_entity.c | 49 ++++++++++++-------
>  .../media/platform/renesas/vsp1/vsp1_sru.c    | 38 +++++++-------
>  .../media/platform/renesas/vsp1/vsp1_uds.c    | 38 +++++++-------
>  3 files changed, 64 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_entity.c b/drivers/media/platform/renesas/vsp1/vsp1_entity.c
> index 04b7ae6fb935..892a2adfdf3a 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_entity.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_entity.c
> @@ -7,8 +7,10 @@
>   * Contact: Laurent Pinchart (laurent.pinchart@xxxxxxxxxxxxxxxx)
>   */
>
> +#include <linux/cleanup.h>
>  #include <linux/device.h>
>  #include <linux/gfp.h>
> +#include <linux/mutex.h>
>
>  #include <media/media-entity.h>
>  #include <media/v4l2-ctrls.h>
> @@ -238,42 +240,51 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,
>  				struct v4l2_subdev_frame_size_enum *fse)
>  {
>  	struct vsp1_entity *entity = to_vsp1_entity(subdev);
> -	struct v4l2_subdev_state *state;
> -	struct v4l2_mbus_framefmt *format;
> -	int ret = 0;
>
> -	state = vsp1_entity_get_state(entity, sd_state, fse->which);
> -	if (!state)
> +	if (fse->index)
>  		return -EINVAL;
>
> -	format = v4l2_subdev_state_get_format(state, fse->pad);
> -
> -	mutex_lock(&entity->lock);
> -
> -	if (fse->index || fse->code != format->code) {
> -		ret = -EINVAL;
> -		goto done;
> -	}
> -
>  	if (fse->pad == 0) {
> +		unsigned int i;
> +
> +		for (i = 0; i < entity->num_codes; ++i) {
> +			if (fse->code == entity->codes[i])
> +				break;
> +		}
> +
> +		if (i == entity->num_codes)
> +			return -EINVAL;
> +
>  		fse->min_width = entity->min_width;
>  		fse->max_width = entity->max_width;
>  		fse->min_height = entity->min_height;
>  		fse->max_height = entity->max_height;
>  	} else {
> +		struct v4l2_subdev_state *state;
> +		struct v4l2_mbus_framefmt *format;
> +
> +		state = vsp1_entity_get_state(entity, sd_state, fse->which);
> +		if (!state)
> +			return -EINVAL;
> +
>  		/*
> -		 * The size on the source pad are fixed and always identical to
> -		 * the size on the sink pad.
> +		 * The media bus code and size on the source pad are fixed and
> +		 * always identical to the sink pad.
>  		 */
> +		format = v4l2_subdev_state_get_format(state, 0);
> +
> +		guard(mutex)(&entity->lock);
> +
> +		if (fse->code != format->code)
> +			return -EINVAL;
> +
>  		fse->min_width = format->width;
>  		fse->max_width = format->width;
>  		fse->min_height = format->height;
>  		fse->max_height = format->height;
>  	}
>
> -done:
> -	mutex_unlock(&entity->lock);
> -	return ret;
> +	return 0;
>  }
>
>  /*
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_sru.c b/drivers/media/platform/renesas/vsp1/vsp1_sru.c
> index 1dc34e6a510d..37fd36d09045 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_sru.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_sru.c
> @@ -7,8 +7,10 @@
>   * Contact: Laurent Pinchart (laurent.pinchart@xxxxxxxxxxxxxxxx)
>   */
>
> +#include <linux/cleanup.h>
>  #include <linux/device.h>
>  #include <linux/gfp.h>
> +#include <linux/mutex.h>
>
>  #include <media/v4l2-subdev.h>
>
> @@ -116,29 +118,25 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
>  			       struct v4l2_subdev_frame_size_enum *fse)
>  {
>  	struct vsp1_sru *sru = to_sru(subdev);
> -	struct v4l2_subdev_state *state;
> -	struct v4l2_mbus_framefmt *format;
> -	int ret = 0;
> +	int ret;
>
> -	state = vsp1_entity_get_state(&sru->entity, sd_state, fse->which);
> -	if (!state)
> -		return -EINVAL;
> +	ret = vsp1_subdev_enum_frame_size(subdev, sd_state, fse);
> +	if (ret)
> +		return ret;

Here, in case of PAD_SOURCE, we have validated that the fse->code
matches the format on the sink

>
> -	format = v4l2_subdev_state_get_format(state, SRU_PAD_SINK);
> +	if (fse->pad == SRU_PAD_SOURCE) {
> +		struct v4l2_subdev_state *state;
> +		struct v4l2_mbus_framefmt *format;
>
> -	mutex_lock(&sru->entity.lock);
> +		state = vsp1_entity_get_state(&sru->entity, sd_state,
> +					      fse->which);
> +		if (!state)
> +			return -EINVAL;
>
> -	if (fse->index || fse->code != format->code) {
> -		ret = -EINVAL;
> -		goto done;
> -	}
> +		format = v4l2_subdev_state_get_format(state, SRU_PAD_SINK);
> +
> +		guard(mutex)(&sru->entity.lock);

and we get here where we do SRU-specific adjustments to the sizes but
we don't re-check for the code.

Can the code on the sink change between the above call to
vsp1_subdev_enum_frame_size() and here ? Is this a concern ?

Same for UDS I guess..

Thanks
  j

>
> -	if (fse->pad == SRU_PAD_SINK) {
> -		fse->min_width = SRU_MIN_SIZE;
> -		fse->max_width = SRU_MAX_SIZE;
> -		fse->min_height = SRU_MIN_SIZE;
> -		fse->max_height = SRU_MAX_SIZE;
> -	} else {
>  		fse->min_width = format->width;
>  		fse->min_height = format->height;
>  		if (format->width <= SRU_MAX_SIZE / 2 &&
> @@ -151,9 +149,7 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
>  		}
>  	}
>
> -done:
> -	mutex_unlock(&sru->entity.lock);
> -	return ret;
> +	return 0;
>  }
>
>  static void sru_try_format(struct vsp1_sru *sru,
> diff --git a/drivers/media/platform/renesas/vsp1/vsp1_uds.c b/drivers/media/platform/renesas/vsp1/vsp1_uds.c
> index 8006d49ffbea..dd4722315c56 100644
> --- a/drivers/media/platform/renesas/vsp1/vsp1_uds.c
> +++ b/drivers/media/platform/renesas/vsp1/vsp1_uds.c
> @@ -7,8 +7,10 @@
>   * Contact: Laurent Pinchart (laurent.pinchart@xxxxxxxxxxxxxxxx)
>   */
>
> +#include <linux/cleanup.h>
>  #include <linux/device.h>
>  #include <linux/gfp.h>
> +#include <linux/mutex.h>
>
>  #include <media/v4l2-subdev.h>
>
> @@ -121,38 +123,32 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev,
>  			       struct v4l2_subdev_frame_size_enum *fse)
>  {
>  	struct vsp1_uds *uds = to_uds(subdev);
> -	struct v4l2_subdev_state *state;
> -	struct v4l2_mbus_framefmt *format;
> -	int ret = 0;
> +	int ret;
>
> -	state = vsp1_entity_get_state(&uds->entity, sd_state, fse->which);
> -	if (!state)
> -		return -EINVAL;
> +	ret = vsp1_subdev_enum_frame_size(subdev, sd_state, fse);
> +	if (ret)
> +		return ret;
>
> -	format = v4l2_subdev_state_get_format(state, UDS_PAD_SINK);
> +	if (fse->pad == UDS_PAD_SOURCE) {
> +		struct v4l2_subdev_state *state;
> +		struct v4l2_mbus_framefmt *format;
>
> -	mutex_lock(&uds->entity.lock);
> +		state = vsp1_entity_get_state(&uds->entity, sd_state,
> +					      fse->which);
> +		if (!state)
> +			return -EINVAL;
>
> -	if (fse->index || fse->code != format->code) {
> -		ret = -EINVAL;
> -		goto done;
> -	}
> +		format = v4l2_subdev_state_get_format(state, UDS_PAD_SINK);
> +
> +		guard(mutex)(&uds->entity.lock);
>
> -	if (fse->pad == UDS_PAD_SINK) {
> -		fse->min_width = UDS_MIN_SIZE;
> -		fse->max_width = UDS_MAX_SIZE;
> -		fse->min_height = UDS_MIN_SIZE;
> -		fse->max_height = UDS_MAX_SIZE;
> -	} else {
>  		uds_output_limits(format->width, &fse->min_width,
>  				  &fse->max_width);
>  		uds_output_limits(format->height, &fse->min_height,
>  				  &fse->max_height);
>  	}
>
> -done:
> -	mutex_unlock(&uds->entity.lock);
> -	return ret;
> +	return 0;
>  }
>
>  static void uds_try_format(struct vsp1_uds *uds,
> --
> Regards,
>
> Laurent Pinchart
>
>




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux