[media] cpia2: convert .ioctl to .unlocked_ioctl
Implement core-assisted locking in cpia2. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
9af39713fe
commit
d2db8fee0d
@ -378,7 +378,7 @@ struct cpia2_fh {
|
|||||||
|
|
||||||
struct camera_data {
|
struct camera_data {
|
||||||
/* locks */
|
/* locks */
|
||||||
struct mutex busy_lock; /* guard against SMP multithreading */
|
struct mutex v4l2_lock; /* serialize file operations */
|
||||||
struct v4l2_prio_state prio;
|
struct v4l2_prio_state prio;
|
||||||
|
|
||||||
/* camera status */
|
/* camera status */
|
||||||
|
@ -2247,7 +2247,7 @@ struct camera_data *cpia2_init_camera_struct(void)
|
|||||||
|
|
||||||
|
|
||||||
cam->present = 1;
|
cam->present = 1;
|
||||||
mutex_init(&cam->busy_lock);
|
mutex_init(&cam->v4l2_lock);
|
||||||
init_waitqueue_head(&cam->wq_stream);
|
init_waitqueue_head(&cam->wq_stream);
|
||||||
|
|
||||||
return cam;
|
return cam;
|
||||||
@ -2365,9 +2365,9 @@ long cpia2_read(struct camera_data *cam,
|
|||||||
char __user *buf, unsigned long count, int noblock)
|
char __user *buf, unsigned long count, int noblock)
|
||||||
{
|
{
|
||||||
struct framebuf *frame;
|
struct framebuf *frame;
|
||||||
if (!count) {
|
|
||||||
|
if (!count)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
ERR("%s: buffer NULL\n",__func__);
|
ERR("%s: buffer NULL\n",__func__);
|
||||||
@ -2379,17 +2379,12 @@ long cpia2_read(struct camera_data *cam,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make this _really_ smp and multithread-safe */
|
|
||||||
if (mutex_lock_interruptible(&cam->busy_lock))
|
|
||||||
return -ERESTARTSYS;
|
|
||||||
|
|
||||||
if (!cam->present) {
|
if (!cam->present) {
|
||||||
LOG("%s: camera removed\n",__func__);
|
LOG("%s: camera removed\n",__func__);
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return 0; /* EOF */
|
return 0; /* EOF */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!cam->streaming) {
|
if (!cam->streaming) {
|
||||||
/* Start streaming */
|
/* Start streaming */
|
||||||
cpia2_usb_stream_start(cam,
|
cpia2_usb_stream_start(cam,
|
||||||
cam->params.camera_state.stream_mode);
|
cam->params.camera_state.stream_mode);
|
||||||
@ -2398,42 +2393,31 @@ long cpia2_read(struct camera_data *cam,
|
|||||||
/* Copy cam->curbuff in case it changes while we're processing */
|
/* Copy cam->curbuff in case it changes while we're processing */
|
||||||
frame = cam->curbuff;
|
frame = cam->curbuff;
|
||||||
if (noblock && frame->status != FRAME_READY) {
|
if (noblock && frame->status != FRAME_READY) {
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(frame->status != FRAME_READY) {
|
if (frame->status != FRAME_READY) {
|
||||||
mutex_unlock(&cam->busy_lock);
|
mutex_unlock(&cam->v4l2_lock);
|
||||||
wait_event_interruptible(cam->wq_stream,
|
wait_event_interruptible(cam->wq_stream,
|
||||||
!cam->present ||
|
!cam->present ||
|
||||||
(frame = cam->curbuff)->status == FRAME_READY);
|
(frame = cam->curbuff)->status == FRAME_READY);
|
||||||
|
mutex_lock(&cam->v4l2_lock);
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
/* make this _really_ smp and multithread-safe */
|
if (!cam->present)
|
||||||
if (mutex_lock_interruptible(&cam->busy_lock)) {
|
|
||||||
return -ERESTARTSYS;
|
|
||||||
}
|
|
||||||
if(!cam->present) {
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy data to user space */
|
/* copy data to user space */
|
||||||
if (frame->length > count) {
|
if (frame->length > count)
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
if (copy_to_user(buf, frame->data, frame->length))
|
||||||
if (copy_to_user(buf, frame->data, frame->length)) {
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
count = frame->length;
|
count = frame->length;
|
||||||
|
|
||||||
frame->status = FRAME_EMPTY;
|
frame->status = FRAME_EMPTY;
|
||||||
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2447,17 +2431,13 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
|
|||||||
{
|
{
|
||||||
unsigned int status=0;
|
unsigned int status=0;
|
||||||
|
|
||||||
if(!cam) {
|
if (!cam) {
|
||||||
ERR("%s: Internal error, camera_data not found!\n",__func__);
|
ERR("%s: Internal error, camera_data not found!\n",__func__);
|
||||||
return POLLERR;
|
return POLLERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&cam->busy_lock);
|
if (!cam->present)
|
||||||
|
|
||||||
if(!cam->present) {
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return POLLHUP;
|
return POLLHUP;
|
||||||
}
|
|
||||||
|
|
||||||
if(!cam->streaming) {
|
if(!cam->streaming) {
|
||||||
/* Start streaming */
|
/* Start streaming */
|
||||||
@ -2465,16 +2445,13 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
|
|||||||
cam->params.camera_state.stream_mode);
|
cam->params.camera_state.stream_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
poll_wait(filp, &cam->wq_stream, wait);
|
poll_wait(filp, &cam->wq_stream, wait);
|
||||||
mutex_lock(&cam->busy_lock);
|
|
||||||
|
|
||||||
if(!cam->present)
|
if(!cam->present)
|
||||||
status = POLLHUP;
|
status = POLLHUP;
|
||||||
else if(cam->curbuff->status == FRAME_READY)
|
else if(cam->curbuff->status == FRAME_READY)
|
||||||
status = POLLIN | POLLRDNORM;
|
status = POLLIN | POLLRDNORM;
|
||||||
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2496,29 +2473,19 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
|
|||||||
|
|
||||||
DBG("mmap offset:%ld size:%ld\n", start_offset, size);
|
DBG("mmap offset:%ld size:%ld\n", start_offset, size);
|
||||||
|
|
||||||
/* make this _really_ smp-safe */
|
if (!cam->present)
|
||||||
if (mutex_lock_interruptible(&cam->busy_lock))
|
|
||||||
return -ERESTARTSYS;
|
|
||||||
|
|
||||||
if (!cam->present) {
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
|
|
||||||
if (size > cam->frame_size*cam->num_frames ||
|
if (size > cam->frame_size*cam->num_frames ||
|
||||||
(start_offset % cam->frame_size) != 0 ||
|
(start_offset % cam->frame_size) != 0 ||
|
||||||
(start_offset+size > cam->frame_size*cam->num_frames)) {
|
(start_offset+size > cam->frame_size*cam->num_frames))
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
pos = ((unsigned long) (cam->frame_buffer)) + start_offset;
|
pos = ((unsigned long) (cam->frame_buffer)) + start_offset;
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
page = kvirt_to_pa(pos);
|
page = kvirt_to_pa(pos);
|
||||||
if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) {
|
if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED))
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
|
||||||
start += PAGE_SIZE;
|
start += PAGE_SIZE;
|
||||||
pos += PAGE_SIZE;
|
pos += PAGE_SIZE;
|
||||||
if (size > PAGE_SIZE)
|
if (size > PAGE_SIZE)
|
||||||
@ -2528,7 +2495,5 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cam->mmapped = true;
|
cam->mmapped = true;
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,59 +238,40 @@ static struct v4l2_queryctrl controls[] = {
|
|||||||
static int cpia2_open(struct file *file)
|
static int cpia2_open(struct file *file)
|
||||||
{
|
{
|
||||||
struct camera_data *cam = video_drvdata(file);
|
struct camera_data *cam = video_drvdata(file);
|
||||||
int retval = 0;
|
struct cpia2_fh *fh;
|
||||||
|
|
||||||
if (!cam) {
|
if (!cam) {
|
||||||
ERR("Internal error, camera_data not found!\n");
|
ERR("Internal error, camera_data not found!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mutex_lock_interruptible(&cam->busy_lock))
|
if (!cam->present)
|
||||||
return -ERESTARTSYS;
|
return -ENODEV;
|
||||||
|
|
||||||
if(!cam->present) {
|
if (cam->open_count == 0) {
|
||||||
retval = -ENODEV;
|
if (cpia2_allocate_buffers(cam))
|
||||||
goto err_return;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* reset the camera */
|
||||||
|
if (cpia2_reset_camera(cam) < 0)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
cam->APP_len = 0;
|
||||||
|
cam->COM_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cam->open_count > 0) {
|
fh = kmalloc(sizeof(*fh), GFP_KERNEL);
|
||||||
goto skip_init;
|
if (!fh)
|
||||||
}
|
return -ENOMEM;
|
||||||
|
file->private_data = fh;
|
||||||
if (cpia2_allocate_buffers(cam)) {
|
fh->prio = V4L2_PRIORITY_UNSET;
|
||||||
retval = -ENOMEM;
|
v4l2_prio_open(&cam->prio, &fh->prio);
|
||||||
goto err_return;
|
fh->mmapped = 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the camera */
|
|
||||||
if (cpia2_reset_camera(cam) < 0) {
|
|
||||||
retval = -EIO;
|
|
||||||
goto err_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cam->APP_len = 0;
|
|
||||||
cam->COM_len = 0;
|
|
||||||
|
|
||||||
skip_init:
|
|
||||||
{
|
|
||||||
struct cpia2_fh *fh = kmalloc(sizeof(*fh),GFP_KERNEL);
|
|
||||||
if(!fh) {
|
|
||||||
retval = -ENOMEM;
|
|
||||||
goto err_return;
|
|
||||||
}
|
|
||||||
file->private_data = fh;
|
|
||||||
fh->prio = V4L2_PRIORITY_UNSET;
|
|
||||||
v4l2_prio_open(&cam->prio, &fh->prio);
|
|
||||||
fh->mmapped = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
++cam->open_count;
|
++cam->open_count;
|
||||||
|
|
||||||
cpia2_dbg_dump_registers(cam);
|
cpia2_dbg_dump_registers(cam);
|
||||||
|
return 0;
|
||||||
err_return:
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@ -304,15 +285,11 @@ static int cpia2_close(struct file *file)
|
|||||||
struct camera_data *cam = video_get_drvdata(dev);
|
struct camera_data *cam = video_get_drvdata(dev);
|
||||||
struct cpia2_fh *fh = file->private_data;
|
struct cpia2_fh *fh = file->private_data;
|
||||||
|
|
||||||
mutex_lock(&cam->busy_lock);
|
|
||||||
|
|
||||||
if (cam->present &&
|
if (cam->present &&
|
||||||
(cam->open_count == 1
|
(cam->open_count == 1 || fh->prio == V4L2_PRIORITY_RECORD)) {
|
||||||
|| fh->prio == V4L2_PRIORITY_RECORD
|
|
||||||
)) {
|
|
||||||
cpia2_usb_stream_stop(cam);
|
cpia2_usb_stream_stop(cam);
|
||||||
|
|
||||||
if(cam->open_count == 1) {
|
if (cam->open_count == 1) {
|
||||||
/* save camera state for later open */
|
/* save camera state for later open */
|
||||||
cpia2_save_camera_state(cam);
|
cpia2_save_camera_state(cam);
|
||||||
|
|
||||||
@ -321,26 +298,21 @@ static int cpia2_close(struct file *file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (fh->mmapped)
|
||||||
if(fh->mmapped)
|
cam->mmapped = 0;
|
||||||
cam->mmapped = 0;
|
v4l2_prio_close(&cam->prio, fh->prio);
|
||||||
v4l2_prio_close(&cam->prio, fh->prio);
|
file->private_data = NULL;
|
||||||
file->private_data = NULL;
|
kfree(fh);
|
||||||
kfree(fh);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (--cam->open_count == 0) {
|
if (--cam->open_count == 0) {
|
||||||
cpia2_free_buffers(cam);
|
cpia2_free_buffers(cam);
|
||||||
if (!cam->present) {
|
if (!cam->present) {
|
||||||
video_unregister_device(dev);
|
video_unregister_device(dev);
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
kfree(cam);
|
kfree(cam);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,11 +377,11 @@ static int sync(struct camera_data *cam, int frame_nr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
mutex_unlock(&cam->v4l2_lock);
|
||||||
wait_event_interruptible(cam->wq_stream,
|
wait_event_interruptible(cam->wq_stream,
|
||||||
!cam->streaming ||
|
!cam->streaming ||
|
||||||
frame->status == FRAME_READY);
|
frame->status == FRAME_READY);
|
||||||
mutex_lock(&cam->busy_lock);
|
mutex_lock(&cam->v4l2_lock);
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
if(!cam->present)
|
if(!cam->present)
|
||||||
@ -1293,11 +1265,11 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
|
|||||||
if(frame < 0) {
|
if(frame < 0) {
|
||||||
/* Wait for a frame to become available */
|
/* Wait for a frame to become available */
|
||||||
struct framebuf *cb=cam->curbuff;
|
struct framebuf *cb=cam->curbuff;
|
||||||
mutex_unlock(&cam->busy_lock);
|
mutex_unlock(&cam->v4l2_lock);
|
||||||
wait_event_interruptible(cam->wq_stream,
|
wait_event_interruptible(cam->wq_stream,
|
||||||
!cam->present ||
|
!cam->present ||
|
||||||
(cb=cam->curbuff)->status == FRAME_READY);
|
(cb=cam->curbuff)->status == FRAME_READY);
|
||||||
mutex_lock(&cam->busy_lock);
|
mutex_lock(&cam->v4l2_lock);
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
if(!cam->present)
|
if(!cam->present)
|
||||||
@ -1337,14 +1309,8 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
|||||||
if (!cam)
|
if (!cam)
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
|
|
||||||
/* make this _really_ smp-safe */
|
if (!cam->present)
|
||||||
if (mutex_lock_interruptible(&cam->busy_lock))
|
|
||||||
return -ERESTARTSYS;
|
|
||||||
|
|
||||||
if (!cam->present) {
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
|
|
||||||
/* Priority check */
|
/* Priority check */
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
@ -1352,10 +1318,8 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
|||||||
{
|
{
|
||||||
struct cpia2_fh *fh = file->private_data;
|
struct cpia2_fh *fh = file->private_data;
|
||||||
retval = v4l2_prio_check(&cam->prio, fh->prio);
|
retval = v4l2_prio_check(&cam->prio, fh->prio);
|
||||||
if(retval) {
|
if (retval)
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1529,7 +1493,6 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&cam->busy_lock);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1596,7 +1559,7 @@ static const struct v4l2_file_operations cpia2_fops = {
|
|||||||
.release = cpia2_close,
|
.release = cpia2_close,
|
||||||
.read = cpia2_v4l_read,
|
.read = cpia2_v4l_read,
|
||||||
.poll = cpia2_v4l_poll,
|
.poll = cpia2_v4l_poll,
|
||||||
.ioctl = cpia2_ioctl,
|
.unlocked_ioctl = cpia2_ioctl,
|
||||||
.mmap = cpia2_mmap,
|
.mmap = cpia2_mmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1620,6 +1583,7 @@ int cpia2_register_camera(struct camera_data *cam)
|
|||||||
|
|
||||||
memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template));
|
memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template));
|
||||||
video_set_drvdata(cam->vdev, cam);
|
video_set_drvdata(cam->vdev, cam);
|
||||||
|
cam->vdev->lock = &cam->v4l2_lock;
|
||||||
|
|
||||||
reset_camera_struct_v4l(cam);
|
reset_camera_struct_v4l(cam);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user