aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov511.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-06-15 09:04:00 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-16 18:07:40 -0400
commit163fe744c3283fd267268629afff4cfc846ed0e0 (patch)
tree4ad105db31f39491b5bb2f936c13416faf684121 /drivers/media/video/ov511.c
parenteccd15aad72f774b2059f708bc422dbb8493bb30 (diff)
V4L/DVB (11966): ov511: Fix unit_video parameter behavior
Fix a regression caused by changeset 9133:64aed7485a43 - v4l: disconnect kernel number from minor Before the above changeset, ov511_probe used to allow forcing to use a certain specific set of video devices, like: modprobe ov511 unit_video=4,1,3 num_uv=3 So, assuming that you have 5 ov511 devices, and connect they one by one, they'll gain the following device numbers (at the connection order): /dev/video4 /dev/video1 /dev/video3 /dev/video0 /dev/video2 However, this was changed due to this change at video_register_device(): + nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); With the previous behavior, a trial to register on an already allocated mirror would fail, and a loop would get the next requested minor. However, the current behavior is to get the next available minor instead of failing. Due to that, this means that the above modprobe parameter will give, instead: /dev/video5 /dev/video6 /dev/video7 /dev/video8 /dev/video9 In order to restore the original behavior, a static var were added, storing the amount of already registered devices. While there, it also fixes the locking of the probe/disconnect functions. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ov511.c')
-rw-r--r--drivers/media/video/ov511.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 9af5532db142..08cfd3e4ae8a 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -112,6 +112,8 @@ static int framedrop = -1;
112static int fastset; 112static int fastset;
113static int force_palette; 113static int force_palette;
114static int backlight; 114static int backlight;
115/* Bitmask marking allocated devices from 0 to OV511_MAX_UNIT_VIDEO */
116static unsigned long ov511_devused;
115static int unit_video[OV511_MAX_UNIT_VIDEO]; 117static int unit_video[OV511_MAX_UNIT_VIDEO];
116static int remove_zeros; 118static int remove_zeros;
117static int mirror; 119static int mirror;
@@ -5720,7 +5722,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
5720 struct usb_device *dev = interface_to_usbdev(intf); 5722 struct usb_device *dev = interface_to_usbdev(intf);
5721 struct usb_interface_descriptor *idesc; 5723 struct usb_interface_descriptor *idesc;
5722 struct usb_ov511 *ov; 5724 struct usb_ov511 *ov;
5723 int i; 5725 int i, rc, nr;
5724 5726
5725 PDEBUG(1, "probing for device..."); 5727 PDEBUG(1, "probing for device...");
5726 5728
@@ -5845,33 +5847,41 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
5845 ov->vdev->parent = &intf->dev; 5847 ov->vdev->parent = &intf->dev;
5846 video_set_drvdata(ov->vdev, ov); 5848 video_set_drvdata(ov->vdev, ov);
5847 5849
5848 for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) { 5850 mutex_lock(&ov->lock);
5849 /* Minor 0 cannot be specified; assume user wants autodetect */
5850 if (unit_video[i] == 0)
5851 break;
5852 5851
5853 if (video_register_device(ov->vdev, VFL_TYPE_GRABBER, 5852 /* Check to see next free device and mark as used */
5854 unit_video[i]) >= 0) { 5853 nr = find_first_zero_bit(&ov511_devused, OV511_MAX_UNIT_VIDEO);
5855 break; 5854
5856 } 5855 /* Registers device */
5857 } 5856 if (unit_video[nr] != 0)
5857 rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER,
5858 unit_video[nr]);
5859 else
5860 rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1);
5858 5861
5859 /* Use the next available one */ 5862 if (rc < 0) {
5860 if ((ov->vdev->minor == -1) &&
5861 video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
5862 err("video_register_device failed"); 5863 err("video_register_device failed");
5864 mutex_unlock(&ov->lock);
5863 goto error; 5865 goto error;
5864 } 5866 }
5865 5867
5868 /* Mark device as used */
5869 ov511_devused |= 1 << nr;
5870 ov->nr = nr;
5871
5866 dev_info(&intf->dev, "Device at %s registered to minor %d\n", 5872 dev_info(&intf->dev, "Device at %s registered to minor %d\n",
5867 ov->usb_path, ov->vdev->minor); 5873 ov->usb_path, ov->vdev->minor);
5868 5874
5869 usb_set_intfdata(intf, ov); 5875 usb_set_intfdata(intf, ov);
5870 if (ov_create_sysfs(ov->vdev)) { 5876 if (ov_create_sysfs(ov->vdev)) {
5871 err("ov_create_sysfs failed"); 5877 err("ov_create_sysfs failed");
5878 ov511_devused &= ~(1 << nr);
5879 mutex_unlock(&ov->lock);
5872 goto error; 5880 goto error;
5873 } 5881 }
5874 5882
5883 mutex_lock(&ov->lock);
5884
5875 return 0; 5885 return 0;
5876 5886
5877error: 5887error:
@@ -5906,10 +5916,16 @@ ov51x_disconnect(struct usb_interface *intf)
5906 5916
5907 PDEBUG(3, ""); 5917 PDEBUG(3, "");
5908 5918
5919 mutex_lock(&ov->lock);
5909 usb_set_intfdata (intf, NULL); 5920 usb_set_intfdata (intf, NULL);
5910 5921
5911 if (!ov) 5922 if (!ov) {
5923 mutex_unlock(&ov->lock);
5912 return; 5924 return;
5925 }
5926
5927 /* Free device number */
5928 ov511_devused &= ~(1 << ov->nr);
5913 5929
5914 if (ov->vdev) 5930 if (ov->vdev)
5915 video_unregister_device(ov->vdev); 5931 video_unregister_device(ov->vdev);
@@ -5927,6 +5943,7 @@ ov51x_disconnect(struct usb_interface *intf)
5927 5943
5928 ov->streaming = 0; 5944 ov->streaming = 0;
5929 ov51x_unlink_isoc(ov); 5945 ov51x_unlink_isoc(ov);
5946 mutex_unlock(&ov->lock);
5930 5947
5931 ov->dev = NULL; 5948 ov->dev = NULL;
5932 5949