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 renames bMaxPower to MaxPower and the various /2 and *2 are removed. Before reporting the config descriptor, the proper value is computer based on the speed, all in-tree users are updated. MaxPower is also increased to u16 so we can store the nokia gadget value which is larger than the max value allowed for u8. Cc: Felipe Balbi <balbi@xxxxxx> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> --- Felipe, I'm not sure if this stable material, I also fixed the host side. drivers/usb/gadget/composite.c | 27 +++++++++++++++++++++++---- drivers/usb/gadget/gmidi.c | 2 +- drivers/usb/gadget/nokia.c | 4 ++-- drivers/usb/gadget/webcam.c | 2 +- include/linux/usb/composite.h | 5 +++-- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 682ae15..8c1141e 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -332,6 +332,25 @@ int usb_interface_id(struct usb_configuration *config, } EXPORT_SYMBOL_GPL(usb_interface_id); +static u8 encode_bMaxPower(enum usb_device_speed speed, + struct usb_configuration *c) +{ + unsigned val; + + if (c->MaxPower) + val = c->MaxPower; + else + val = CONFIG_USB_GADGET_VBUS_DRAW; + if (!val) + return 0; + switch (speed) { + case USB_SPEED_SUPER: + return DIV_ROUND_UP(val, 8); + default: + return DIV_ROUND_UP(val, 2); + }; +} + static int config_buf(struct usb_configuration *config, enum usb_device_speed speed, void *buf, u8 type) { @@ -351,7 +370,7 @@ static int config_buf(struct usb_configuration *config, c->bConfigurationValue = config->bConfigurationValue; c->iConfiguration = config->iConfiguration; c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; - c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2); + c->bMaxPower = encode_bMaxPower(speed, config); /* There may be e.g. OTG descriptors */ if (config->descriptors) { @@ -668,7 +687,7 @@ static int set_config(struct usb_composite_dev *cdev, } /* when we return, be sure our power usage is valid */ - power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW; + power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW; done: usb_gadget_vbus_draw(gadget, power); if (result >= 0 && cdev->delayed_status) @@ -1547,10 +1566,10 @@ composite_resume(struct usb_gadget *gadget) f->resume(f); } - maxpower = cdev->config->bMaxPower; + maxpower = cdev->config->MaxPower; usb_gadget_vbus_draw(gadget, maxpower ? - (2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW); + maxpower : CONFIG_USB_GADGET_VBUS_DRAW); } cdev->suspended = 0; diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 881aab8..e879e2c 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -125,7 +125,7 @@ static struct usb_configuration midi_config = { .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_ONE, - .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, + .MaxPower = CONFIG_USB_GADGET_VBUS_DRAW, }; static int __init midi_bind_config(struct usb_configuration *c) diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index a599ae6..12d263f 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -106,7 +106,7 @@ static struct usb_configuration nokia_config_500ma_driver = { .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_ONE, - .bMaxPower = 250, /* 500mA */ + .MaxPower = 500, }; static struct usb_configuration nokia_config_100ma_driver = { @@ -114,7 +114,7 @@ static struct usb_configuration nokia_config_100ma_driver = { .bConfigurationValue = 2, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 50, /* 100 mA */ + .MaxPower = 100, }; static int __init nokia_bind_config(struct usb_configuration *c) diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 69cf5c2..8cef1e6 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -336,7 +336,7 @@ static struct usb_configuration webcam_config_driver = { .bConfigurationValue = 1, .iConfiguration = 0, /* dynamic */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, + .MaxPower = CONFIG_USB_GADGET_VBUS_DRAW, }; static int /* __init_or_exit */ diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index b52211a..1f71370 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -191,7 +191,8 @@ int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f, * @bConfigurationValue: Copied into configuration descriptor. * @iConfiguration: Copied into configuration descriptor. * @bmAttributes: Copied into configuration descriptor. - * @bMaxPower: Copied into configuration descriptor. + * @MaxPower: Power consumtion in mA. Used to compute bMaxPower in the + * configuration descriptor after considering the bus speed. * @cdev: assigned by @usb_add_config() before calling @bind(); this is * the device associated with this configuration. * @@ -237,7 +238,7 @@ struct usb_configuration { u8 bConfigurationValue; u8 iConfiguration; u8 bmAttributes; - u8 bMaxPower; + u16 MaxPower; struct usb_composite_dev *cdev; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html