]> git.baikalelectronics.ru Git - kernel.git/commitdiff
usb: gadget: goku_udc: Fix error path
authorDan Carpenter <error27@gmail.com>
Tue, 5 Oct 2010 16:55:34 +0000 (18:55 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 22 Oct 2010 17:22:04 +0000 (10:22 -0700)
This is based on an initial patch by Rahul Ruikar.

The goku_remove() function can be called before device_register() so it
can call device_unregister() improperly.  Also if the call to
device_register() fails we need to call put_device().

As I was changing the error handling in goku_probe(), I noticed that
the label was "done" but actually if the function succeeds we return
earlier.  I renamed the error path to "err" instead of "done."

Reported-by: Rahul Ruikar <rahul.ruikar@gmail.com>
Signed-off-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/goku_udc.c

index 49fbd4dbeb94a685426de1e3aa36945c204df952..48a760220baf992c48541f2cae822943690bae5c 100644 (file)
@@ -1745,7 +1745,8 @@ static void goku_remove(struct pci_dev *pdev)
                                pci_resource_len (pdev, 0));
        if (dev->enabled)
                pci_disable_device(pdev);
-       device_unregister(&dev->gadget.dev);
+       if (dev->registered)
+               device_unregister(&dev->gadget.dev);
 
        pci_set_drvdata(pdev, NULL);
        dev->regs = NULL;
@@ -1775,7 +1776,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!pdev->irq) {
                printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
                retval = -ENODEV;
-               goto done;
+               goto err;
        }
 
        /* alloc, and start init */
@@ -1783,7 +1784,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (dev == NULL){
                pr_debug("enomem %s\n", pci_name(pdev));
                retval = -ENOMEM;
-               goto done;
+               goto err;
        }
 
        spin_lock_init(&dev->lock);
@@ -1801,7 +1802,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        retval = pci_enable_device(pdev);
        if (retval < 0) {
                DBG(dev, "can't enable, %d\n", retval);
-               goto done;
+               goto err;
        }
        dev->enabled = 1;
 
@@ -1810,7 +1811,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!request_mem_region(resource, len, driver_name)) {
                DBG(dev, "controller already in use\n");
                retval = -EBUSY;
-               goto done;
+               goto err;
        }
        dev->got_region = 1;
 
@@ -1818,7 +1819,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (base == NULL) {
                DBG(dev, "can't map memory\n");
                retval = -EFAULT;
-               goto done;
+               goto err;
        }
        dev->regs = (struct goku_udc_regs __iomem *) base;
 
@@ -1834,7 +1835,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                        driver_name, dev) != 0) {
                DBG(dev, "request interrupt %d failed\n", pdev->irq);
                retval = -EBUSY;
-               goto done;
+               goto err;
        }
        dev->got_irq = 1;
        if (use_dma)
@@ -1845,13 +1846,16 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 #endif
 
-       /* done */
        the_controller = dev;
        retval = device_register(&dev->gadget.dev);
-       if (retval == 0)
-               return 0;
+       if (retval) {
+               put_device(&dev->gadget.dev);
+               goto err;
+       }
+       dev->registered = 1;
+       return 0;
 
-done:
+err:
        if (dev)
                goku_remove (pdev);
        return retval;