mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 17:51:43 +00:00
[media] m5mols: Protect driver data with a mutex
Without the locking the driver's data could get corrupted when the subdev is accessed from user space and from host driver by multiple processes. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
05fb4da441
commit
5565a2ad47
@ -155,8 +155,6 @@ struct m5mols_version {
|
||||
* @pdata: platform data
|
||||
* @sd: v4l-subdev instance
|
||||
* @pad: media pad
|
||||
* @ffmt: current fmt according to resolution type
|
||||
* @res_type: current resolution type
|
||||
* @irq_waitq: waitqueue for the capture
|
||||
* @irq_done: set to 1 in the interrupt handler
|
||||
* @handle: control handler
|
||||
@ -174,6 +172,10 @@ struct m5mols_version {
|
||||
* @wdr: wide dynamic range control
|
||||
* @stabilization: image stabilization control
|
||||
* @jpeg_quality: JPEG compression quality control
|
||||
* @set_power: optional power callback to the board code
|
||||
* @lock: mutex protecting the structure fields below
|
||||
* @ffmt: current fmt according to resolution type
|
||||
* @res_type: current resolution type
|
||||
* @ver: information of the version
|
||||
* @cap: the capture mode attributes
|
||||
* @isp_ready: 1 when the ISP controller has completed booting
|
||||
@ -181,14 +183,11 @@ struct m5mols_version {
|
||||
* @ctrl_sync: 1 when the control handler state is restored in H/W
|
||||
* @resolution: register value for current resolution
|
||||
* @mode: register value for current operation mode
|
||||
* @set_power: optional power callback to the board code
|
||||
*/
|
||||
struct m5mols_info {
|
||||
const struct m5mols_platform_data *pdata;
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pad;
|
||||
struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
|
||||
int res_type;
|
||||
|
||||
wait_queue_head_t irq_waitq;
|
||||
atomic_t irq_done;
|
||||
@ -216,6 +215,13 @@ struct m5mols_info {
|
||||
struct v4l2_ctrl *stabilization;
|
||||
struct v4l2_ctrl *jpeg_quality;
|
||||
|
||||
int (*set_power)(struct device *dev, int on);
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
|
||||
int res_type;
|
||||
|
||||
struct m5mols_version ver;
|
||||
struct m5mols_capture cap;
|
||||
|
||||
@ -225,8 +231,6 @@ struct m5mols_info {
|
||||
|
||||
u8 resolution;
|
||||
u8 mode;
|
||||
|
||||
int (*set_power)(struct device *dev, int on);
|
||||
};
|
||||
|
||||
#define is_available_af(__info) (__info->ver.af)
|
||||
|
@ -551,13 +551,18 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
{
|
||||
struct m5mols_info *info = to_m5mols(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
format = __find_format(info, fh, fmt->which, info->res_type);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
fmt->format = *format;
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
fmt->format = *format;
|
||||
return 0;
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
@ -578,6 +583,7 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
if (!sfmt)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
format->code = m5mols_default_ffmt[type].code;
|
||||
format->colorspace = V4L2_COLORSPACE_JPEG;
|
||||
@ -589,7 +595,8 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
info->res_type = type;
|
||||
}
|
||||
|
||||
return 0;
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
@ -661,20 +668,25 @@ static int m5mols_start_monitor(struct m5mols_info *info)
|
||||
static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct m5mols_info *info = to_m5mols(sd);
|
||||
u32 code = info->ffmt[info->res_type].code;
|
||||
u32 code;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
code = info->ffmt[info->res_type].code;
|
||||
|
||||
if (enable) {
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (is_code(code, M5MOLS_RESTYPE_MONITOR))
|
||||
ret = m5mols_start_monitor(info);
|
||||
if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
|
||||
ret = m5mols_start_capture(info);
|
||||
|
||||
return ret;
|
||||
else
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = m5mols_set_mode(info, REG_PARAMETER);
|
||||
}
|
||||
|
||||
return m5mols_set_mode(info, REG_PARAMETER);
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_video_ops m5mols_video_ops = {
|
||||
@ -773,6 +785,20 @@ static int m5mols_fw_start(struct v4l2_subdev *sd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Execute the lens soft-landing algorithm */
|
||||
static int m5mols_auto_focus_stop(struct m5mols_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
|
||||
if (!ret)
|
||||
ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF);
|
||||
if (!ret)
|
||||
ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE,
|
||||
0xff, -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* m5mols_s_power - Main sensor power control function
|
||||
*
|
||||
@ -785,29 +811,26 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
|
||||
struct m5mols_info *info = to_m5mols(sd);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
if (on) {
|
||||
ret = m5mols_sensor_power(info, true);
|
||||
if (!ret)
|
||||
ret = m5mols_fw_start(sd);
|
||||
return ret;
|
||||
} else {
|
||||
if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
|
||||
ret = m5mols_set_mode(info, REG_MONITOR);
|
||||
if (!ret)
|
||||
ret = m5mols_auto_focus_stop(info);
|
||||
if (ret < 0)
|
||||
v4l2_warn(sd, "Soft landing lens failed\n");
|
||||
}
|
||||
ret = m5mols_sensor_power(info, false);
|
||||
|
||||
info->ctrl_sync = 0;
|
||||
}
|
||||
|
||||
if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
|
||||
ret = m5mols_set_mode(info, REG_MONITOR);
|
||||
if (!ret)
|
||||
ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP);
|
||||
if (!ret)
|
||||
ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
|
||||
if (!ret)
|
||||
ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
|
||||
0xff, -1);
|
||||
if (ret < 0)
|
||||
v4l2_warn(sd, "Soft landing lens failed\n");
|
||||
}
|
||||
|
||||
ret = m5mols_sensor_power(info, false);
|
||||
info->ctrl_sync = 0;
|
||||
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -912,6 +935,8 @@ static int __devinit m5mols_probe(struct i2c_client *client,
|
||||
sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
|
||||
|
||||
init_waitqueue_head(&info->irq_waitq);
|
||||
mutex_init(&info->lock);
|
||||
|
||||
ret = request_irq(client->irq, m5mols_irq_handler,
|
||||
IRQF_TRIGGER_RISING, MODULE_NAME, sd);
|
||||
if (ret) {
|
||||
|
Loading…
Reference in New Issue
Block a user