diff options
author | Dan Williams <dan.j.williams@intel.com> | 2014-06-17 19:16:27 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-06-17 20:04:39 -0400 |
commit | 6c79fe4afcb0450bd638f6e959e512aad270ff2f (patch) | |
tree | 10e7f6a082cd83d15139ce3e666e061ca69d5f0b /drivers/usb/core | |
parent | b658b8f5c09d3d1db9641c9d520b36b3e4c0d744 (diff) |
usb: quiet peer failure warning, disable poweroff
In the case where platform firmware has specified conflicting values for
port locations it is confusing and otherwise not helpful to throw a
backtrace. Instead, include enough information to determine that
firmware has done something wrong and globally disable port poweroff.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
-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 | ||