diff options
author | Dan Carpenter <error27@gmail.com> | 2010-10-05 12:55:34 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:22:04 -0400 |
commit | 319feaabb6c7ccd90da6e3207563c265da7d21ae (patch) | |
tree | 07998aec5e760ec294566b5facac1ff60d0eb6c8 /drivers/usb/gadget | |
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/gadget')
-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) | |||
1745 | pci_resource_len (pdev, 0)); | 1745 | pci_resource_len (pdev, 0)); |
1746 | if (dev->enabled) | 1746 | if (dev->enabled) |
1747 | pci_disable_device(pdev); | 1747 | pci_disable_device(pdev); |
1748 | device_unregister(&dev->gadget.dev); | 1748 | if (dev->registered) |
1749 | device_unregister(&dev->gadget.dev); | ||
1749 | 1750 | ||
1750 | pci_set_drvdata(pdev, NULL); | 1751 | pci_set_drvdata(pdev, NULL); |
1751 | dev->regs = NULL; | 1752 | dev->regs = NULL; |
@@ -1775,7 +1776,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1775 | if (!pdev->irq) { | 1776 | if (!pdev->irq) { |
1776 | printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev)); | 1777 | printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev)); |
1777 | retval = -ENODEV; | 1778 | retval = -ENODEV; |
1778 | goto done; | 1779 | goto err; |
1779 | } | 1780 | } |
1780 | 1781 | ||
1781 | /* alloc, and start init */ | 1782 | /* alloc, and start init */ |
@@ -1783,7 +1784,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1783 | if (dev == NULL){ | 1784 | if (dev == NULL){ |
1784 | pr_debug("enomem %s\n", pci_name(pdev)); | 1785 | pr_debug("enomem %s\n", pci_name(pdev)); |
1785 | retval = -ENOMEM; | 1786 | retval = -ENOMEM; |
1786 | goto done; | 1787 | goto err; |
1787 | } | 1788 | } |
1788 | 1789 | ||
1789 | spin_lock_init(&dev->lock); | 1790 | spin_lock_init(&dev->lock); |
@@ -1801,7 +1802,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1801 | retval = pci_enable_device(pdev); | 1802 | retval = pci_enable_device(pdev); |
1802 | if (retval < 0) { | 1803 | if (retval < 0) { |
1803 | DBG(dev, "can't enable, %d\n", retval); | 1804 | DBG(dev, "can't enable, %d\n", retval); |
1804 | goto done; | 1805 | goto err; |
1805 | } | 1806 | } |
1806 | dev->enabled = 1; | 1807 | dev->enabled = 1; |
1807 | 1808 | ||
@@ -1810,7 +1811,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1810 | if (!request_mem_region(resource, len, driver_name)) { | 1811 | if (!request_mem_region(resource, len, driver_name)) { |
1811 | DBG(dev, "controller already in use\n"); | 1812 | DBG(dev, "controller already in use\n"); |
1812 | retval = -EBUSY; | 1813 | retval = -EBUSY; |
1813 | goto done; | 1814 | goto err; |
1814 | } | 1815 | } |
1815 | dev->got_region = 1; | 1816 | dev->got_region = 1; |
1816 | 1817 | ||
@@ -1818,7 +1819,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1818 | if (base == NULL) { | 1819 | if (base == NULL) { |
1819 | DBG(dev, "can't map memory\n"); | 1820 | DBG(dev, "can't map memory\n"); |
1820 | retval = -EFAULT; | 1821 | retval = -EFAULT; |
1821 | goto done; | 1822 | goto err; |
1822 | } | 1823 | } |
1823 | dev->regs = (struct goku_udc_regs __iomem *) base; | 1824 | dev->regs = (struct goku_udc_regs __iomem *) base; |
1824 | 1825 | ||
@@ -1834,7 +1835,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1834 | driver_name, dev) != 0) { | 1835 | driver_name, dev) != 0) { |
1835 | DBG(dev, "request interrupt %d failed\n", pdev->irq); | 1836 | DBG(dev, "request interrupt %d failed\n", pdev->irq); |
1836 | retval = -EBUSY; | 1837 | retval = -EBUSY; |
1837 | goto done; | 1838 | goto err; |
1838 | } | 1839 | } |
1839 | dev->got_irq = 1; | 1840 | dev->got_irq = 1; |
1840 | if (use_dma) | 1841 | if (use_dma) |
@@ -1845,13 +1846,16 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1845 | create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev); | 1846 | create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev); |
1846 | #endif | 1847 | #endif |
1847 | 1848 | ||
1848 | /* done */ | ||
1849 | the_controller = dev; | 1849 | the_controller = dev; |
1850 | retval = device_register(&dev->gadget.dev); | 1850 | retval = device_register(&dev->gadget.dev); |
1851 | if (retval == 0) | 1851 | if (retval) { |
1852 | return 0; | 1852 | put_device(&dev->gadget.dev); |
1853 | goto err; | ||
1854 | } | ||
1855 | dev->registered = 1; | ||
1856 | return 0; | ||
1853 | 1857 | ||
1854 | done: | 1858 | err: |
1855 | if (dev) | 1859 | if (dev) |
1856 | goku_remove (pdev); | 1860 | goku_remove (pdev); |
1857 | return retval; | 1861 | return retval; |