diff options
Diffstat (limited to 'drivers/media/video/ov511.c')
-rw-r--r-- | drivers/media/video/ov511.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 9af5532db14..08cfd3e4ae8 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -112,6 +112,8 @@ static int framedrop = -1; static int fastset; static int force_palette; static int backlight; +/* Bitmask marking allocated devices from 0 to OV511_MAX_UNIT_VIDEO */ +static unsigned long ov511_devused; static int unit_video[OV511_MAX_UNIT_VIDEO]; static int remove_zeros; static int mirror; @@ -5720,7 +5722,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) struct usb_device *dev = interface_to_usbdev(intf); struct usb_interface_descriptor *idesc; struct usb_ov511 *ov; - int i; + int i, rc, nr; PDEBUG(1, "probing for device..."); @@ -5845,33 +5847,41 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) ov->vdev->parent = &intf->dev; video_set_drvdata(ov->vdev, ov); - for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) { - /* Minor 0 cannot be specified; assume user wants autodetect */ - if (unit_video[i] == 0) - break; + mutex_lock(&ov->lock); - if (video_register_device(ov->vdev, VFL_TYPE_GRABBER, - unit_video[i]) >= 0) { - break; - } - } + /* Check to see next free device and mark as used */ + nr = find_first_zero_bit(&ov511_devused, OV511_MAX_UNIT_VIDEO); + + /* Registers device */ + if (unit_video[nr] != 0) + rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, + unit_video[nr]); + else + rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1); - /* Use the next available one */ - if ((ov->vdev->minor == -1) && - video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) { + if (rc < 0) { err("video_register_device failed"); + mutex_unlock(&ov->lock); goto error; } + /* Mark device as used */ + ov511_devused |= 1 << nr; + ov->nr = nr; + dev_info(&intf->dev, "Device at %s registered to minor %d\n", ov->usb_path, ov->vdev->minor); usb_set_intfdata(intf, ov); if (ov_create_sysfs(ov->vdev)) { err("ov_create_sysfs failed"); + ov511_devused &= ~(1 << nr); + mutex_unlock(&ov->lock); goto error; } + mutex_lock(&ov->lock); + return 0; error: @@ -5906,10 +5916,16 @@ ov51x_disconnect(struct usb_interface *intf) PDEBUG(3, ""); + mutex_lock(&ov->lock); usb_set_intfdata (intf, NULL); - if (!ov) + if (!ov) { + mutex_unlock(&ov->lock); return; + } + + /* Free device number */ + ov511_devused &= ~(1 << ov->nr); if (ov->vdev) video_unregister_device(ov->vdev); @@ -5927,6 +5943,7 @@ ov51x_disconnect(struct usb_interface *intf) ov->streaming = 0; ov51x_unlink_isoc(ov); + mutex_unlock(&ov->lock); ov->dev = NULL; |