aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88/cx88-mpeg.c
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2007-10-14 01:52:17 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-22 10:01:43 -0400
commit081c2fc8b9cdd13a2436e8510889293874a33340 (patch)
tree0eee36eb0d0de0a578082995027ca2832025964a /drivers/media/video/cx88/cx88-mpeg.c
parentf0ad90975bc9ff6cd7361b452b31dab7a90084fc (diff)
V4L/DVB (6334): cx88: Change (struct cx8802_dev)->drvlist to a list_head and fix bugs
It was a struct cx8802_driver for no apparent reason. Nothing uses a cx8802_driver in the cx8802_dev struct. The only field that was used was devlist, a list_head. The code in cx8802_remove() that removed any loaded sub-drivers was broken. It would delete the current list entry, but didn't use list_for_each_safe. It also called list_del() on the list _head_ inside the list_for_each loop? It would crash if it was run, which I don't think can ever happen. Since the cx8802 sub-drivers use the cx8802 driver, they have to be unloaded first. So there isn't any way for a sub-driver to still be loaded when cx8802_remove() is called... Except maybe with PCI hot-plug, if one removes the PCI card while the drivers are loaded? So I left some code in to handle that if it's actually possible. It will remove the sub-drivers from the device cx8802_remove() was called on, and only that device. If one has two DVB cards and unplugs one, there is no reason to unload the DVB drivers for both cards. I have no way to test this, but it can't be worse than what was there before. cx8802_get_driver() is passed a cx8802_dev pointer and looks for the requested driver on that device. It first loops over the cx8802 device list looking for the device it was passed, which is pointless. It doesn't need to find the device pointer in the list, as it already has the pointer. The list_head in the cx8802_driver struct, which joins all the _drivers_ attached to a device, was named devlist. Changed that to drvlist, since the devlist is used for a list of _devices_ in other cx8802 structs. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Reviewed-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx88/cx88-mpeg.c')
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c60
1 files changed, 29 insertions, 31 deletions
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 1b1418241b4..11d9865e34f 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -594,24 +594,14 @@ EXPORT_SYMBOL(cx8802_get_device);
594 594
595struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) 595struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
596{ 596{
597 struct cx8802_dev *h = NULL; 597 struct cx8802_driver *d;
598 struct cx8802_driver *d = NULL;
599 struct list_head *list; 598 struct list_head *list;
600 struct list_head *list2;
601
602 list_for_each(list,&cx8802_devlist) {
603 h = list_entry(list, struct cx8802_dev, devlist);
604 if (h != dev)
605 continue;
606 599
607 list_for_each(list2, &h->drvlist.devlist) { 600 list_for_each(list, &dev->drvlist) {
608 d = list_entry(list2, struct cx8802_driver, devlist); 601 d = list_entry(list, struct cx8802_driver, drvlist);
609 602
610 /* only unregister the correct driver type */ 603 if (d->type_id == btype)
611 if (d->type_id == btype) { 604 return d;
612 return d;
613 }
614 }
615 } 605 }
616 606
617 return NULL; 607 return NULL;
@@ -717,7 +707,7 @@ int cx8802_register_driver(struct cx8802_driver *drv)
717 if (err == 0) { 707 if (err == 0) {
718 i++; 708 i++;
719 mutex_lock(&drv->core->lock); 709 mutex_lock(&drv->core->lock);
720 list_add_tail(&driver->devlist,&h->drvlist.devlist); 710 list_add_tail(&driver->drvlist, &h->drvlist);
721 mutex_unlock(&drv->core->lock); 711 mutex_unlock(&drv->core->lock);
722 } else { 712 } else {
723 printk(KERN_ERR 713 printk(KERN_ERR
@@ -757,8 +747,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
757 h->pci->subsystem_device, h->core->board.name, 747 h->pci->subsystem_device, h->core->board.name,
758 h->core->boardnr); 748 h->core->boardnr);
759 749
760 list_for_each_safe(list2, q, &h->drvlist.devlist) { 750 list_for_each_safe(list2, q, &h->drvlist) {
761 d = list_entry(list2, struct cx8802_driver, devlist); 751 d = list_entry(list2, struct cx8802_driver, drvlist);
762 752
763 /* only unregister the correct driver type */ 753 /* only unregister the correct driver type */
764 if (d->type_id != drv->type_id) 754 if (d->type_id != drv->type_id)
@@ -772,7 +762,6 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
772 } else 762 } else
773 printk(KERN_ERR "%s/2: cx8802 driver remove " 763 printk(KERN_ERR "%s/2: cx8802 driver remove "
774 "failed (%d)\n", h->core->name, err); 764 "failed (%d)\n", h->core->name, err);
775
776 } 765 }
777 766
778 } 767 }
@@ -810,7 +799,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
810 if (err != 0) 799 if (err != 0)
811 goto fail_free; 800 goto fail_free;
812 801
813 INIT_LIST_HEAD(&dev->drvlist.devlist); 802 INIT_LIST_HEAD(&dev->drvlist);
814 list_add_tail(&dev->devlist,&cx8802_devlist); 803 list_add_tail(&dev->devlist,&cx8802_devlist);
815 804
816 /* Maintain a reference so cx88-video can query the 8802 device. */ 805 /* Maintain a reference so cx88-video can query the 8802 device. */
@@ -830,23 +819,32 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
830static void __devexit cx8802_remove(struct pci_dev *pci_dev) 819static void __devexit cx8802_remove(struct pci_dev *pci_dev)
831{ 820{
832 struct cx8802_dev *dev; 821 struct cx8802_dev *dev;
833 struct cx8802_driver *h;
834 struct list_head *list;
835 822
836 dev = pci_get_drvdata(pci_dev); 823 dev = pci_get_drvdata(pci_dev);
837 824
838 dprintk( 1, "%s\n", __FUNCTION__); 825 dprintk( 1, "%s\n", __FUNCTION__);
839 826
840 list_for_each(list,&dev->drvlist.devlist) { 827 if (!list_empty(&dev->drvlist)) {
841 h = list_entry(list, struct cx8802_driver, devlist); 828 struct list_head *list, *tmp;
842 dprintk( 1, " ->driver\n"); 829 struct cx8802_driver *drv;
843 if (h->remove == NULL) { 830 int err;
844 printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__); 831
845 continue; 832 printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
833 "while cx8802 sub-drivers still loaded?!\n",
834 dev->core->name);
835
836 list_for_each_safe(list, tmp, &dev->drvlist) {
837 drv = list_entry(list, struct cx8802_driver, drvlist);
838
839 err = drv->remove(drv);
840 if (err == 0) {
841 mutex_lock(&drv->core->lock);
842 list_del(list);
843 mutex_unlock(&drv->core->lock);
844 } else
845 printk(KERN_ERR "%s/2: cx8802 driver remove "
846 "failed (%d)\n", dev->core->name, err);
846 } 847 }
847 printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
848 cx8802_unregister_driver(h);
849 list_del(&dev->drvlist.devlist);
850 } 848 }
851 849
852 /* Destroy any 8802 reference. */ 850 /* Destroy any 8802 reference. */