mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-26 16:30:55 +07:00
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>
This commit is contained in:
parent
ece1d77ed7
commit
8d8479db3d
@ -316,17 +316,23 @@ static char *usb_dump_iad_descriptor(char *start, char *end,
|
||||
*/
|
||||
static char *usb_dump_config_descriptor(char *start, char *end,
|
||||
const struct usb_config_descriptor *desc,
|
||||
int active)
|
||||
int active, int speed)
|
||||
{
|
||||
int mul;
|
||||
|
||||
if (start > end)
|
||||
return start;
|
||||
if (speed == USB_SPEED_SUPER)
|
||||
mul = 8;
|
||||
else
|
||||
mul = 2;
|
||||
start += sprintf(start, format_config,
|
||||
/* mark active/actual/current cfg. */
|
||||
active ? '*' : ' ',
|
||||
desc->bNumInterfaces,
|
||||
desc->bConfigurationValue,
|
||||
desc->bmAttributes,
|
||||
desc->bMaxPower * 2);
|
||||
desc->bMaxPower * mul);
|
||||
return start;
|
||||
}
|
||||
|
||||
@ -342,7 +348,8 @@ static char *usb_dump_config(int speed, char *start, char *end,
|
||||
if (!config)
|
||||
/* getting these some in 2.3.7; none in 2.3.6 */
|
||||
return start + sprintf(start, "(null Cfg. desc.)\n");
|
||||
start = usb_dump_config_descriptor(start, end, &config->desc, active);
|
||||
start = usb_dump_config_descriptor(start, end, &config->desc, active,
|
||||
speed);
|
||||
for (i = 0; i < USB_MAXIADS; i++) {
|
||||
if (config->intf_assoc[i] == NULL)
|
||||
break;
|
||||
|
@ -100,7 +100,7 @@ int usb_choose_configuration(struct usb_device *udev)
|
||||
*/
|
||||
|
||||
/* Rule out configs that draw too much bus current */
|
||||
if (c->desc.bMaxPower * 2 > udev->bus_mA) {
|
||||
if (usb_get_max_power(udev, c) > udev->bus_mA) {
|
||||
insufficient_power++;
|
||||
continue;
|
||||
}
|
||||
|
@ -4211,7 +4211,7 @@ hub_power_remaining (struct usb_hub *hub)
|
||||
/* Unconfigured devices may not use more than 100mA,
|
||||
* or 8mA for OTG ports */
|
||||
if (udev->actconfig)
|
||||
delta = udev->actconfig->desc.bMaxPower * 2;
|
||||
delta = usb_get_max_power(udev, udev->actconfig);
|
||||
else if (port1 != udev->bus->otg_port || hdev->parent)
|
||||
delta = 100;
|
||||
else
|
||||
|
@ -1751,7 +1751,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
|
||||
}
|
||||
}
|
||||
|
||||
i = dev->bus_mA - cp->desc.bMaxPower * 2;
|
||||
i = dev->bus_mA - usb_get_max_power(dev, cp);
|
||||
if (i < 0)
|
||||
dev_warn(&dev->dev, "new config #%d exceeds power "
|
||||
"limit by %dmA\n",
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "usb.h"
|
||||
|
||||
/* Active configuration fields */
|
||||
#define usb_actconfig_show(field, multiplier, format_string) \
|
||||
#define usb_actconfig_show(field, format_string) \
|
||||
static ssize_t show_##field(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
@ -28,18 +28,31 @@ static ssize_t show_##field(struct device *dev, \
|
||||
actconfig = udev->actconfig; \
|
||||
if (actconfig) \
|
||||
return sprintf(buf, format_string, \
|
||||
actconfig->desc.field * multiplier); \
|
||||
actconfig->desc.field); \
|
||||
else \
|
||||
return 0; \
|
||||
} \
|
||||
|
||||
#define usb_actconfig_attr(field, multiplier, format_string) \
|
||||
usb_actconfig_show(field, multiplier, format_string) \
|
||||
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
|
||||
#define usb_actconfig_attr(field, format_string) \
|
||||
usb_actconfig_show(field, format_string) \
|
||||
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
|
||||
|
||||
usb_actconfig_attr(bNumInterfaces, 1, "%2d\n")
|
||||
usb_actconfig_attr(bmAttributes, 1, "%2x\n")
|
||||
usb_actconfig_attr(bMaxPower, 2, "%3dmA\n")
|
||||
usb_actconfig_attr(bNumInterfaces, "%2d\n")
|
||||
usb_actconfig_attr(bmAttributes, "%2x\n")
|
||||
|
||||
static ssize_t show_bMaxPower(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
struct usb_host_config *actconfig;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
actconfig = udev->actconfig;
|
||||
if (!actconfig)
|
||||
return 0;
|
||||
return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
|
||||
}
|
||||
static DEVICE_ATTR(bMaxPower, S_IRUGO, show_bMaxPower, NULL);
|
||||
|
||||
static ssize_t show_configuration_string(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
@ -56,7 +69,7 @@ static ssize_t show_configuration_string(struct device *dev,
|
||||
static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
|
||||
|
||||
/* configuration value is always present, and r/w */
|
||||
usb_actconfig_show(bConfigurationValue, 1, "%u\n");
|
||||
usb_actconfig_show(bConfigurationValue, "%u\n");
|
||||
|
||||
static ssize_t
|
||||
set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
|
||||
|
@ -38,6 +38,15 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
|
||||
extern int usb_set_configuration(struct usb_device *dev, int configuration);
|
||||
extern int usb_choose_configuration(struct usb_device *udev);
|
||||
|
||||
static inline unsigned usb_get_max_power(struct usb_device *udev,
|
||||
struct usb_host_config *c)
|
||||
{
|
||||
/* SuperSpeed power is in 8 mA units; others are in 2 mA units */
|
||||
unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2);
|
||||
|
||||
return c->desc.bMaxPower * mul;
|
||||
}
|
||||
|
||||
extern void usb_kick_khubd(struct usb_device *dev);
|
||||
extern int usb_match_one_id_intf(struct usb_device *dev,
|
||||
struct usb_host_interface *intf,
|
||||
|
Loading…
Reference in New Issue
Block a user