[media] pwc: Allow dqbuf / read to complete while waiting for controls
Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
6c9cac89c0
commit
c11271349a
|
@ -1160,6 +1160,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
pwc_construct(pdev); /* set min/max sizes correct */
|
pwc_construct(pdev); /* set min/max sizes correct */
|
||||||
|
|
||||||
mutex_init(&pdev->modlock);
|
mutex_init(&pdev->modlock);
|
||||||
|
mutex_init(&pdev->udevlock);
|
||||||
spin_lock_init(&pdev->queued_bufs_lock);
|
spin_lock_init(&pdev->queued_bufs_lock);
|
||||||
INIT_LIST_HEAD(&pdev->queued_bufs);
|
INIT_LIST_HEAD(&pdev->queued_bufs);
|
||||||
|
|
||||||
|
@ -1297,6 +1298,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
|
||||||
{
|
{
|
||||||
struct pwc_device *pdev = usb_get_intfdata(intf);
|
struct pwc_device *pdev = usb_get_intfdata(intf);
|
||||||
|
|
||||||
|
mutex_lock(&pdev->udevlock);
|
||||||
mutex_lock(&pdev->modlock);
|
mutex_lock(&pdev->modlock);
|
||||||
|
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
|
@ -1306,6 +1308,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
|
||||||
pdev->udev = NULL;
|
pdev->udev = NULL;
|
||||||
|
|
||||||
mutex_unlock(&pdev->modlock);
|
mutex_unlock(&pdev->modlock);
|
||||||
|
mutex_unlock(&pdev->udevlock);
|
||||||
|
|
||||||
pwc_remove_sysfs_files(pdev);
|
pwc_remove_sysfs_files(pdev);
|
||||||
video_unregister_device(&pdev->vdev);
|
video_unregister_device(&pdev->vdev);
|
||||||
|
|
|
@ -526,8 +526,24 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
container_of(ctrl->handler, struct pwc_device, ctrl_handler);
|
container_of(ctrl->handler, struct pwc_device, ctrl_handler);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!pdev->udev)
|
/*
|
||||||
return -ENODEV;
|
* Sometimes it can take quite long for the pwc to complete usb control
|
||||||
|
* transfers, so release the modlock to give streaming by another
|
||||||
|
* process / thread the chance to continue with a dqbuf.
|
||||||
|
*/
|
||||||
|
mutex_unlock(&pdev->modlock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take the udev-lock to protect against the disconnect handler
|
||||||
|
* completing and setting dev->udev to NULL underneath us. Other code
|
||||||
|
* does not need to do this since it is protected by the modlock.
|
||||||
|
*/
|
||||||
|
mutex_lock(&pdev->udevlock);
|
||||||
|
|
||||||
|
if (!pdev->udev) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case V4L2_CID_AUTO_WHITE_BALANCE:
|
case V4L2_CID_AUTO_WHITE_BALANCE:
|
||||||
|
@ -590,6 +606,9 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
if (ret)
|
if (ret)
|
||||||
PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
|
PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
mutex_unlock(&pdev->udevlock);
|
||||||
|
mutex_lock(&pdev->modlock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,8 +770,14 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
container_of(ctrl->handler, struct pwc_device, ctrl_handler);
|
container_of(ctrl->handler, struct pwc_device, ctrl_handler);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!pdev->udev)
|
/* See the comments on locking in pwc_g_volatile_ctrl */
|
||||||
return -ENODEV;
|
mutex_unlock(&pdev->modlock);
|
||||||
|
mutex_lock(&pdev->udevlock);
|
||||||
|
|
||||||
|
if (!pdev->udev) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case V4L2_CID_BRIGHTNESS:
|
case V4L2_CID_BRIGHTNESS:
|
||||||
|
@ -841,6 +866,9 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
if (ret)
|
if (ret)
|
||||||
PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
|
PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
mutex_unlock(&pdev->udevlock);
|
||||||
|
mutex_lock(&pdev->modlock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,9 @@ struct pwc_device
|
||||||
|
|
||||||
/* Pointer to our usb_device, may be NULL after unplug */
|
/* Pointer to our usb_device, may be NULL after unplug */
|
||||||
struct usb_device *udev;
|
struct usb_device *udev;
|
||||||
|
/* Protects the setting of udev to NULL by our disconnect handler */
|
||||||
|
struct mutex udevlock;
|
||||||
|
|
||||||
/* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
|
/* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
|
||||||
int type;
|
int type;
|
||||||
int release; /* release number */
|
int release; /* release number */
|
||||||
|
|
Loading…
Reference in New Issue