diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2009-09-29 20:07:19 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:40:36 -0500 |
commit | 716fdee110ceb816cca8c46c0890d08c5a1addb9 (patch) | |
tree | 69e4f133fbbf6549a73b03c3d72583ed66db5710 /drivers/media/video/uvc/uvc_driver.c | |
parent | 1a969d9863a0c8890eb799ec710dda9701f10483 (diff) |
V4L/DVB (13152): uvcvideo: Rely on videodev to reference-count the device
The uvcvideo driver has a driver-wide lock and a reference count to protect
against a disconnect/open race. Now that videodev handles the race itself,
reference-counting in the driver can be removed.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc/uvc_driver.c')
-rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 155 |
1 files changed, 79 insertions, 76 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 8756be569154..ebddf006a4f4 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -1531,22 +1531,92 @@ static int uvc_scan_device(struct uvc_device *dev) | |||
1531 | */ | 1531 | */ |
1532 | 1532 | ||
1533 | /* | 1533 | /* |
1534 | * Delete the UVC device. | ||
1535 | * | ||
1536 | * Called by the kernel when the last reference to the uvc_device structure | ||
1537 | * is released. | ||
1538 | * | ||
1539 | * As this function is called after or during disconnect(), all URBs have | ||
1540 | * already been canceled by the USB core. There is no need to kill the | ||
1541 | * interrupt URB manually. | ||
1542 | */ | ||
1543 | static void uvc_delete(struct uvc_device *dev) | ||
1544 | { | ||
1545 | struct list_head *p, *n; | ||
1546 | |||
1547 | usb_put_intf(dev->intf); | ||
1548 | usb_put_dev(dev->udev); | ||
1549 | |||
1550 | uvc_status_cleanup(dev); | ||
1551 | uvc_ctrl_cleanup_device(dev); | ||
1552 | |||
1553 | list_for_each_safe(p, n, &dev->chains) { | ||
1554 | struct uvc_video_chain *chain; | ||
1555 | chain = list_entry(p, struct uvc_video_chain, list); | ||
1556 | kfree(chain); | ||
1557 | } | ||
1558 | |||
1559 | list_for_each_safe(p, n, &dev->entities) { | ||
1560 | struct uvc_entity *entity; | ||
1561 | entity = list_entry(p, struct uvc_entity, list); | ||
1562 | kfree(entity); | ||
1563 | } | ||
1564 | |||
1565 | list_for_each_safe(p, n, &dev->streams) { | ||
1566 | struct uvc_streaming *streaming; | ||
1567 | streaming = list_entry(p, struct uvc_streaming, list); | ||
1568 | usb_driver_release_interface(&uvc_driver.driver, | ||
1569 | streaming->intf); | ||
1570 | usb_put_intf(streaming->intf); | ||
1571 | kfree(streaming->format); | ||
1572 | kfree(streaming->header.bmaControls); | ||
1573 | kfree(streaming); | ||
1574 | } | ||
1575 | |||
1576 | kfree(dev); | ||
1577 | } | ||
1578 | |||
1579 | static void uvc_release(struct video_device *vdev) | ||
1580 | { | ||
1581 | struct uvc_streaming *stream = video_get_drvdata(vdev); | ||
1582 | struct uvc_device *dev = stream->dev; | ||
1583 | |||
1584 | video_device_release(vdev); | ||
1585 | |||
1586 | /* Decrement the registered streams count and delete the device when it | ||
1587 | * reaches zero. | ||
1588 | */ | ||
1589 | if (atomic_dec_and_test(&dev->nstreams)) | ||
1590 | uvc_delete(dev); | ||
1591 | } | ||
1592 | |||
1593 | /* | ||
1534 | * Unregister the video devices. | 1594 | * Unregister the video devices. |
1535 | */ | 1595 | */ |
1536 | static void uvc_unregister_video(struct uvc_device *dev) | 1596 | static void uvc_unregister_video(struct uvc_device *dev) |
1537 | { | 1597 | { |
1538 | struct uvc_streaming *stream; | 1598 | struct uvc_streaming *stream; |
1539 | 1599 | ||
1600 | /* Unregistering all video devices might result in uvc_delete() being | ||
1601 | * called from inside the loop if there's no open file handle. To avoid | ||
1602 | * that, increment the stream count before iterating over the streams | ||
1603 | * and decrement it when done. | ||
1604 | */ | ||
1605 | atomic_inc(&dev->nstreams); | ||
1606 | |||
1540 | list_for_each_entry(stream, &dev->streams, list) { | 1607 | list_for_each_entry(stream, &dev->streams, list) { |
1541 | if (stream->vdev == NULL) | 1608 | if (stream->vdev == NULL) |
1542 | continue; | 1609 | continue; |
1543 | 1610 | ||
1544 | if (stream->vdev->minor == -1) | 1611 | video_unregister_device(stream->vdev); |
1545 | video_device_release(stream->vdev); | ||
1546 | else | ||
1547 | video_unregister_device(stream->vdev); | ||
1548 | stream->vdev = NULL; | 1612 | stream->vdev = NULL; |
1549 | } | 1613 | } |
1614 | |||
1615 | /* Decrement the stream count and call uvc_delete explicitly if there | ||
1616 | * are no stream left. | ||
1617 | */ | ||
1618 | if (atomic_dec_and_test(&dev->nstreams)) | ||
1619 | uvc_delete(dev); | ||
1550 | } | 1620 | } |
1551 | 1621 | ||
1552 | static int uvc_register_video(struct uvc_device *dev, | 1622 | static int uvc_register_video(struct uvc_device *dev, |
@@ -1580,7 +1650,7 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1580 | vdev->parent = &dev->intf->dev; | 1650 | vdev->parent = &dev->intf->dev; |
1581 | vdev->minor = -1; | 1651 | vdev->minor = -1; |
1582 | vdev->fops = &uvc_fops; | 1652 | vdev->fops = &uvc_fops; |
1583 | vdev->release = video_device_release; | 1653 | vdev->release = uvc_release; |
1584 | strlcpy(vdev->name, dev->name, sizeof vdev->name); | 1654 | strlcpy(vdev->name, dev->name, sizeof vdev->name); |
1585 | 1655 | ||
1586 | /* Set the driver data before calling video_register_device, otherwise | 1656 | /* Set the driver data before calling video_register_device, otherwise |
@@ -1598,6 +1668,7 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1598 | return ret; | 1668 | return ret; |
1599 | } | 1669 | } |
1600 | 1670 | ||
1671 | atomic_inc(&dev->nstreams); | ||
1601 | return 0; | 1672 | return 0; |
1602 | } | 1673 | } |
1603 | 1674 | ||
@@ -1653,61 +1724,6 @@ static int uvc_register_chains(struct uvc_device *dev) | |||
1653 | * USB probe, disconnect, suspend and resume | 1724 | * USB probe, disconnect, suspend and resume |
1654 | */ | 1725 | */ |
1655 | 1726 | ||
1656 | /* | ||
1657 | * Delete the UVC device. | ||
1658 | * | ||
1659 | * Called by the kernel when the last reference to the uvc_device structure | ||
1660 | * is released. | ||
1661 | * | ||
1662 | * Unregistering the video devices is done here because every opened instance | ||
1663 | * must be closed before the device can be unregistered. An alternative would | ||
1664 | * have been to use another reference count for uvc_v4l2_open/uvc_release, and | ||
1665 | * unregister the video devices on disconnect when that reference count drops | ||
1666 | * to zero. | ||
1667 | * | ||
1668 | * As this function is called after or during disconnect(), all URBs have | ||
1669 | * already been canceled by the USB core. There is no need to kill the | ||
1670 | * interrupt URB manually. | ||
1671 | */ | ||
1672 | void uvc_delete(struct kref *kref) | ||
1673 | { | ||
1674 | struct uvc_device *dev = container_of(kref, struct uvc_device, kref); | ||
1675 | struct list_head *p, *n; | ||
1676 | |||
1677 | /* Unregister the video devices. */ | ||
1678 | uvc_unregister_video(dev); | ||
1679 | usb_put_intf(dev->intf); | ||
1680 | usb_put_dev(dev->udev); | ||
1681 | |||
1682 | uvc_status_cleanup(dev); | ||
1683 | uvc_ctrl_cleanup_device(dev); | ||
1684 | |||
1685 | list_for_each_safe(p, n, &dev->chains) { | ||
1686 | struct uvc_video_chain *chain; | ||
1687 | chain = list_entry(p, struct uvc_video_chain, list); | ||
1688 | kfree(chain); | ||
1689 | } | ||
1690 | |||
1691 | list_for_each_safe(p, n, &dev->entities) { | ||
1692 | struct uvc_entity *entity; | ||
1693 | entity = list_entry(p, struct uvc_entity, list); | ||
1694 | kfree(entity); | ||
1695 | } | ||
1696 | |||
1697 | list_for_each_safe(p, n, &dev->streams) { | ||
1698 | struct uvc_streaming *streaming; | ||
1699 | streaming = list_entry(p, struct uvc_streaming, list); | ||
1700 | usb_driver_release_interface(&uvc_driver.driver, | ||
1701 | streaming->intf); | ||
1702 | usb_put_intf(streaming->intf); | ||
1703 | kfree(streaming->format); | ||
1704 | kfree(streaming->header.bmaControls); | ||
1705 | kfree(streaming); | ||
1706 | } | ||
1707 | |||
1708 | kfree(dev); | ||
1709 | } | ||
1710 | |||
1711 | static int uvc_probe(struct usb_interface *intf, | 1727 | static int uvc_probe(struct usb_interface *intf, |
1712 | const struct usb_device_id *id) | 1728 | const struct usb_device_id *id) |
1713 | { | 1729 | { |
@@ -1730,7 +1746,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1730 | INIT_LIST_HEAD(&dev->entities); | 1746 | INIT_LIST_HEAD(&dev->entities); |
1731 | INIT_LIST_HEAD(&dev->chains); | 1747 | INIT_LIST_HEAD(&dev->chains); |
1732 | INIT_LIST_HEAD(&dev->streams); | 1748 | INIT_LIST_HEAD(&dev->streams); |
1733 | kref_init(&dev->kref); | 1749 | atomic_set(&dev->nstreams, 0); |
1734 | atomic_set(&dev->users, 0); | 1750 | atomic_set(&dev->users, 0); |
1735 | 1751 | ||
1736 | dev->udev = usb_get_dev(udev); | 1752 | dev->udev = usb_get_dev(udev); |
@@ -1792,7 +1808,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1792 | return 0; | 1808 | return 0; |
1793 | 1809 | ||
1794 | error: | 1810 | error: |
1795 | kref_put(&dev->kref, uvc_delete); | 1811 | uvc_unregister_video(dev); |
1796 | return -ENODEV; | 1812 | return -ENODEV; |
1797 | } | 1813 | } |
1798 | 1814 | ||
@@ -1809,21 +1825,9 @@ static void uvc_disconnect(struct usb_interface *intf) | |||
1809 | UVC_SC_VIDEOSTREAMING) | 1825 | UVC_SC_VIDEOSTREAMING) |
1810 | return; | 1826 | return; |
1811 | 1827 | ||
1812 | /* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide | ||
1813 | * lock is needed to prevent uvc_disconnect from releasing its | ||
1814 | * reference to the uvc_device instance after uvc_v4l2_open() received | ||
1815 | * the pointer to the device (video_devdata) but before it got the | ||
1816 | * chance to increase the reference count (kref_get). | ||
1817 | * | ||
1818 | * Note that the reference can't be released with the lock held, | ||
1819 | * otherwise a AB-BA deadlock can occur with videodev_lock that | ||
1820 | * videodev acquires in videodev_open() and video_unregister_device(). | ||
1821 | */ | ||
1822 | mutex_lock(&uvc_driver.open_mutex); | ||
1823 | dev->state |= UVC_DEV_DISCONNECTED; | 1828 | dev->state |= UVC_DEV_DISCONNECTED; |
1824 | mutex_unlock(&uvc_driver.open_mutex); | ||
1825 | 1829 | ||
1826 | kref_put(&dev->kref, uvc_delete); | 1830 | uvc_unregister_video(dev); |
1827 | } | 1831 | } |
1828 | 1832 | ||
1829 | static int uvc_suspend(struct usb_interface *intf, pm_message_t message) | 1833 | static int uvc_suspend(struct usb_interface *intf, pm_message_t message) |
@@ -2159,7 +2163,6 @@ static int __init uvc_init(void) | |||
2159 | 2163 | ||
2160 | INIT_LIST_HEAD(&uvc_driver.devices); | 2164 | INIT_LIST_HEAD(&uvc_driver.devices); |
2161 | INIT_LIST_HEAD(&uvc_driver.controls); | 2165 | INIT_LIST_HEAD(&uvc_driver.controls); |
2162 | mutex_init(&uvc_driver.open_mutex); | ||
2163 | mutex_init(&uvc_driver.ctrl_mutex); | 2166 | mutex_init(&uvc_driver.ctrl_mutex); |
2164 | 2167 | ||
2165 | uvc_ctrl_init(); | 2168 | uvc_ctrl_init(); |