diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-05-06 08:28:27 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-14 08:31:03 -0400 |
commit | a3d6e8cc0e6ddc8b3cfdeb3c979f07ed1aa528b3 (patch) | |
tree | 60e69fcac849b505328e5755ee71195d0bc6728b /drivers/media/video/gspca/gspca.c | |
parent | 254902b01d2acc6aced99ec17caa4c6cd890cdea (diff) |
[media] gspca: Switch to V4L2 core locking, except for the buffer queuing ioctls
Due to latency concerns the VIDIOC_QBUF, DQBUF and QUERYBUF do not use the
core lock, instead they rely only on queue_lock.
Changes by HdG:
1) Change release from the video_device to the v4l2_device, to avoid a
race on disconnect.
2) Adjust for the V4L2 core changes which cause non ioctl fops to no longer
take the V4L2 core lock.
[mchehab@redhat.com: fix a merge conflict]
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 257 |
1 files changed, 76 insertions, 181 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index a14c8f71d48b..2687e76b0fb8 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -850,14 +850,6 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
850 | struct ep_tb_s ep_tb[MAX_ALT]; | 850 | struct ep_tb_s ep_tb[MAX_ALT]; |
851 | int n, ret, xfer, alt, alt_idx; | 851 | int n, ret, xfer, alt, alt_idx; |
852 | 852 | ||
853 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
854 | return -ERESTARTSYS; | ||
855 | |||
856 | if (!gspca_dev->present) { | ||
857 | ret = -ENODEV; | ||
858 | goto unlock; | ||
859 | } | ||
860 | |||
861 | /* reset the streaming variables */ | 853 | /* reset the streaming variables */ |
862 | gspca_dev->image = NULL; | 854 | gspca_dev->image = NULL; |
863 | gspca_dev->image_len = 0; | 855 | gspca_dev->image_len = 0; |
@@ -872,7 +864,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
872 | if (gspca_dev->sd_desc->isoc_init) { | 864 | if (gspca_dev->sd_desc->isoc_init) { |
873 | ret = gspca_dev->sd_desc->isoc_init(gspca_dev); | 865 | ret = gspca_dev->sd_desc->isoc_init(gspca_dev); |
874 | if (ret < 0) | 866 | if (ret < 0) |
875 | goto unlock; | 867 | return ret; |
876 | } | 868 | } |
877 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK | 869 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK |
878 | : USB_ENDPOINT_XFER_ISOC; | 870 | : USB_ENDPOINT_XFER_ISOC; |
@@ -883,8 +875,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
883 | ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer); | 875 | ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer); |
884 | if (ep == NULL) { | 876 | if (ep == NULL) { |
885 | pr_err("bad altsetting %d\n", gspca_dev->alt); | 877 | pr_err("bad altsetting %d\n", gspca_dev->alt); |
886 | ret = -EIO; | 878 | return -EIO; |
887 | goto out; | ||
888 | } | 879 | } |
889 | ep_tb[0].alt = gspca_dev->alt; | 880 | ep_tb[0].alt = gspca_dev->alt; |
890 | alt_idx = 1; | 881 | alt_idx = 1; |
@@ -895,8 +886,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
895 | alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb); | 886 | alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb); |
896 | if (alt_idx <= 0) { | 887 | if (alt_idx <= 0) { |
897 | pr_err("no transfer endpoint found\n"); | 888 | pr_err("no transfer endpoint found\n"); |
898 | ret = -EIO; | 889 | return -EIO; |
899 | goto unlock; | ||
900 | } | 890 | } |
901 | } | 891 | } |
902 | 892 | ||
@@ -991,8 +981,6 @@ retry: | |||
991 | } | 981 | } |
992 | out: | 982 | out: |
993 | gspca_input_create_urb(gspca_dev); | 983 | gspca_input_create_urb(gspca_dev); |
994 | unlock: | ||
995 | mutex_unlock(&gspca_dev->usb_lock); | ||
996 | return ret; | 984 | return ret; |
997 | } | 985 | } |
998 | 986 | ||
@@ -1062,7 +1050,6 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev, | |||
1062 | static int vidioc_g_register(struct file *file, void *priv, | 1050 | static int vidioc_g_register(struct file *file, void *priv, |
1063 | struct v4l2_dbg_register *reg) | 1051 | struct v4l2_dbg_register *reg) |
1064 | { | 1052 | { |
1065 | int ret; | ||
1066 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1053 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1067 | 1054 | ||
1068 | if (!gspca_dev->sd_desc->get_chip_ident) | 1055 | if (!gspca_dev->sd_desc->get_chip_ident) |
@@ -1071,22 +1058,13 @@ static int vidioc_g_register(struct file *file, void *priv, | |||
1071 | if (!gspca_dev->sd_desc->get_register) | 1058 | if (!gspca_dev->sd_desc->get_register) |
1072 | return -ENOTTY; | 1059 | return -ENOTTY; |
1073 | 1060 | ||
1074 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1075 | return -ERESTARTSYS; | ||
1076 | gspca_dev->usb_err = 0; | 1061 | gspca_dev->usb_err = 0; |
1077 | if (gspca_dev->present) | 1062 | return gspca_dev->sd_desc->get_register(gspca_dev, reg); |
1078 | ret = gspca_dev->sd_desc->get_register(gspca_dev, reg); | ||
1079 | else | ||
1080 | ret = -ENODEV; | ||
1081 | mutex_unlock(&gspca_dev->usb_lock); | ||
1082 | |||
1083 | return ret; | ||
1084 | } | 1063 | } |
1085 | 1064 | ||
1086 | static int vidioc_s_register(struct file *file, void *priv, | 1065 | static int vidioc_s_register(struct file *file, void *priv, |
1087 | struct v4l2_dbg_register *reg) | 1066 | struct v4l2_dbg_register *reg) |
1088 | { | 1067 | { |
1089 | int ret; | ||
1090 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1068 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1091 | 1069 | ||
1092 | if (!gspca_dev->sd_desc->get_chip_ident) | 1070 | if (!gspca_dev->sd_desc->get_chip_ident) |
@@ -1095,38 +1073,21 @@ static int vidioc_s_register(struct file *file, void *priv, | |||
1095 | if (!gspca_dev->sd_desc->set_register) | 1073 | if (!gspca_dev->sd_desc->set_register) |
1096 | return -ENOTTY; | 1074 | return -ENOTTY; |
1097 | 1075 | ||
1098 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1099 | return -ERESTARTSYS; | ||
1100 | gspca_dev->usb_err = 0; | 1076 | gspca_dev->usb_err = 0; |
1101 | if (gspca_dev->present) | 1077 | return gspca_dev->sd_desc->set_register(gspca_dev, reg); |
1102 | ret = gspca_dev->sd_desc->set_register(gspca_dev, reg); | ||
1103 | else | ||
1104 | ret = -ENODEV; | ||
1105 | mutex_unlock(&gspca_dev->usb_lock); | ||
1106 | |||
1107 | return ret; | ||
1108 | } | 1078 | } |
1109 | #endif | 1079 | #endif |
1110 | 1080 | ||
1111 | static int vidioc_g_chip_ident(struct file *file, void *priv, | 1081 | static int vidioc_g_chip_ident(struct file *file, void *priv, |
1112 | struct v4l2_dbg_chip_ident *chip) | 1082 | struct v4l2_dbg_chip_ident *chip) |
1113 | { | 1083 | { |
1114 | int ret; | ||
1115 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1084 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1116 | 1085 | ||
1117 | if (!gspca_dev->sd_desc->get_chip_ident) | 1086 | if (!gspca_dev->sd_desc->get_chip_ident) |
1118 | return -ENOTTY; | 1087 | return -ENOTTY; |
1119 | 1088 | ||
1120 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1121 | return -ERESTARTSYS; | ||
1122 | gspca_dev->usb_err = 0; | 1089 | gspca_dev->usb_err = 0; |
1123 | if (gspca_dev->present) | 1090 | return gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); |
1124 | ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); | ||
1125 | else | ||
1126 | ret = -ENODEV; | ||
1127 | mutex_unlock(&gspca_dev->usb_lock); | ||
1128 | |||
1129 | return ret; | ||
1130 | } | 1091 | } |
1131 | 1092 | ||
1132 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 1093 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
@@ -1321,9 +1282,10 @@ static int vidioc_enum_frameintervals(struct file *filp, void *priv, | |||
1321 | return -EINVAL; | 1282 | return -EINVAL; |
1322 | } | 1283 | } |
1323 | 1284 | ||
1324 | static void gspca_release(struct video_device *vfd) | 1285 | static void gspca_release(struct v4l2_device *v4l2_device) |
1325 | { | 1286 | { |
1326 | struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); | 1287 | struct gspca_dev *gspca_dev = |
1288 | container_of(v4l2_device, struct gspca_dev, v4l2_dev); | ||
1327 | 1289 | ||
1328 | PDEBUG(D_PROBE, "%s released", | 1290 | PDEBUG(D_PROBE, "%s released", |
1329 | video_device_node_name(&gspca_dev->vdev)); | 1291 | video_device_node_name(&gspca_dev->vdev)); |
@@ -1339,8 +1301,6 @@ static int dev_open(struct file *file) | |||
1339 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1301 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1340 | 1302 | ||
1341 | PDEBUG(D_STREAM, "[%s] open", current->comm); | 1303 | PDEBUG(D_STREAM, "[%s] open", current->comm); |
1342 | if (!gspca_dev->present) | ||
1343 | return -ENODEV; | ||
1344 | 1304 | ||
1345 | /* protect the subdriver against rmmod */ | 1305 | /* protect the subdriver against rmmod */ |
1346 | if (!try_module_get(gspca_dev->module)) | 1306 | if (!try_module_get(gspca_dev->module)) |
@@ -1363,21 +1323,27 @@ static int dev_close(struct file *file) | |||
1363 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1323 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1364 | 1324 | ||
1365 | PDEBUG(D_STREAM, "[%s] close", current->comm); | 1325 | PDEBUG(D_STREAM, "[%s] close", current->comm); |
1366 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1326 | |
1327 | /* Needed for gspca_stream_off, always lock before queue_lock! */ | ||
1328 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1367 | return -ERESTARTSYS; | 1329 | return -ERESTARTSYS; |
1368 | 1330 | ||
1331 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) { | ||
1332 | mutex_unlock(&gspca_dev->usb_lock); | ||
1333 | return -ERESTARTSYS; | ||
1334 | } | ||
1335 | |||
1369 | /* if the file did the capture, free the streaming resources */ | 1336 | /* if the file did the capture, free the streaming resources */ |
1370 | if (gspca_dev->capt_file == file) { | 1337 | if (gspca_dev->capt_file == file) { |
1371 | if (gspca_dev->streaming) { | 1338 | if (gspca_dev->streaming) { |
1372 | mutex_lock(&gspca_dev->usb_lock); | ||
1373 | gspca_dev->usb_err = 0; | 1339 | gspca_dev->usb_err = 0; |
1374 | gspca_stream_off(gspca_dev); | 1340 | gspca_stream_off(gspca_dev); |
1375 | mutex_unlock(&gspca_dev->usb_lock); | ||
1376 | } | 1341 | } |
1377 | frame_free(gspca_dev); | 1342 | frame_free(gspca_dev); |
1378 | } | 1343 | } |
1379 | module_put(gspca_dev->module); | 1344 | module_put(gspca_dev->module); |
1380 | mutex_unlock(&gspca_dev->queue_lock); | 1345 | mutex_unlock(&gspca_dev->queue_lock); |
1346 | mutex_unlock(&gspca_dev->usb_lock); | ||
1381 | 1347 | ||
1382 | PDEBUG(D_STREAM, "close done"); | 1348 | PDEBUG(D_STREAM, "close done"); |
1383 | 1349 | ||
@@ -1388,15 +1354,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
1388 | struct v4l2_capability *cap) | 1354 | struct v4l2_capability *cap) |
1389 | { | 1355 | { |
1390 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1356 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1391 | int ret; | ||
1392 | 1357 | ||
1393 | /* protect the access to the usb device */ | ||
1394 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1395 | return -ERESTARTSYS; | ||
1396 | if (!gspca_dev->present) { | ||
1397 | ret = -ENODEV; | ||
1398 | goto out; | ||
1399 | } | ||
1400 | strlcpy((char *) cap->driver, gspca_dev->sd_desc->name, | 1358 | strlcpy((char *) cap->driver, gspca_dev->sd_desc->name, |
1401 | sizeof cap->driver); | 1359 | sizeof cap->driver); |
1402 | if (gspca_dev->dev->product != NULL) { | 1360 | if (gspca_dev->dev->product != NULL) { |
@@ -1414,10 +1372,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
1414 | | V4L2_CAP_STREAMING | 1372 | | V4L2_CAP_STREAMING |
1415 | | V4L2_CAP_READWRITE; | 1373 | | V4L2_CAP_READWRITE; |
1416 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | 1374 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
1417 | ret = 0; | 1375 | return 0; |
1418 | out: | ||
1419 | mutex_unlock(&gspca_dev->usb_lock); | ||
1420 | return ret; | ||
1421 | } | 1376 | } |
1422 | 1377 | ||
1423 | static int get_ctrl(struct gspca_dev *gspca_dev, | 1378 | static int get_ctrl(struct gspca_dev *gspca_dev, |
@@ -1486,7 +1441,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1486 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1441 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1487 | const struct ctrl *ctrls; | 1442 | const struct ctrl *ctrls; |
1488 | struct gspca_ctrl *gspca_ctrl; | 1443 | struct gspca_ctrl *gspca_ctrl; |
1489 | int idx, ret; | 1444 | int idx; |
1490 | 1445 | ||
1491 | idx = get_ctrl(gspca_dev, ctrl->id); | 1446 | idx = get_ctrl(gspca_dev, ctrl->id); |
1492 | if (idx < 0) | 1447 | if (idx < 0) |
@@ -1506,27 +1461,16 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1506 | return -ERANGE; | 1461 | return -ERANGE; |
1507 | } | 1462 | } |
1508 | PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); | 1463 | PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); |
1509 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1510 | return -ERESTARTSYS; | ||
1511 | if (!gspca_dev->present) { | ||
1512 | ret = -ENODEV; | ||
1513 | goto out; | ||
1514 | } | ||
1515 | gspca_dev->usb_err = 0; | 1464 | gspca_dev->usb_err = 0; |
1516 | if (ctrls->set != NULL) { | 1465 | if (ctrls->set != NULL) |
1517 | ret = ctrls->set(gspca_dev, ctrl->value); | 1466 | return ctrls->set(gspca_dev, ctrl->value); |
1518 | goto out; | ||
1519 | } | ||
1520 | if (gspca_ctrl != NULL) { | 1467 | if (gspca_ctrl != NULL) { |
1521 | gspca_ctrl->val = ctrl->value; | 1468 | gspca_ctrl->val = ctrl->value; |
1522 | if (ctrls->set_control != NULL | 1469 | if (ctrls->set_control != NULL |
1523 | && gspca_dev->streaming) | 1470 | && gspca_dev->streaming) |
1524 | ctrls->set_control(gspca_dev); | 1471 | ctrls->set_control(gspca_dev); |
1525 | } | 1472 | } |
1526 | ret = gspca_dev->usb_err; | 1473 | return gspca_dev->usb_err; |
1527 | out: | ||
1528 | mutex_unlock(&gspca_dev->usb_lock); | ||
1529 | return ret; | ||
1530 | } | 1474 | } |
1531 | 1475 | ||
1532 | static int vidioc_g_ctrl(struct file *file, void *priv, | 1476 | static int vidioc_g_ctrl(struct file *file, void *priv, |
@@ -1534,30 +1478,19 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
1534 | { | 1478 | { |
1535 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1479 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1536 | const struct ctrl *ctrls; | 1480 | const struct ctrl *ctrls; |
1537 | int idx, ret; | 1481 | int idx; |
1538 | 1482 | ||
1539 | idx = get_ctrl(gspca_dev, ctrl->id); | 1483 | idx = get_ctrl(gspca_dev, ctrl->id); |
1540 | if (idx < 0) | 1484 | if (idx < 0) |
1541 | return -EINVAL; | 1485 | return -EINVAL; |
1542 | ctrls = &gspca_dev->sd_desc->ctrls[idx]; | 1486 | ctrls = &gspca_dev->sd_desc->ctrls[idx]; |
1543 | 1487 | ||
1544 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1545 | return -ERESTARTSYS; | ||
1546 | if (!gspca_dev->present) { | ||
1547 | ret = -ENODEV; | ||
1548 | goto out; | ||
1549 | } | ||
1550 | gspca_dev->usb_err = 0; | 1488 | gspca_dev->usb_err = 0; |
1551 | if (ctrls->get != NULL) { | 1489 | if (ctrls->get != NULL) |
1552 | ret = ctrls->get(gspca_dev, &ctrl->value); | 1490 | return ctrls->get(gspca_dev, &ctrl->value); |
1553 | goto out; | ||
1554 | } | ||
1555 | if (gspca_dev->cam.ctrls != NULL) | 1491 | if (gspca_dev->cam.ctrls != NULL) |
1556 | ctrl->value = gspca_dev->cam.ctrls[idx].val; | 1492 | ctrl->value = gspca_dev->cam.ctrls[idx].val; |
1557 | ret = 0; | 1493 | return 0; |
1558 | out: | ||
1559 | mutex_unlock(&gspca_dev->usb_lock); | ||
1560 | return ret; | ||
1561 | } | 1494 | } |
1562 | 1495 | ||
1563 | static int vidioc_querymenu(struct file *file, void *priv, | 1496 | static int vidioc_querymenu(struct file *file, void *priv, |
@@ -1640,10 +1573,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1640 | /* stop streaming */ | 1573 | /* stop streaming */ |
1641 | streaming = gspca_dev->streaming; | 1574 | streaming = gspca_dev->streaming; |
1642 | if (streaming) { | 1575 | if (streaming) { |
1643 | mutex_lock(&gspca_dev->usb_lock); | ||
1644 | gspca_dev->usb_err = 0; | 1576 | gspca_dev->usb_err = 0; |
1645 | gspca_stream_off(gspca_dev); | 1577 | gspca_stream_off(gspca_dev); |
1646 | mutex_unlock(&gspca_dev->usb_lock); | ||
1647 | 1578 | ||
1648 | /* Don't restart the stream when switching from read | 1579 | /* Don't restart the stream when switching from read |
1649 | * to mmap mode */ | 1580 | * to mmap mode */ |
@@ -1748,13 +1679,8 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1748 | } | 1679 | } |
1749 | 1680 | ||
1750 | /* stop streaming */ | 1681 | /* stop streaming */ |
1751 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { | ||
1752 | ret = -ERESTARTSYS; | ||
1753 | goto out; | ||
1754 | } | ||
1755 | gspca_dev->usb_err = 0; | 1682 | gspca_dev->usb_err = 0; |
1756 | gspca_stream_off(gspca_dev); | 1683 | gspca_stream_off(gspca_dev); |
1757 | mutex_unlock(&gspca_dev->usb_lock); | ||
1758 | /* In case another thread is waiting in dqbuf */ | 1684 | /* In case another thread is waiting in dqbuf */ |
1759 | wake_up_interruptible(&gspca_dev->wq); | 1685 | wake_up_interruptible(&gspca_dev->wq); |
1760 | 1686 | ||
@@ -1772,38 +1698,22 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, | |||
1772 | struct v4l2_jpegcompression *jpegcomp) | 1698 | struct v4l2_jpegcompression *jpegcomp) |
1773 | { | 1699 | { |
1774 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1700 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1775 | int ret; | ||
1776 | 1701 | ||
1777 | if (!gspca_dev->sd_desc->get_jcomp) | 1702 | if (!gspca_dev->sd_desc->get_jcomp) |
1778 | return -ENOTTY; | 1703 | return -ENOTTY; |
1779 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1780 | return -ERESTARTSYS; | ||
1781 | gspca_dev->usb_err = 0; | 1704 | gspca_dev->usb_err = 0; |
1782 | if (gspca_dev->present) | 1705 | return gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); |
1783 | ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); | ||
1784 | else | ||
1785 | ret = -ENODEV; | ||
1786 | mutex_unlock(&gspca_dev->usb_lock); | ||
1787 | return ret; | ||
1788 | } | 1706 | } |
1789 | 1707 | ||
1790 | static int vidioc_s_jpegcomp(struct file *file, void *priv, | 1708 | static int vidioc_s_jpegcomp(struct file *file, void *priv, |
1791 | struct v4l2_jpegcompression *jpegcomp) | 1709 | struct v4l2_jpegcompression *jpegcomp) |
1792 | { | 1710 | { |
1793 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1711 | struct gspca_dev *gspca_dev = video_drvdata(file); |
1794 | int ret; | ||
1795 | 1712 | ||
1796 | if (!gspca_dev->sd_desc->set_jcomp) | 1713 | if (!gspca_dev->sd_desc->set_jcomp) |
1797 | return -ENOTTY; | 1714 | return -ENOTTY; |
1798 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1799 | return -ERESTARTSYS; | ||
1800 | gspca_dev->usb_err = 0; | 1715 | gspca_dev->usb_err = 0; |
1801 | if (gspca_dev->present) | 1716 | return gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); |
1802 | ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); | ||
1803 | else | ||
1804 | ret = -ENODEV; | ||
1805 | mutex_unlock(&gspca_dev->usb_lock); | ||
1806 | return ret; | ||
1807 | } | 1717 | } |
1808 | 1718 | ||
1809 | static int vidioc_g_parm(struct file *filp, void *priv, | 1719 | static int vidioc_g_parm(struct file *filp, void *priv, |
@@ -1814,21 +1724,10 @@ static int vidioc_g_parm(struct file *filp, void *priv, | |||
1814 | parm->parm.capture.readbuffers = gspca_dev->nbufread; | 1724 | parm->parm.capture.readbuffers = gspca_dev->nbufread; |
1815 | 1725 | ||
1816 | if (gspca_dev->sd_desc->get_streamparm) { | 1726 | if (gspca_dev->sd_desc->get_streamparm) { |
1817 | int ret; | 1727 | gspca_dev->usb_err = 0; |
1818 | 1728 | gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); | |
1819 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1729 | return gspca_dev->usb_err; |
1820 | return -ERESTARTSYS; | ||
1821 | if (gspca_dev->present) { | ||
1822 | gspca_dev->usb_err = 0; | ||
1823 | gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); | ||
1824 | ret = gspca_dev->usb_err; | ||
1825 | } else { | ||
1826 | ret = -ENODEV; | ||
1827 | } | ||
1828 | mutex_unlock(&gspca_dev->usb_lock); | ||
1829 | return ret; | ||
1830 | } | 1730 | } |
1831 | |||
1832 | return 0; | 1731 | return 0; |
1833 | } | 1732 | } |
1834 | 1733 | ||
@@ -1845,19 +1744,9 @@ static int vidioc_s_parm(struct file *filp, void *priv, | |||
1845 | gspca_dev->nbufread = n; | 1744 | gspca_dev->nbufread = n; |
1846 | 1745 | ||
1847 | if (gspca_dev->sd_desc->set_streamparm) { | 1746 | if (gspca_dev->sd_desc->set_streamparm) { |
1848 | int ret; | 1747 | gspca_dev->usb_err = 0; |
1849 | 1748 | gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); | |
1850 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1749 | return gspca_dev->usb_err; |
1851 | return -ERESTARTSYS; | ||
1852 | if (gspca_dev->present) { | ||
1853 | gspca_dev->usb_err = 0; | ||
1854 | gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); | ||
1855 | ret = gspca_dev->usb_err; | ||
1856 | } else { | ||
1857 | ret = -ENODEV; | ||
1858 | } | ||
1859 | mutex_unlock(&gspca_dev->usb_lock); | ||
1860 | return ret; | ||
1861 | } | 1750 | } |
1862 | 1751 | ||
1863 | return 0; | 1752 | return 0; |
@@ -1877,10 +1766,6 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1877 | 1766 | ||
1878 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1767 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1879 | return -ERESTARTSYS; | 1768 | return -ERESTARTSYS; |
1880 | if (!gspca_dev->present) { | ||
1881 | ret = -ENODEV; | ||
1882 | goto out; | ||
1883 | } | ||
1884 | if (gspca_dev->capt_file != file) { | 1769 | if (gspca_dev->capt_file != file) { |
1885 | ret = -EINVAL; | 1770 | ret = -EINVAL; |
1886 | goto out; | 1771 | goto out; |
@@ -2008,14 +1893,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, | |||
2008 | 1893 | ||
2009 | gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES; | 1894 | gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES; |
2010 | 1895 | ||
2011 | if (gspca_dev->sd_desc->dq_callback) { | ||
2012 | mutex_lock(&gspca_dev->usb_lock); | ||
2013 | gspca_dev->usb_err = 0; | ||
2014 | if (gspca_dev->present) | ||
2015 | gspca_dev->sd_desc->dq_callback(gspca_dev); | ||
2016 | mutex_unlock(&gspca_dev->usb_lock); | ||
2017 | } | ||
2018 | |||
2019 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; | 1896 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; |
2020 | memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); | 1897 | memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); |
2021 | PDEBUG(D_FRAM, "dqbuf %d", j); | 1898 | PDEBUG(D_FRAM, "dqbuf %d", j); |
@@ -2032,6 +1909,15 @@ static int vidioc_dqbuf(struct file *file, void *priv, | |||
2032 | } | 1909 | } |
2033 | out: | 1910 | out: |
2034 | mutex_unlock(&gspca_dev->queue_lock); | 1911 | mutex_unlock(&gspca_dev->queue_lock); |
1912 | |||
1913 | if (ret == 0 && gspca_dev->sd_desc->dq_callback) { | ||
1914 | mutex_lock(&gspca_dev->usb_lock); | ||
1915 | gspca_dev->usb_err = 0; | ||
1916 | if (gspca_dev->present) | ||
1917 | gspca_dev->sd_desc->dq_callback(gspca_dev); | ||
1918 | mutex_unlock(&gspca_dev->usb_lock); | ||
1919 | } | ||
1920 | |||
2035 | return ret; | 1921 | return ret; |
2036 | } | 1922 | } |
2037 | 1923 | ||
@@ -2103,6 +1989,10 @@ static int read_alloc(struct gspca_dev *gspca_dev, | |||
2103 | int i, ret; | 1989 | int i, ret; |
2104 | 1990 | ||
2105 | PDEBUG(D_STREAM, "read alloc"); | 1991 | PDEBUG(D_STREAM, "read alloc"); |
1992 | |||
1993 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1994 | return -ERESTARTSYS; | ||
1995 | |||
2106 | if (gspca_dev->nframes == 0) { | 1996 | if (gspca_dev->nframes == 0) { |
2107 | struct v4l2_requestbuffers rb; | 1997 | struct v4l2_requestbuffers rb; |
2108 | 1998 | ||
@@ -2113,7 +2003,7 @@ static int read_alloc(struct gspca_dev *gspca_dev, | |||
2113 | ret = vidioc_reqbufs(file, gspca_dev, &rb); | 2003 | ret = vidioc_reqbufs(file, gspca_dev, &rb); |
2114 | if (ret != 0) { | 2004 | if (ret != 0) { |
2115 | PDEBUG(D_STREAM, "read reqbuf err %d", ret); | 2005 | PDEBUG(D_STREAM, "read reqbuf err %d", ret); |
2116 | return ret; | 2006 | goto out; |
2117 | } | 2007 | } |
2118 | memset(&v4l2_buf, 0, sizeof v4l2_buf); | 2008 | memset(&v4l2_buf, 0, sizeof v4l2_buf); |
2119 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 2009 | v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
@@ -2123,16 +2013,17 @@ static int read_alloc(struct gspca_dev *gspca_dev, | |||
2123 | ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); | 2013 | ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); |
2124 | if (ret != 0) { | 2014 | if (ret != 0) { |
2125 | PDEBUG(D_STREAM, "read qbuf err: %d", ret); | 2015 | PDEBUG(D_STREAM, "read qbuf err: %d", ret); |
2126 | return ret; | 2016 | goto out; |
2127 | } | 2017 | } |
2128 | } | 2018 | } |
2129 | gspca_dev->memory = GSPCA_MEMORY_READ; | ||
2130 | } | 2019 | } |
2131 | 2020 | ||
2132 | /* start streaming */ | 2021 | /* start streaming */ |
2133 | ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 2022 | ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
2134 | if (ret != 0) | 2023 | if (ret != 0) |
2135 | PDEBUG(D_STREAM, "read streamon err %d", ret); | 2024 | PDEBUG(D_STREAM, "read streamon err %d", ret); |
2025 | out: | ||
2026 | mutex_unlock(&gspca_dev->usb_lock); | ||
2136 | return ret; | 2027 | return ret; |
2137 | } | 2028 | } |
2138 | 2029 | ||
@@ -2177,8 +2068,6 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
2177 | int n, ret, ret2; | 2068 | int n, ret, ret2; |
2178 | 2069 | ||
2179 | PDEBUG(D_FRAM, "read (%zd)", count); | 2070 | PDEBUG(D_FRAM, "read (%zd)", count); |
2180 | if (!gspca_dev->present) | ||
2181 | return -ENODEV; | ||
2182 | if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */ | 2071 | if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */ |
2183 | ret = read_alloc(gspca_dev, file); | 2072 | ret = read_alloc(gspca_dev, file); |
2184 | if (ret != 0) | 2073 | if (ret != 0) |
@@ -2280,7 +2169,7 @@ static const struct video_device gspca_template = { | |||
2280 | .name = "gspca main driver", | 2169 | .name = "gspca main driver", |
2281 | .fops = &dev_fops, | 2170 | .fops = &dev_fops, |
2282 | .ioctl_ops = &dev_ioctl_ops, | 2171 | .ioctl_ops = &dev_ioctl_ops, |
2283 | .release = gspca_release, | 2172 | .release = video_device_release_empty, /* We use v4l2_dev.release */ |
2284 | }; | 2173 | }; |
2285 | 2174 | ||
2286 | /* initialize the controls */ | 2175 | /* initialize the controls */ |
@@ -2352,6 +2241,7 @@ int gspca_dev_probe2(struct usb_interface *intf, | |||
2352 | } | 2241 | } |
2353 | } | 2242 | } |
2354 | 2243 | ||
2244 | gspca_dev->v4l2_dev.release = gspca_release; | ||
2355 | ret = v4l2_device_register(&intf->dev, &gspca_dev->v4l2_dev); | 2245 | ret = v4l2_device_register(&intf->dev, &gspca_dev->v4l2_dev); |
2356 | if (ret) | 2246 | if (ret) |
2357 | goto out; | 2247 | goto out; |
@@ -2366,6 +2256,7 @@ int gspca_dev_probe2(struct usb_interface *intf, | |||
2366 | gspca_dev->present = 1; | 2256 | gspca_dev->present = 1; |
2367 | 2257 | ||
2368 | mutex_init(&gspca_dev->usb_lock); | 2258 | mutex_init(&gspca_dev->usb_lock); |
2259 | gspca_dev->vdev.lock = &gspca_dev->usb_lock; | ||
2369 | mutex_init(&gspca_dev->queue_lock); | 2260 | mutex_init(&gspca_dev->queue_lock); |
2370 | init_waitqueue_head(&gspca_dev->wq); | 2261 | init_waitqueue_head(&gspca_dev->wq); |
2371 | 2262 | ||
@@ -2388,6 +2279,15 @@ int gspca_dev_probe2(struct usb_interface *intf, | |||
2388 | if (ret) | 2279 | if (ret) |
2389 | goto out; | 2280 | goto out; |
2390 | 2281 | ||
2282 | /* | ||
2283 | * Don't take usb_lock for these ioctls. This improves latency if | ||
2284 | * usb_lock is taken for a long time, e.g. when changing a control | ||
2285 | * value, and a new frame is ready to be dequeued. | ||
2286 | */ | ||
2287 | v4l2_dont_use_lock(&gspca_dev->vdev, VIDIOC_DQBUF); | ||
2288 | v4l2_dont_use_lock(&gspca_dev->vdev, VIDIOC_QBUF); | ||
2289 | v4l2_dont_use_lock(&gspca_dev->vdev, VIDIOC_QUERYBUF); | ||
2290 | |||
2391 | /* init video stuff */ | 2291 | /* init video stuff */ |
2392 | ret = video_register_device(&gspca_dev->vdev, | 2292 | ret = video_register_device(&gspca_dev->vdev, |
2393 | VFL_TYPE_GRABBER, | 2293 | VFL_TYPE_GRABBER, |
@@ -2455,11 +2355,13 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2455 | 2355 | ||
2456 | PDEBUG(D_PROBE, "%s disconnect", | 2356 | PDEBUG(D_PROBE, "%s disconnect", |
2457 | video_device_node_name(&gspca_dev->vdev)); | 2357 | video_device_node_name(&gspca_dev->vdev)); |
2358 | |||
2458 | mutex_lock(&gspca_dev->usb_lock); | 2359 | mutex_lock(&gspca_dev->usb_lock); |
2459 | 2360 | ||
2361 | usb_set_intfdata(intf, NULL); | ||
2362 | gspca_dev->dev = NULL; | ||
2460 | gspca_dev->present = 0; | 2363 | gspca_dev->present = 0; |
2461 | wake_up_interruptible(&gspca_dev->wq); | 2364 | wake_up_interruptible(&gspca_dev->wq); |
2462 | |||
2463 | destroy_urbs(gspca_dev); | 2365 | destroy_urbs(gspca_dev); |
2464 | 2366 | ||
2465 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 2367 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
@@ -2471,18 +2373,13 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2471 | } | 2373 | } |
2472 | #endif | 2374 | #endif |
2473 | 2375 | ||
2474 | /* the device is freed at exit of this function */ | ||
2475 | gspca_dev->dev = NULL; | ||
2476 | v4l2_device_disconnect(&gspca_dev->v4l2_dev); | 2376 | v4l2_device_disconnect(&gspca_dev->v4l2_dev); |
2477 | mutex_unlock(&gspca_dev->usb_lock); | 2377 | video_unregister_device(&gspca_dev->vdev); |
2478 | 2378 | ||
2479 | usb_set_intfdata(intf, NULL); | 2379 | mutex_unlock(&gspca_dev->usb_lock); |
2480 | 2380 | ||
2481 | /* release the device */ | ||
2482 | /* (this will call gspca_release() immediately or on last close) */ | 2381 | /* (this will call gspca_release() immediately or on last close) */ |
2483 | video_unregister_device(&gspca_dev->vdev); | 2382 | v4l2_device_put(&gspca_dev->v4l2_dev); |
2484 | |||
2485 | /* PDEBUG(D_PROBE, "disconnect complete"); */ | ||
2486 | } | 2383 | } |
2487 | EXPORT_SYMBOL(gspca_disconnect); | 2384 | EXPORT_SYMBOL(gspca_disconnect); |
2488 | 2385 | ||
@@ -2493,17 +2390,16 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message) | |||
2493 | 2390 | ||
2494 | if (!gspca_dev->streaming) | 2391 | if (!gspca_dev->streaming) |
2495 | return 0; | 2392 | return 0; |
2393 | mutex_lock(&gspca_dev->usb_lock); | ||
2496 | gspca_dev->frozen = 1; /* avoid urb error messages */ | 2394 | gspca_dev->frozen = 1; /* avoid urb error messages */ |
2497 | if (gspca_dev->sd_desc->stopN) | 2395 | if (gspca_dev->sd_desc->stopN) |
2498 | gspca_dev->sd_desc->stopN(gspca_dev); | 2396 | gspca_dev->sd_desc->stopN(gspca_dev); |
2499 | destroy_urbs(gspca_dev); | 2397 | destroy_urbs(gspca_dev); |
2500 | gspca_input_destroy_urb(gspca_dev); | 2398 | gspca_input_destroy_urb(gspca_dev); |
2501 | gspca_set_alt0(gspca_dev); | 2399 | gspca_set_alt0(gspca_dev); |
2502 | if (gspca_dev->sd_desc->stop0) { | 2400 | if (gspca_dev->sd_desc->stop0) |
2503 | mutex_lock(&gspca_dev->usb_lock); | ||
2504 | gspca_dev->sd_desc->stop0(gspca_dev); | 2401 | gspca_dev->sd_desc->stop0(gspca_dev); |
2505 | mutex_unlock(&gspca_dev->usb_lock); | 2402 | mutex_unlock(&gspca_dev->usb_lock); |
2506 | } | ||
2507 | return 0; | 2403 | return 0; |
2508 | } | 2404 | } |
2509 | EXPORT_SYMBOL(gspca_suspend); | 2405 | EXPORT_SYMBOL(gspca_suspend); |
@@ -2513,6 +2409,7 @@ int gspca_resume(struct usb_interface *intf) | |||
2513 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 2409 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
2514 | int streaming, ret = 0; | 2410 | int streaming, ret = 0; |
2515 | 2411 | ||
2412 | mutex_lock(&gspca_dev->usb_lock); | ||
2516 | gspca_dev->frozen = 0; | 2413 | gspca_dev->frozen = 0; |
2517 | gspca_dev->sd_desc->init(gspca_dev); | 2414 | gspca_dev->sd_desc->init(gspca_dev); |
2518 | gspca_input_create_urb(gspca_dev); | 2415 | gspca_input_create_urb(gspca_dev); |
@@ -2524,11 +2421,9 @@ int gspca_resume(struct usb_interface *intf) | |||
2524 | streaming = gspca_dev->streaming; | 2421 | streaming = gspca_dev->streaming; |
2525 | gspca_dev->streaming = 0; | 2422 | gspca_dev->streaming = 0; |
2526 | v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler); | 2423 | v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler); |
2527 | if (streaming) { | 2424 | if (streaming) |
2528 | mutex_lock(&gspca_dev->queue_lock); | ||
2529 | ret = gspca_init_transfer(gspca_dev); | 2425 | ret = gspca_init_transfer(gspca_dev); |
2530 | mutex_unlock(&gspca_dev->queue_lock); | 2426 | mutex_unlock(&gspca_dev->usb_lock); |
2531 | } | ||
2532 | return ret; | 2427 | return ret; |
2533 | } | 2428 | } |
2534 | EXPORT_SYMBOL(gspca_resume); | 2429 | EXPORT_SYMBOL(gspca_resume); |