diff options
author | Dan Carpenter <error27@gmail.com> | 2010-10-05 18:55:34 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 10:22:04 -0700 |
commit | 319feaabb6c7ccd90da6e3207563c265da7d21ae (patch) | |
tree | 07998aec5e760ec294566b5facac1ff60d0eb6c8 /drivers/usb | |
parent | d0cc3d4100e829d726d7c0fbf5b7b8d2146f60ba (diff) |
usb: gadget: goku_udc: Fix error path
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/goku_udc.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 49fbd4dbeb94..48a760220baf 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -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; |