summaryrefslogtreecommitdiff
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorValentine Barshak <valentine.barshak@cogentembedded.com>2013-12-04 01:42:21 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-12-09 06:00:51 +0400
commit103e127d1f8f985e8a662da6537ebc5e08902ee3 (patch)
treea9ae5594b47919a5bb652172abbb61c9e61d66b0 /drivers/usb/core
parente5fc70d5ccc3d005bb038c0275ffdf57a34b1496 (diff)
downloadlinux-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.c14
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);