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) | |||
78 | 78 | ||
79 | 79 | ||
80 | static LIST_HEAD(cx8802_devlist); | 80 | static LIST_HEAD(cx8802_devlist); |
81 | static DEFINE_MUTEX(cx8802_mutex); | ||
81 | /* ------------------------------------------------------------------ */ | 82 | /* ------------------------------------------------------------------ */ |
82 | 83 | ||
83 | static int cx8802_start_dma(struct cx8802_dev *dev, | 84 | static int cx8802_start_dma(struct cx8802_dev *dev, |
@@ -474,7 +475,7 @@ static int cx8802_init_common(struct cx8802_dev *dev) | |||
474 | return -EIO; | 475 | return -EIO; |
475 | } | 476 | } |
476 | 477 | ||
477 | pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev); | 478 | dev->pci_rev = dev->pci->revision; |
478 | pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); | 479 | pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); |
479 | printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " | 480 | printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " |
480 | "latency: %d, mmio: 0x%llx\n", dev->core->name, | 481 | "latency: %d, mmio: 0x%llx\n", dev->core->name, |
@@ -624,13 +625,11 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) | |||
624 | 625 | ||
625 | if (drv->advise_acquire) | 626 | if (drv->advise_acquire) |
626 | { | 627 | { |
627 | mutex_lock(&drv->core->lock); | ||
628 | core->active_ref++; | 628 | core->active_ref++; |
629 | if (core->active_type_id == CX88_BOARD_NONE) { | 629 | if (core->active_type_id == CX88_BOARD_NONE) { |
630 | core->active_type_id = drv->type_id; | 630 | core->active_type_id = drv->type_id; |
631 | drv->advise_acquire(drv); | 631 | drv->advise_acquire(drv); |
632 | } | 632 | } |
633 | mutex_unlock(&drv->core->lock); | ||
634 | 633 | ||
635 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); | 634 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); |
636 | } | 635 | } |
@@ -643,14 +642,12 @@ static int cx8802_request_release(struct cx8802_driver *drv) | |||
643 | { | 642 | { |
644 | struct cx88_core *core = drv->core; | 643 | struct cx88_core *core = drv->core; |
645 | 644 | ||
646 | mutex_lock(&drv->core->lock); | ||
647 | if (drv->advise_release && --core->active_ref == 0) | 645 | if (drv->advise_release && --core->active_ref == 0) |
648 | { | 646 | { |
649 | drv->advise_release(drv); | 647 | drv->advise_release(drv); |
650 | core->active_type_id = CX88_BOARD_NONE; | 648 | core->active_type_id = CX88_BOARD_NONE; |
651 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); | 649 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); |
652 | } | 650 | } |
653 | mutex_unlock(&drv->core->lock); | ||
654 | 651 | ||
655 | return 0; | 652 | return 0; |
656 | } | 653 | } |
@@ -693,6 +690,8 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
693 | return err; | 690 | return err; |
694 | } | 691 | } |
695 | 692 | ||
693 | mutex_lock(&cx8802_mutex); | ||
694 | |||
696 | list_for_each_entry(dev, &cx8802_devlist, devlist) { | 695 | list_for_each_entry(dev, &cx8802_devlist, devlist) { |
697 | printk(KERN_INFO | 696 | printk(KERN_INFO |
698 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", | 697 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", |
@@ -702,8 +701,10 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
702 | 701 | ||
703 | /* Bring up a new struct for each driver instance */ | 702 | /* Bring up a new struct for each driver instance */ |
704 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); | 703 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); |
705 | if (driver == NULL) | 704 | if (driver == NULL) { |
706 | return -ENOMEM; | 705 | err = -ENOMEM; |
706 | goto out; | ||
707 | } | ||
707 | 708 | ||
708 | /* Snapshot of the driver registration data */ | 709 | /* Snapshot of the driver registration data */ |
709 | drv->core = dev->core; | 710 | drv->core = dev->core; |
@@ -713,21 +714,23 @@ int cx8802_register_driver(struct cx8802_driver *drv) | |||
713 | drv->request_release = cx8802_request_release; | 714 | drv->request_release = cx8802_request_release; |
714 | memcpy(driver, drv, sizeof(*driver)); | 715 | memcpy(driver, drv, sizeof(*driver)); |
715 | 716 | ||
717 | mutex_lock(&drv->core->lock); | ||
716 | err = drv->probe(driver); | 718 | err = drv->probe(driver); |
717 | if (err == 0) { | 719 | if (err == 0) { |
718 | i++; | 720 | i++; |
719 | mutex_lock(&drv->core->lock); | ||
720 | list_add_tail(&driver->drvlist, &dev->drvlist); | 721 | list_add_tail(&driver->drvlist, &dev->drvlist); |
721 | mutex_unlock(&drv->core->lock); | ||
722 | } else { | 722 | } else { |
723 | printk(KERN_ERR | 723 | printk(KERN_ERR |
724 | "%s/2: cx8802 probe failed, err = %d\n", | 724 | "%s/2: cx8802 probe failed, err = %d\n", |
725 | dev->core->name, err); | 725 | dev->core->name, err); |
726 | } | 726 | } |
727 | 727 | mutex_unlock(&drv->core->lock); | |
728 | } | 728 | } |
729 | 729 | ||
730 | return i ? 0 : -ENODEV; | 730 | err = i ? 0 : -ENODEV; |
731 | out: | ||
732 | mutex_unlock(&cx8802_mutex); | ||
733 | return err; | ||
731 | } | 734 | } |
732 | 735 | ||
733 | int cx8802_unregister_driver(struct cx8802_driver *drv) | 736 | int cx8802_unregister_driver(struct cx8802_driver *drv) |
@@ -741,6 +744,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
741 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", | 744 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", |
742 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | 745 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); |
743 | 746 | ||
747 | mutex_lock(&cx8802_mutex); | ||
748 | |||
744 | list_for_each_entry(dev, &cx8802_devlist, devlist) { | 749 | list_for_each_entry(dev, &cx8802_devlist, devlist) { |
745 | printk(KERN_INFO | 750 | printk(KERN_INFO |
746 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", | 751 | "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", |
@@ -748,6 +753,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
748 | dev->pci->subsystem_device, dev->core->board.name, | 753 | dev->pci->subsystem_device, dev->core->board.name, |
749 | dev->core->boardnr); | 754 | dev->core->boardnr); |
750 | 755 | ||
756 | mutex_lock(&dev->core->lock); | ||
757 | |||
751 | list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) { | 758 | list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) { |
752 | /* only unregister the correct driver type */ | 759 | /* only unregister the correct driver type */ |
753 | if (d->type_id != drv->type_id) | 760 | if (d->type_id != drv->type_id) |
@@ -755,17 +762,18 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) | |||
755 | 762 | ||
756 | err = d->remove(d); | 763 | err = d->remove(d); |
757 | if (err == 0) { | 764 | if (err == 0) { |
758 | mutex_lock(&drv->core->lock); | ||
759 | list_del(&d->drvlist); | 765 | list_del(&d->drvlist); |
760 | mutex_unlock(&drv->core->lock); | ||
761 | kfree(d); | 766 | kfree(d); |
762 | } else | 767 | } else |
763 | printk(KERN_ERR "%s/2: cx8802 driver remove " | 768 | printk(KERN_ERR "%s/2: cx8802 driver remove " |
764 | "failed (%d)\n", dev->core->name, err); | 769 | "failed (%d)\n", dev->core->name, err); |
765 | } | 770 | } |
766 | 771 | ||
772 | mutex_unlock(&dev->core->lock); | ||
767 | } | 773 | } |
768 | 774 | ||
775 | mutex_unlock(&cx8802_mutex); | ||
776 | |||
769 | return err; | 777 | return err; |
770 | } | 778 | } |
771 | 779 | ||
@@ -803,7 +811,9 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, | |||
803 | goto fail_free; | 811 | goto fail_free; |
804 | 812 | ||
805 | INIT_LIST_HEAD(&dev->drvlist); | 813 | INIT_LIST_HEAD(&dev->drvlist); |
814 | mutex_lock(&cx8802_mutex); | ||
806 | list_add_tail(&dev->devlist,&cx8802_devlist); | 815 | list_add_tail(&dev->devlist,&cx8802_devlist); |
816 | mutex_unlock(&cx8802_mutex); | ||
807 | 817 | ||
808 | /* now autoload cx88-dvb or cx88-blackbird */ | 818 | /* now autoload cx88-dvb or cx88-blackbird */ |
809 | request_modules(dev); | 819 | request_modules(dev); |
@@ -827,6 +837,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) | |||
827 | 837 | ||
828 | flush_request_modules(dev); | 838 | flush_request_modules(dev); |
829 | 839 | ||
840 | mutex_lock(&dev->core->lock); | ||
841 | |||
830 | if (!list_empty(&dev->drvlist)) { | 842 | if (!list_empty(&dev->drvlist)) { |
831 | struct cx8802_driver *drv, *tmp; | 843 | struct cx8802_driver *drv, *tmp; |
832 | int err; | 844 | int err; |
@@ -838,9 +850,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) | |||
838 | list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) { | 850 | list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) { |
839 | err = drv->remove(drv); | 851 | err = drv->remove(drv); |
840 | if (err == 0) { | 852 | if (err == 0) { |
841 | mutex_lock(&drv->core->lock); | ||
842 | list_del(&drv->drvlist); | 853 | list_del(&drv->drvlist); |
843 | mutex_unlock(&drv->core->lock); | ||
844 | } else | 854 | } else |
845 | printk(KERN_ERR "%s/2: cx8802 driver remove " | 855 | printk(KERN_ERR "%s/2: cx8802 driver remove " |
846 | "failed (%d)\n", dev->core->name, err); | 856 | "failed (%d)\n", dev->core->name, err); |
@@ -848,6 +858,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) | |||
848 | } | 858 | } |
849 | } | 859 | } |
850 | 860 | ||
861 | mutex_unlock(&dev->core->lock); | ||
862 | |||
851 | /* Destroy any 8802 reference. */ | 863 | /* Destroy any 8802 reference. */ |
852 | dev->core->dvbdev = NULL; | 864 | dev->core->dvbdev = NULL; |
853 | 865 | ||