diff options
author | Valentine Barshak <valentine.barshak@cogentembedded.com> | 2013-12-04 01:42:21 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-12-09 06:00:51 +0400 |
commit | 103e127d1f8f985e8a662da6537ebc5e08902ee3 (patch) | |
tree | a9ae5594b47919a5bb652172abbb61c9e61d66b0 /drivers/usb/core | |
parent | e5fc70d5ccc3d005bb038c0275ffdf57a34b1496 (diff) | |
download | linux-103e127d1f8f985e8a662da6537ebc5e08902ee3.tar.xz |
usb: hcd: Remove USB phy if needed
This adds remove_phy flag to the HCD structure. If the flag is
set and if hcd->phy is valid, the phy is shutdown and released
whenever usb_add_hcd fails or usb_hcd_remove is called.
This can be used by the HCD drivers to auto-remove
the external USB phy when it is no longer needed.
Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hcd.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6bffb8c87bc9..7527c8e4ec64 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -44,6 +44,7 @@ #include <linux/usb.h> #include <linux/usb/hcd.h> +#include <linux/usb/phy.h> #include "usb.h" @@ -2603,7 +2604,7 @@ int usb_add_hcd(struct usb_hcd *hcd, */ if ((retval = hcd_buffer_create(hcd)) != 0) { dev_dbg(hcd->self.controller, "pool alloc failed\n"); - return retval; + goto err_remove_phy; } if ((retval = usb_register_bus(&hcd->self)) < 0) @@ -2734,6 +2735,12 @@ err_allocate_root_hub: usb_deregister_bus(&hcd->self); err_register_bus: hcd_buffer_destroy(hcd); +err_remove_phy: + if (hcd->remove_phy && hcd->phy) { + usb_phy_shutdown(hcd->phy); + usb_put_phy(hcd->phy); + hcd->phy = NULL; + } return retval; } EXPORT_SYMBOL_GPL(usb_add_hcd); @@ -2806,6 +2813,11 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_put_dev(hcd->self.root_hub); usb_deregister_bus(&hcd->self); hcd_buffer_destroy(hcd); + if (hcd->remove_phy && hcd->phy) { + usb_phy_shutdown(hcd->phy); + usb_put_phy(hcd->phy); + hcd->phy = NULL; + } } EXPORT_SYMBOL_GPL(usb_remove_hcd); |