Hi Jacopo, On Tue, Apr 28, 2020 at 03:40:36PM +0200, Jacopo Mondi wrote: > On Mon, Apr 27, 2020 at 12:05:48AM +0300, Laurent Pinchart wrote: > > Hi Jacopo, > > > > Thank you for the patch. > > > > [snip] > > > > + > > > +static int imx219_get_selection(struct v4l2_subdev *sd, > > > + struct v4l2_subdev_pad_config *cfg, > > > + struct v4l2_subdev_selection *sel) > > > +{ > > > + struct imx219 *imx219 = to_imx219(sd); > > > + const struct v4l2_rect *__crop; > > > + > > > + if (sel->pad != 0) > > > + return -EINVAL; > > > + > > > + mutex_lock(&imx219->mutex); > > > + > > > + switch (sel->target) { > > > + case V4L2_SEL_TGT_NATIVE_SIZE: > > > + sel->r.top = 0; > > > + sel->r.left = 0; > > > + sel->r.width = IMX219_NATIVE_WIDTH; > > > + sel->r.height = IMX219_NATIVE_HEIGHT; > > > + mutex_unlock(&imx219->mutex); > > > + > > > + return 0; > > > + > > > + case V4L2_SEL_TGT_CROP_DEFAULT: > > > + sel->r.top = IMX219_PIXEL_ARRAY_TOP; > > > + sel->r.left = IMX219_PIXEL_ARRAY_LEFT; > > > + sel->r.width = IMX219_PIXEL_ARRAY_WIDTH; > > > + sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT; > > > + mutex_unlock(&imx219->mutex); > > > + > > > + return 0; > > > + > > > + case V4L2_SEL_TGT_CROP: > > > + __crop = __imx219_get_pad_crop(imx219, cfg, sel->pad, > > > + sel->which); > > > + sel->r = *__crop; > > > + mutex_unlock(&imx219->mutex); > > > > I should have thought about it before, but only this case requires > > locking. Maybe > > I should have thought it better, yes > > > > > __crop = __imx219_get_pad_crop(imx219, cfg, sel->pad, > > sel->which); > > mutex_lock(&imx219->mutex); > > Actually, retreiveing __crop should be protected too, as the crop > rectangle is part of the imx219->mode, which is updated by the set_fmt > operation. __crop is a pointer, retrieving the pointer doesn't need protection. Accessing its contents does. No big deal though, it's cheap, as long as we don't lock for the bounds and default cases. > I'll wrap the whole case content in a critical session. > > > sel->r = *__crop; > > mutex_unlock(&imx219->mutex); > > > > and removing the mutex_lock() at the beginning ? > > > > > + > > > + return 0; > > > + } > > > + > > > + mutex_unlock(&imx219->mutex); > > > + > > > + return -EINVAL; > > > +} > > > + > > > static int imx219_start_streaming(struct imx219 *imx219) > > > { > > > struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); > > > @@ -1152,6 +1248,7 @@ static const struct v4l2_subdev_pad_ops imx219_pad_ops = { > > > .enum_mbus_code = imx219_enum_mbus_code, > > > .get_fmt = imx219_get_pad_format, > > > .set_fmt = imx219_set_pad_format, > > > + .get_selection = imx219_get_selection, > > > .enum_frame_size = imx219_enum_frame_size, > > > }; > > > -- Regards, Laurent Pinchart