The driver wasn't releasing the requested resources on error, so make that work. Signed-off-by: Felipe Balbi <me@xxxxxxxxxxxxxxx> --- drivers/usb/host/ehci-omap.c | 82 ++++++++++++++++++++++++++++++++++-------- 1 files changed, 67 insertions(+), 15 deletions(-) diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 35c645d..b058ada 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -262,6 +262,7 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) { struct ehci_omap_clock_defs *ehci_clocks; unsigned long timeout = jiffies + msecs_to_jiffies(100); + int ret = 0; dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n"); @@ -293,7 +294,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) if (time_after(timeout, jiffies)) { dev_dbg(hcd->self.controller, "operation timed out\n"); - return -EINVAL; + ret = -EINVAL; + goto err_idlest2; } } /* End DPLL5 programming */ @@ -317,20 +319,26 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) /* Enable Clocks for USBHOST */ ehci_clocks->usbhost_ick_clk = clk_get(&dev->dev, USBHOST_ICKL); - if (IS_ERR(ehci_clocks->usbhost_ick_clk)) - return PTR_ERR(ehci_clocks->usbhost_ick_clk); + if (IS_ERR(ehci_clocks->usbhost_ick_clk)) { + ret = PTR_ERR(ehci_clocks->usbhost_ick_clk); + goto err_host_ick; + } clk_enable(ehci_clocks->usbhost_ick_clk); ehci_clocks->usbhost2_120m_fck_clk = clk_get(&dev->dev, USBHOST_120M_FCLK); - if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk)) - return PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk); + if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk)) { + ret = PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk); + goto err_host_120m_fck; + } clk_enable(ehci_clocks->usbhost2_120m_fck_clk); ehci_clocks->usbhost1_48m_fck_clk = clk_get(&dev->dev, USBHOST_48M_FCLK); - if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk)) - return PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk); + if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk)) { + ret = PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk); + goto err_host_48m_fck; + } clk_enable(ehci_clocks->usbhost1_48m_fck_clk); @@ -346,13 +354,17 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) /* Configure TLL for 60Mhz clk for ULPI */ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK); - if (IS_ERR(ehci_clocks->usbtll_fck_clk)) - return PTR_ERR(ehci_clocks->usbtll_fck_clk); + if (IS_ERR(ehci_clocks->usbtll_fck_clk)) { + ret = PTR_ERR(ehci_clocks->usbtll_fck_clk); + goto err_tll_fck; + } clk_enable(ehci_clocks->usbtll_fck_clk); ehci_clocks->usbtll_ick_clk = clk_get(&dev->dev, USBHOST_TLL_ICKL); - if (IS_ERR(ehci_clocks->usbtll_ick_clk)) - return PTR_ERR(ehci_clocks->usbtll_ick_clk); + if (IS_ERR(ehci_clocks->usbtll_ick_clk)) { + ret = PTR_ERR(ehci_clocks->usbtll_ick_clk); + goto err_tll_ick; + } clk_enable(ehci_clocks->usbtll_ick_clk); /* Disable Auto Idle of USBTLL */ @@ -366,7 +378,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) if (time_after(timeout, jiffies)) { dev_dbg(hcd->self.controller, "operation timed out\n"); - return -EINVAL; + ret = -EINVAL; + goto err_idlest3; } } @@ -381,7 +394,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) if (time_after(timeout, jiffies)) { dev_dbg(hcd->self.controller, "operation timed out\n"); - return -EINVAL; + ret = -EINVAL; + goto err_sys_status; } } @@ -418,7 +432,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) if (time_after(timeout, jiffies)) { dev_dbg(hcd->self.controller, "operation timed out\n"); - return -EINVAL; + ret = -EINVAL; + goto err_ulpi_bypass; } } @@ -461,13 +476,50 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) if (time_after(timeout, jiffies)) { dev_dbg(hcd->self.controller, "operation timed out\n"); - return -EINVAL; + ret = -EINVAL; + goto err_ulpi_control; } } #endif return 0; + +#ifdef VBUS_INTERNAL_CHARGEPUMP_HACK +err_ulpi_control: +#endif +#ifdef CONFIG_OMAP_EHCI_PHY_MODE +err_ulpi_bypass: +#endif +err_sys_status: +err_idlest3: + clk_disable(ehci_clocks->usbtll_ick_clk); + clk_put(ehci_clocks->usbtll_ick_clk); + +err_tll_ick: + clk_disable(ehci_clocks->usbtll_fck_clk); + clk_put(ehci_clocks->usbtll_fck_clk); + +err_tll_fck: + clk_disable(ehci_clocks->usbhost1_48m_fck_clk); + clk_put(ehci_clocks->usbhost1_48m_fck_clk); + +#ifdef EXTERNAL_PHY_RESET + gpio_free(EXT_PHY_RESET_GPIO_PORT1); + gpio_free(EXT_PHY_RESET_GPIO_PORT2); +#endif + +err_host_48m_fck: + clk_disable(ehci_clocks->usbhost2_120m_fck_clk); + clk_put(ehci_clocks->usbhost2_120m_fck_clk); + +err_host_120m_fck: + clk_disable(ehci_clocks->usbhost_ick_clk); + clk_put(ehci_clocks->usbhost_ick_clk); + +err_host_ick: +err_idlest2: + return ret; } static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd) -- 1.6.1.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html