aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-12-18 09:25:46 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-11 19:16:01 -0500
commit8d8479db3dde3ef7a9bc803e565842764fa21a53 (patch)
tree6c4e2b049c675b62be0fd3d65ae606f367dfb56c
parentece1d77ed73b335319725f1d5ffa72ca3fa9b05c (diff)
usb/core: consider link speed while looking at bMaxPower
The USB 2.0 specification says that bMaxPower is the maximum power consumption expressed in 2 mA units and the USB 3.0 specification says that it is expressed in 8 mA units. This patch adds a helper function usb_get_max_power() which computes the value based on config & usb_device's speed value. The the device descriptor dump computes the value on its own. Cc: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/devices.c13
-rw-r--r--drivers/usb/core/generic.c2
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/message.c2
-rw-r--r--drivers/usb/core/sysfs.c31
-rw-r--r--drivers/usb/core/usb.h9
6 files changed, 44 insertions, 15 deletions
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index cbacea933b18..e33224e23770 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -316,17 +316,23 @@ static char *usb_dump_iad_descriptor(char *start, char *end,
316 */ 316 */
317static char *usb_dump_config_descriptor(char *start, char *end, 317static char *usb_dump_config_descriptor(char *start, char *end,
318 const struct usb_config_descriptor *desc, 318 const struct usb_config_descriptor *desc,
319 int active) 319 int active, int speed)
320{ 320{
321 int mul;
322
321 if (start > end) 323 if (start > end)
322 return start; 324 return start;
325 if (speed == USB_SPEED_SUPER)
326 mul = 8;
327 else
328 mul = 2;
323 start += sprintf(start, format_config, 329 start += sprintf(start, format_config,
324 /* mark active/actual/current cfg. */ 330 /* mark active/actual/current cfg. */
325 active ? '*' : ' ', 331 active ? '*' : ' ',
326 desc->bNumInterfaces, 332 desc->bNumInterfaces,
327 desc->bConfigurationValue, 333 desc->bConfigurationValue,
328 desc->bmAttributes, 334 desc->bmAttributes,
329 desc->bMaxPower * 2); 335 desc->bMaxPower * mul);
330 return start; 336 return start;
331} 337}
332 338
@@ -342,7 +348,8 @@ static char *usb_dump_config(int speed, char *start, char *end,
342 if (!config) 348 if (!config)
343 /* getting these some in 2.3.7; none in 2.3.6 */ 349 /* getting these some in 2.3.7; none in 2.3.6 */
344 return start + sprintf(start, "(null Cfg. desc.)\n"); 350 return start + sprintf(start, "(null Cfg. desc.)\n");
345 start = usb_dump_config_descriptor(start, end, &config->desc, active); 351 start = usb_dump_config_descriptor(start, end, &config->desc, active,
352 speed);
346 for (i = 0; i < USB_MAXIADS; i++) { 353 for (i = 0; i < USB_MAXIADS; i++) {
347 if (config->intf_assoc[i] == NULL) 354 if (config->intf_assoc[i] == NULL)
348 break; 355 break;
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index eff2010eb63f..271e761f563e 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -100,7 +100,7 @@ int usb_choose_configuration(struct usb_device *udev)
100 */ 100 */
101 101
102 /* Rule out configs that draw too much bus current */ 102 /* Rule out configs that draw too much bus current */
103 if (c->desc.bMaxPower * 2 > udev->bus_mA) { 103 if (usb_get_max_power(udev, c) > udev->bus_mA) {
104 insufficient_power++; 104 insufficient_power++;
105 continue; 105 continue;
106 } 106 }
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ae10862fb041..12913306840a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4211,7 +4211,7 @@ hub_power_remaining (struct usb_hub *hub)
4211 /* Unconfigured devices may not use more than 100mA, 4211 /* Unconfigured devices may not use more than 100mA,
4212 * or 8mA for OTG ports */ 4212 * or 8mA for OTG ports */
4213 if (udev->actconfig) 4213 if (udev->actconfig)
4214 delta = udev->actconfig->desc.bMaxPower * 2; 4214 delta = usb_get_max_power(udev, udev->actconfig);
4215 else if (port1 != udev->bus->otg_port || hdev->parent) 4215 else if (port1 != udev->bus->otg_port || hdev->parent)
4216 delta = 100; 4216 delta = 100;
4217 else 4217 else
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 131f73649b60..444d30e3a78b 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1751,7 +1751,7 @@ free_interfaces:
1751 } 1751 }
1752 } 1752 }
1753 1753
1754 i = dev->bus_mA - cp->desc.bMaxPower * 2; 1754 i = dev->bus_mA - usb_get_max_power(dev, cp);
1755 if (i < 0) 1755 if (i < 0)
1756 dev_warn(&dev->dev, "new config #%d exceeds power " 1756 dev_warn(&dev->dev, "new config #%d exceeds power "
1757 "limit by %dmA\n", 1757 "limit by %dmA\n",
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 818e4a024d0d..3f81a3dc6867 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -17,7 +17,7 @@
17#include "usb.h" 17#include "usb.h"
18 18
19/* Active configuration fields */ 19/* Active configuration fields */
20#define usb_actconfig_show(field, multiplier, format_string) \ 20#define usb_actconfig_show(field, format_string) \
21static ssize_t show_##field(struct device *dev, \ 21static ssize_t show_##field(struct device *dev, \
22 struct device_attribute *attr, char *buf) \ 22 struct device_attribute *attr, char *buf) \
23{ \ 23{ \
@@ -28,18 +28,31 @@ static ssize_t show_##field(struct device *dev, \
28 actconfig = udev->actconfig; \ 28 actconfig = udev->actconfig; \
29 if (actconfig) \ 29 if (actconfig) \
30 return sprintf(buf, format_string, \ 30 return sprintf(buf, format_string, \
31 actconfig->desc.field * multiplier); \ 31 actconfig->desc.field); \
32 else \ 32 else \
33 return 0; \ 33 return 0; \
34} \ 34} \
35 35
36#define usb_actconfig_attr(field, multiplier, format_string) \ 36#define usb_actconfig_attr(field, format_string) \
37usb_actconfig_show(field, multiplier, format_string) \ 37 usb_actconfig_show(field, format_string) \
38static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); 38 static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
39
40usb_actconfig_attr(bNumInterfaces, "%2d\n")
41usb_actconfig_attr(bmAttributes, "%2x\n")
39 42
40usb_actconfig_attr(bNumInterfaces, 1, "%2d\n") 43static ssize_t show_bMaxPower(struct device *dev,
41usb_actconfig_attr(bmAttributes, 1, "%2x\n") 44 struct device_attribute *attr, char *buf)
42usb_actconfig_attr(bMaxPower, 2, "%3dmA\n") 45{
46 struct usb_device *udev;
47 struct usb_host_config *actconfig;
48
49 udev = to_usb_device(dev);
50 actconfig = udev->actconfig;
51 if (!actconfig)
52 return 0;
53 return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
54}
55static DEVICE_ATTR(bMaxPower, S_IRUGO, show_bMaxPower, NULL);
43 56
44static ssize_t show_configuration_string(struct device *dev, 57static ssize_t show_configuration_string(struct device *dev,
45 struct device_attribute *attr, char *buf) 58 struct device_attribute *attr, char *buf)
@@ -56,7 +69,7 @@ static ssize_t show_configuration_string(struct device *dev,
56static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); 69static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
57 70
58/* configuration value is always present, and r/w */ 71/* configuration value is always present, and r/w */
59usb_actconfig_show(bConfigurationValue, 1, "%u\n"); 72usb_actconfig_show(bConfigurationValue, "%u\n");
60 73
61static ssize_t 74static ssize_t
62set_bConfigurationValue(struct device *dev, struct device_attribute *attr, 75set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1c528c1bf0be..fb7d8fcb4551 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -38,6 +38,15 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
38extern int usb_set_configuration(struct usb_device *dev, int configuration); 38extern int usb_set_configuration(struct usb_device *dev, int configuration);
39extern int usb_choose_configuration(struct usb_device *udev); 39extern int usb_choose_configuration(struct usb_device *udev);
40 40
41static inline unsigned usb_get_max_power(struct usb_device *udev,
42 struct usb_host_config *c)
43{
44 /* SuperSpeed power is in 8 mA units; others are in 2 mA units */
45 unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2);
46
47 return c->desc.bMaxPower * mul;
48}
49
41extern void usb_kick_khubd(struct usb_device *dev); 50extern void usb_kick_khubd(struct usb_device *dev);
42extern int usb_match_one_id_intf(struct usb_device *dev, 51extern int usb_match_one_id_intf(struct usb_device *dev,
43 struct usb_host_interface *intf, 52 struct usb_host_interface *intf,