diff options
author | Jonathan Nieder <jrnieder@gmail.com> | 2011-05-01 05:29:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 08:29:37 -0400 |
commit | 1d6213ab995c61f7d1d81cf6cf876acf15d6e714 (patch) | |
tree | 72ebdfa1d65066a6cd5361ee605a48e2dfcda4b2 /drivers/media/video/cx88 | |
parent | 1fe70e963028f34ba5e32488a7870ff4b410b19b (diff) |
[media] cx88: hold device lock during sub-driver initialization
cx8802_blackbird_probe makes a device node for the mpeg sub-device
before it has been added to dev->drvlist. If the device is opened
during that time, the open succeeds but request_acquire cannot be
called, so the reference count remains zero. Later, when the device
is closed, the reference count becomes negative --- uh oh.
Close the race by holding core->lock during probe and not releasing
until the device is in drvlist and initialization finished.
Previously the BKL prevented this race.
Reported-by: Andreas Huber <hobrom@gmx.at>
Tested-by: Andi Huber <hobrom@gmx.at>
Tested-by: Marlon de Boer <marlon@hyves.nl>
Cc: stable@kernel.org
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 5 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 7 |
3 files changed, 4 insertions, 10 deletions
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index a6f7d53a4510..f637d34d5062 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -1335,11 +1335,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1335 | blackbird_register_video(dev); | 1335 | blackbird_register_video(dev); |
1336 | 1336 | ||
1337 | /* initial device configuration: needed ? */ | 1337 | /* initial device configuration: needed ? */ |
1338 | mutex_lock(&dev->core->lock); | ||
1339 | // init_controls(core); | 1338 | // init_controls(core); |
1340 | cx88_set_tvnorm(core,core->tvnorm); | 1339 | cx88_set_tvnorm(core,core->tvnorm); |
1341 | cx88_video_mux(core,0); | 1340 | cx88_video_mux(core,0); |
1342 | mutex_unlock(&dev->core->lock); | ||
1343 | 1341 | ||
1344 | return 0; | 1342 | return 0; |
1345 | 1343 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 91d3d179c3c7..455290011d4e 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -709,18 +709,17 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
709 | drv->request_release = cx8802_request_release; | 709 | drv->request_release = cx8802_request_release; |
710 | memcpy(driver, drv, sizeof(*driver)); | 710 | memcpy(driver, drv, sizeof(*driver)); |
711 | 711 | ||
712 | mutex_lock(&drv->core->lock); | ||
712 | err = drv->probe(driver); | 713 | err = drv->probe(driver); |
713 | if (err == 0) { | 714 | if (err == 0) { |
714 | i++; | 715 | i++; |
715 | mutex_lock(&drv->core->lock); | ||
716 | list_add_tail(&driver->drvlist, &dev->drvlist); | 716 | list_add_tail(&driver->drvlist, &dev->drvlist); |
717 | mutex_unlock(&drv->core->lock); | ||
718 | } else { | 717 | } else { |
719 | printk(KERN_ERR | 718 | printk(KERN_ERR |
720 | "%s/2: cx8802 probe failed, err = %d\n", | 719 | "%s/2: cx8802 probe failed, err = %d\n", |
721 | dev->core->name, err); | 720 | dev->core->name, err); |
722 | } | 721 | } |
723 | 722 | mutex_unlock(&drv->core->lock); | |
724 | } | 723 | } |
725 | 724 | ||
726 | return i ? 0 : -ENODEV; | 725 | return i ? 0 : -ENODEV; |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 9731daa92a06..3d32f4afac9d 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -505,13 +505,10 @@ struct cx8802_driver { | |||
505 | int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); | 505 | int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); |
506 | int (*resume)(struct pci_dev *pci_dev); | 506 | int (*resume)(struct pci_dev *pci_dev); |
507 | 507 | ||
508 | /* MPEG 8802 -> mini driver - Driver probe and configuration */ | ||
509 | |||
510 | /* Caller must _not_ hold core->lock */ | ||
511 | int (*probe)(struct cx8802_driver *drv); | ||
512 | |||
513 | /* Callers to the following functions must hold core->lock */ | 508 | /* Callers to the following functions must hold core->lock */ |
514 | 509 | ||
510 | /* MPEG 8802 -> mini driver - Driver probe and configuration */ | ||
511 | int (*probe)(struct cx8802_driver *drv); | ||
515 | int (*remove)(struct cx8802_driver *drv); | 512 | int (*remove)(struct cx8802_driver *drv); |
516 | 513 | ||
517 | /* MPEG 8802 -> mini driver - Access for hardware control */ | 514 | /* MPEG 8802 -> mini driver - Access for hardware control */ |