diff options
| -rw-r--r-- | drivers/usb/core/port.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 62036faf56c0..9347ade7d5fe 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | 21 | ||
| 22 | #include "hub.h" | 22 | #include "hub.h" |
| 23 | 23 | ||
| 24 | static int usb_port_block_power_off; | ||
| 25 | |||
| 24 | static const struct attribute_group *port_dev_group[]; | 26 | static const struct attribute_group *port_dev_group[]; |
| 25 | 27 | ||
| 26 | static ssize_t connect_type_show(struct device *dev, | 28 | static ssize_t connect_type_show(struct device *dev, |
| @@ -142,6 +144,9 @@ static int usb_port_runtime_suspend(struct device *dev) | |||
| 142 | == PM_QOS_FLAGS_ALL) | 144 | == PM_QOS_FLAGS_ALL) |
| 143 | return -EAGAIN; | 145 | return -EAGAIN; |
| 144 | 146 | ||
| 147 | if (usb_port_block_power_off) | ||
| 148 | return -EBUSY; | ||
| 149 | |||
| 145 | usb_autopm_get_interface(intf); | 150 | usb_autopm_get_interface(intf); |
| 146 | retval = usb_hub_set_port_power(hdev, hub, port1, false); | 151 | retval = usb_hub_set_port_power(hdev, hub, port1, false); |
| 147 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); | 152 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); |
| @@ -190,11 +195,19 @@ static int link_peers(struct usb_port *left, struct usb_port *right) | |||
| 190 | if (left->peer || right->peer) { | 195 | if (left->peer || right->peer) { |
| 191 | struct usb_port *lpeer = left->peer; | 196 | struct usb_port *lpeer = left->peer; |
| 192 | struct usb_port *rpeer = right->peer; | 197 | struct usb_port *rpeer = right->peer; |
| 193 | 198 | char *method; | |
| 194 | WARN(1, "failed to peer %s and %s (%s -> %p) (%s -> %p)\n", | 199 | |
| 195 | dev_name(&left->dev), dev_name(&right->dev), | 200 | if (left->location && left->location == right->location) |
| 196 | dev_name(&left->dev), lpeer, | 201 | method = "location"; |
| 197 | dev_name(&right->dev), rpeer); | 202 | else |
| 203 | method = "default"; | ||
| 204 | |||
| 205 | pr_warn("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n", | ||
| 206 | dev_name(&left->dev), dev_name(&right->dev), method, | ||
| 207 | dev_name(&left->dev), | ||
| 208 | lpeer ? dev_name(&lpeer->dev) : "none", | ||
| 209 | dev_name(&right->dev), | ||
| 210 | rpeer ? dev_name(&rpeer->dev) : "none"); | ||
| 198 | return -EBUSY; | 211 | return -EBUSY; |
| 199 | } | 212 | } |
| 200 | 213 | ||
| @@ -251,6 +264,7 @@ static void link_peers_report(struct usb_port *left, struct usb_port *right) | |||
| 251 | dev_warn(&left->dev, "failed to peer to %s (%d)\n", | 264 | dev_warn(&left->dev, "failed to peer to %s (%d)\n", |
| 252 | dev_name(&right->dev), rc); | 265 | dev_name(&right->dev), rc); |
| 253 | pr_warn_once("usb: port power management may be unreliable\n"); | 266 | pr_warn_once("usb: port power management may be unreliable\n"); |
| 267 | usb_port_block_power_off = 1; | ||
| 254 | } | 268 | } |
| 255 | } | 269 | } |
| 256 | 270 | ||
