diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-mpeg.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index addf9545e9bf..1a7b983f8297 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -78,6 +78,7 @@ static void flush_request_modules(struct cx8802_dev *dev) static LIST_HEAD(cx8802_devlist); +static DEFINE_MUTEX(cx8802_mutex); /* ------------------------------------------------------------------ */ static int cx8802_start_dma(struct cx8802_dev *dev, @@ -474,7 +475,7 @@ static int cx8802_init_common(struct cx8802_dev *dev) return -EIO; } - pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev); + dev->pci_rev = dev->pci->revision; pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%llx\n", dev->core->name, @@ -624,13 +625,11 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) if (drv->advise_acquire) { - mutex_lock(&drv->core->lock); core->active_ref++; if (core->active_type_id == CX88_BOARD_NONE) { core->active_type_id = drv->type_id; drv->advise_acquire(drv); } - mutex_unlock(&drv->core->lock); mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); } @@ -643,14 +642,12 @@ static int cx8802_request_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; - mutex_lock(&drv->core->lock); if (drv->advise_release && --core->active_ref == 0) { drv->advise_release(drv); core->active_type_id = CX88_BOARD_NONE; mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); } - mutex_unlock(&drv->core->lock); return 0; } @@ -693,6 +690,8 @@ int cx8802_register_driver(struct cx8802_driver *drv) return err; } + mutex_lock(&cx8802_mutex); + list_for_each_entry(dev, &cx8802_devlist, devlist) { printk(KERN_INFO "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", @@ -702,8 +701,10 @@ int cx8802_register_driver(struct cx8802_driver *drv) /* Bring up a new struct for each driver instance */ driver = kzalloc(sizeof(*drv),GFP_KERNEL); - if (driver == NULL) - return -ENOMEM; + if (driver == NULL) { + err = -ENOMEM; + goto out; + } /* Snapshot of the driver registration data */ drv->core = dev->core; @@ -713,21 +714,23 @@ int cx8802_register_driver(struct cx8802_driver *drv) drv->request_release = cx8802_request_release; memcpy(driver, drv, sizeof(*driver)); + mutex_lock(&drv->core->lock); err = drv->probe(driver); if (err == 0) { i++; - mutex_lock(&drv->core->lock); list_add_tail(&driver->drvlist, &dev->drvlist); - mutex_unlock(&drv->core->lock); } else { printk(KERN_ERR "%s/2: cx8802 probe failed, err = %d\n", dev->core->name, err); } - + mutex_unlock(&drv->core->lock); } - return i ? 0 : -ENODEV; + err = i ? 0 : -ENODEV; +out: + mutex_unlock(&cx8802_mutex); + return err; } int cx8802_unregister_driver(struct cx8802_driver *drv) @@ -741,6 +744,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); + mutex_lock(&cx8802_mutex); + list_for_each_entry(dev, &cx8802_devlist, devlist) { printk(KERN_INFO "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", @@ -748,6 +753,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) dev->pci->subsystem_device, dev->core->board.name, dev->core->boardnr); + mutex_lock(&dev->core->lock); + list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) { /* only unregister the correct driver type */ if (d->type_id != drv->type_id) @@ -755,17 +762,18 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) err = d->remove(d); if (err == 0) { - mutex_lock(&drv->core->lock); list_del(&d->drvlist); - mutex_unlock(&drv->core->lock); kfree(d); } else printk(KERN_ERR "%s/2: cx8802 driver remove " "failed (%d)\n", dev->core->name, err); } + mutex_unlock(&dev->core->lock); } + mutex_unlock(&cx8802_mutex); + return err; } @@ -803,7 +811,9 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, goto fail_free; INIT_LIST_HEAD(&dev->drvlist); + mutex_lock(&cx8802_mutex); list_add_tail(&dev->devlist,&cx8802_devlist); + mutex_unlock(&cx8802_mutex); /* now autoload cx88-dvb or cx88-blackbird */ request_modules(dev); @@ -827,6 +837,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) flush_request_modules(dev); + mutex_lock(&dev->core->lock); + if (!list_empty(&dev->drvlist)) { struct cx8802_driver *drv, *tmp; int err; @@ -838,9 +850,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) { err = drv->remove(drv); if (err == 0) { - mutex_lock(&drv->core->lock); list_del(&drv->drvlist); - mutex_unlock(&drv->core->lock); } else printk(KERN_ERR "%s/2: cx8802 driver remove " "failed (%d)\n", dev->core->name, err); @@ -848,6 +858,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) } } + mutex_unlock(&dev->core->lock); + /* Destroy any 8802 reference. */ dev->core->dvbdev = NULL; |