Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=081c2fc8b9cdd13a2436e8510889293874a33340
Commit:     081c2fc8b9cdd13a2436e8510889293874a33340
Parent:     f0ad90975bc9ff6cd7361b452b31dab7a90084fc
Author:     Trent Piepho <[EMAIL PROTECTED]>
AuthorDate: Sun Oct 14 02:52:17 2007 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Mon Oct 22 12:01:43 2007 -0200

    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 <[EMAIL PROTECTED]>
    Reviewed-by: Michael Krufky <[EMAIL PROTECTED]>
    Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]>
---
 drivers/media/video/cx88/cx88-mpeg.c |   60 ++++++++++++++++-----------------
 drivers/media/video/cx88/cx88.h      |    8 +++--
 2 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/drivers/media/video/cx88/cx88-mpeg.c 
b/drivers/media/video/cx88/cx88-mpeg.c
index 1b14182..11d9865 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);
 
 struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum 
cx88_board_type btype)
 {
-       struct cx8802_dev *h = NULL;
-       struct cx8802_driver *d = NULL;
+       struct cx8802_driver *d;
        struct list_head *list;
-       struct list_head *list2;
-
-       list_for_each(list,&cx8802_devlist) {
-               h = list_entry(list, struct cx8802_dev, devlist);
-               if (h != dev)
-                       continue;
 
-               list_for_each(list2, &h->drvlist.devlist) {
-                       d = list_entry(list2, struct cx8802_driver, devlist);
+       list_for_each(list, &dev->drvlist) {
+               d = list_entry(list, struct cx8802_driver, drvlist);
 
-                       /* only unregister the correct driver type */
-                       if (d->type_id == btype) {
-                               return d;
-                       }
-               }
+               if (d->type_id == btype)
+                       return d;
        }
 
        return NULL;
@@ -717,7 +707,7 @@ int cx8802_register_driver(struct cx8802_driver *drv)
                if (err == 0) {
                        i++;
                        mutex_lock(&drv->core->lock);
-                       list_add_tail(&driver->devlist,&h->drvlist.devlist);
+                       list_add_tail(&driver->drvlist, &h->drvlist);
                        mutex_unlock(&drv->core->lock);
                } else {
                        printk(KERN_ERR
@@ -757,8 +747,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
                       h->pci->subsystem_device, h->core->board.name,
                       h->core->boardnr);
 
-               list_for_each_safe(list2, q, &h->drvlist.devlist) {
-                       d = list_entry(list2, struct cx8802_driver, devlist);
+               list_for_each_safe(list2, q, &h->drvlist) {
+                       d = list_entry(list2, struct cx8802_driver, drvlist);
 
                        /* only unregister the correct driver type */
                        if (d->type_id != drv->type_id)
@@ -772,7 +762,6 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
                        } else
                                printk(KERN_ERR "%s/2: cx8802 driver remove "
                                       "failed (%d)\n", h->core->name, err);
-
                }
 
        }
@@ -810,7 +799,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
        if (err != 0)
                goto fail_free;
 
-       INIT_LIST_HEAD(&dev->drvlist.devlist);
+       INIT_LIST_HEAD(&dev->drvlist);
        list_add_tail(&dev->devlist,&cx8802_devlist);
 
        /* 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,
 static void __devexit cx8802_remove(struct pci_dev *pci_dev)
 {
        struct cx8802_dev *dev;
-       struct cx8802_driver *h;
-       struct list_head *list;
 
        dev = pci_get_drvdata(pci_dev);
 
        dprintk( 1, "%s\n", __FUNCTION__);
 
-       list_for_each(list,&dev->drvlist.devlist) {
-               h = list_entry(list, struct cx8802_driver, devlist);
-               dprintk( 1, " ->driver\n");
-               if (h->remove == NULL) {
-                       printk(KERN_ERR "%s .. skipping driver, no probe 
function\n", __FUNCTION__);
-                       continue;
+       if (!list_empty(&dev->drvlist)) {
+               struct list_head *list, *tmp;
+               struct cx8802_driver *drv;
+               int err;
+
+               printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
+                      "while cx8802 sub-drivers still loaded?!\n",
+                      dev->core->name);
+
+               list_for_each_safe(list, tmp, &dev->drvlist) {
+                       drv = list_entry(list, struct cx8802_driver, drvlist);
+
+                       err = drv->remove(drv);
+                       if (err == 0) {
+                               mutex_lock(&drv->core->lock);
+                               list_del(list);
+                               mutex_unlock(&drv->core->lock);
+                       } else
+                               printk(KERN_ERR "%s/2: cx8802 driver remove "
+                                      "failed (%d)\n", dev->core->name, err);
                }
-               printk(KERN_INFO "%s .. Removing driver type %d\n", 
__FUNCTION__, h->type_id);
-               cx8802_unregister_driver(h);
-               list_del(&dev->drvlist.devlist);
        }
 
        /* Destroy any 8802 reference. */
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 2e0911b..eb296bd 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -412,7 +412,9 @@ struct cx8802_suspend_state {
 
 struct cx8802_driver {
        struct cx88_core *core;
-       struct list_head devlist;
+
+       /* List of drivers attached to device */
+       struct list_head drvlist;
 
        /* Type of driver and access required */
        enum cx88_board_type type_id;
@@ -478,8 +480,8 @@ struct cx8802_dev {
        unsigned char              ts_gen_cntrl;
 
        /* List of attached drivers */
-       struct cx8802_driver       drvlist;
-       struct work_struct request_module_wk;
+       struct list_head           drvlist;
+       struct work_struct         request_module_wk;
 };
 
 /* ----------------------------------------------------------- */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to