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>
This commit is contained in:
Родитель
eccd15aad7
Коммит
163fe744c3
|
@ -112,6 +112,8 @@ static int framedrop = -1;
|
||||||
static int fastset;
|
static int fastset;
|
||||||
static int force_palette;
|
static int force_palette;
|
||||||
static int backlight;
|
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 unit_video[OV511_MAX_UNIT_VIDEO];
|
||||||
static int remove_zeros;
|
static int remove_zeros;
|
||||||
static int mirror;
|
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_device *dev = interface_to_usbdev(intf);
|
||||||
struct usb_interface_descriptor *idesc;
|
struct usb_interface_descriptor *idesc;
|
||||||
struct usb_ov511 *ov;
|
struct usb_ov511 *ov;
|
||||||
int i;
|
int i, rc, nr;
|
||||||
|
|
||||||
PDEBUG(1, "probing for device...");
|
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;
|
ov->vdev->parent = &intf->dev;
|
||||||
video_set_drvdata(ov->vdev, ov);
|
video_set_drvdata(ov->vdev, ov);
|
||||||
|
|
||||||
for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
|
mutex_lock(&ov->lock);
|
||||||
/* Minor 0 cannot be specified; assume user wants autodetect */
|
|
||||||
if (unit_video[i] == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (video_register_device(ov->vdev, VFL_TYPE_GRABBER,
|
/* Check to see next free device and mark as used */
|
||||||
unit_video[i]) >= 0) {
|
nr = find_first_zero_bit(&ov511_devused, OV511_MAX_UNIT_VIDEO);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use the next available one */
|
/* Registers device */
|
||||||
if ((ov->vdev->minor == -1) &&
|
if (unit_video[nr] != 0)
|
||||||
video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
|
rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER,
|
||||||
|
unit_video[nr]);
|
||||||
|
else
|
||||||
|
rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
err("video_register_device failed");
|
err("video_register_device failed");
|
||||||
|
mutex_unlock(&ov->lock);
|
||||||
goto error;
|
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",
|
dev_info(&intf->dev, "Device at %s registered to minor %d\n",
|
||||||
ov->usb_path, ov->vdev->minor);
|
ov->usb_path, ov->vdev->minor);
|
||||||
|
|
||||||
usb_set_intfdata(intf, ov);
|
usb_set_intfdata(intf, ov);
|
||||||
if (ov_create_sysfs(ov->vdev)) {
|
if (ov_create_sysfs(ov->vdev)) {
|
||||||
err("ov_create_sysfs failed");
|
err("ov_create_sysfs failed");
|
||||||
|
ov511_devused &= ~(1 << nr);
|
||||||
|
mutex_unlock(&ov->lock);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ov->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -5906,10 +5916,16 @@ ov51x_disconnect(struct usb_interface *intf)
|
||||||
|
|
||||||
PDEBUG(3, "");
|
PDEBUG(3, "");
|
||||||
|
|
||||||
|
mutex_lock(&ov->lock);
|
||||||
usb_set_intfdata (intf, NULL);
|
usb_set_intfdata (intf, NULL);
|
||||||
|
|
||||||
if (!ov)
|
if (!ov) {
|
||||||
|
mutex_unlock(&ov->lock);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free device number */
|
||||||
|
ov511_devused &= ~(1 << ov->nr);
|
||||||
|
|
||||||
if (ov->vdev)
|
if (ov->vdev)
|
||||||
video_unregister_device(ov->vdev);
|
video_unregister_device(ov->vdev);
|
||||||
|
@ -5927,6 +5943,7 @@ ov51x_disconnect(struct usb_interface *intf)
|
||||||
|
|
||||||
ov->streaming = 0;
|
ov->streaming = 0;
|
||||||
ov51x_unlink_isoc(ov);
|
ov51x_unlink_isoc(ov);
|
||||||
|
mutex_unlock(&ov->lock);
|
||||||
|
|
||||||
ov->dev = NULL;
|
ov->dev = NULL;
|
||||||
|
|
||||||
|
|
|
@ -494,6 +494,9 @@ struct usb_ov511 {
|
||||||
int has_decoder; /* Device has a video decoder */
|
int has_decoder; /* Device has a video decoder */
|
||||||
int pal; /* Device is designed for PAL resolution */
|
int pal; /* Device is designed for PAL resolution */
|
||||||
|
|
||||||
|
/* ov511 device number ID */
|
||||||
|
int nr; /* Stores a device number */
|
||||||
|
|
||||||
/* I2C interface */
|
/* I2C interface */
|
||||||
struct mutex i2c_lock; /* Protect I2C controller regs */
|
struct mutex i2c_lock; /* Protect I2C controller regs */
|
||||||
unsigned char primary_i2c_slave; /* I2C write id of sensor */
|
unsigned char primary_i2c_slave; /* I2C write id of sensor */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче