mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 01:54:00 +00:00
musb_core: fix musb_init_controller() error cleanup path
This function forgets to call usb_remove_hcd() or musb_gadget_cleanup() iff sysfs_create_group() fails. [ felipe.balbi@nokia.com : review the entire error path not only when we fail hcd or gadget ] Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
c6a39eec9d
commit
34e2beb2c8
@ -1878,8 +1878,10 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
|
|||||||
*/
|
*/
|
||||||
if (!plat) {
|
if (!plat) {
|
||||||
dev_dbg(dev, "no platform_data?\n");
|
dev_dbg(dev, "no platform_data?\n");
|
||||||
return -ENODEV;
|
status = -ENODEV;
|
||||||
|
goto fail0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (plat->mode) {
|
switch (plat->mode) {
|
||||||
case MUSB_HOST:
|
case MUSB_HOST:
|
||||||
#ifdef CONFIG_USB_MUSB_HDRC_HCD
|
#ifdef CONFIG_USB_MUSB_HDRC_HCD
|
||||||
@ -1901,13 +1903,16 @@ bad_config:
|
|||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
dev_err(dev, "incompatible Kconfig role setting\n");
|
dev_err(dev, "incompatible Kconfig role setting\n");
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto fail0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate */
|
/* allocate */
|
||||||
musb = allocate_instance(dev, plat->config, ctrl);
|
musb = allocate_instance(dev, plat->config, ctrl);
|
||||||
if (!musb)
|
if (!musb) {
|
||||||
return -ENOMEM;
|
status = -ENOMEM;
|
||||||
|
goto fail0;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_init(&musb->lock);
|
spin_lock_init(&musb->lock);
|
||||||
musb->board_mode = plat->mode;
|
musb->board_mode = plat->mode;
|
||||||
@ -1925,7 +1930,7 @@ bad_config:
|
|||||||
if (IS_ERR(musb->clock)) {
|
if (IS_ERR(musb->clock)) {
|
||||||
status = PTR_ERR(musb->clock);
|
status = PTR_ERR(musb->clock);
|
||||||
musb->clock = NULL;
|
musb->clock = NULL;
|
||||||
goto fail;
|
goto fail1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1944,12 +1949,12 @@ bad_config:
|
|||||||
*/
|
*/
|
||||||
musb->isr = generic_interrupt;
|
musb->isr = generic_interrupt;
|
||||||
status = musb_platform_init(musb);
|
status = musb_platform_init(musb);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto fail;
|
goto fail2;
|
||||||
|
|
||||||
if (!musb->isr) {
|
if (!musb->isr) {
|
||||||
status = -ENODEV;
|
status = -ENODEV;
|
||||||
goto fail2;
|
goto fail3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_MUSB_PIO_ONLY
|
#ifndef CONFIG_MUSB_PIO_ONLY
|
||||||
@ -1975,7 +1980,7 @@ bad_config:
|
|||||||
? MUSB_CONTROLLER_MHDRC
|
? MUSB_CONTROLLER_MHDRC
|
||||||
: MUSB_CONTROLLER_HDRC, musb);
|
: MUSB_CONTROLLER_HDRC, musb);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto fail2;
|
goto fail3;
|
||||||
|
|
||||||
#ifdef CONFIG_USB_MUSB_OTG
|
#ifdef CONFIG_USB_MUSB_OTG
|
||||||
setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
|
setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
|
||||||
@ -1988,7 +1993,7 @@ bad_config:
|
|||||||
if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
|
if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
|
||||||
dev_err(dev, "request_irq %d failed!\n", nIrq);
|
dev_err(dev, "request_irq %d failed!\n", nIrq);
|
||||||
status = -ENODEV;
|
status = -ENODEV;
|
||||||
goto fail2;
|
goto fail3;
|
||||||
}
|
}
|
||||||
musb->nIrq = nIrq;
|
musb->nIrq = nIrq;
|
||||||
/* FIXME this handles wakeup irqs wrong */
|
/* FIXME this handles wakeup irqs wrong */
|
||||||
@ -2050,12 +2055,12 @@ bad_config:
|
|||||||
|
|
||||||
}
|
}
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto fail2;
|
goto fail3;
|
||||||
|
|
||||||
#ifdef CONFIG_SYSFS
|
#ifdef CONFIG_SYSFS
|
||||||
status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
|
status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
|
||||||
if (status)
|
if (status)
|
||||||
goto fail2;
|
goto fail4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
|
dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
|
||||||
@ -2072,17 +2077,29 @@ bad_config:
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail2:
|
fail4:
|
||||||
|
if (!is_otg_enabled(musb) && is_host_enabled(musb))
|
||||||
|
usb_remove_hcd(musb_to_hcd(musb));
|
||||||
|
else
|
||||||
|
musb_gadget_cleanup(musb);
|
||||||
|
|
||||||
|
fail3:
|
||||||
|
if (musb->irq_wake)
|
||||||
|
device_init_wakeup(dev, 0);
|
||||||
musb_platform_exit(musb);
|
musb_platform_exit(musb);
|
||||||
fail:
|
|
||||||
|
fail2:
|
||||||
|
if (musb->clock)
|
||||||
|
clk_put(musb->clock);
|
||||||
|
|
||||||
|
fail1:
|
||||||
dev_err(musb->controller,
|
dev_err(musb->controller,
|
||||||
"musb_init_controller failed with status %d\n", status);
|
"musb_init_controller failed with status %d\n", status);
|
||||||
|
|
||||||
if (musb->clock)
|
|
||||||
clk_put(musb->clock);
|
|
||||||
device_init_wakeup(dev, 0);
|
|
||||||
musb_free(musb);
|
musb_free(musb);
|
||||||
|
|
||||||
|
fail0:
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user