On Mon, 3 Dec 2012, Sebastian Andrzej Siewior wrote: > 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 sysfs interface & > the device descriptor dump compute the value on their own. This is an important fix. A couple of suggestions below... > diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c > index eff2010..68ed80b 100644 > --- a/drivers/usb/core/generic.c > +++ b/drivers/usb/core/generic.c > @@ -40,6 +40,19 @@ static int is_activesync(struct usb_interface_descriptor *desc) > && desc->bInterfaceProtocol == 1; > } > > +unsigned usb_get_max_power(struct usb_device *udev, struct usb_host_config *c) > +{ > + unsigned val = c->desc.bMaxPower; > + > + switch (udev->speed) { > + case USB_SPEED_SUPER: > + return val * 8; > + break; "break" is unnecessary here; control cannot continue past the "return" statement. > + default: > + return val * 2; > + } > +} > + generic.c is an odd file to define this function in. In fact, it might be more efficient to make this an inline function in usb.h: static inline unsigned usb_get_max_power(...) { /* 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; } > diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c > index 818e4a0..d31d1c8 100644 > --- a/drivers/usb/core/sysfs.c > +++ b/drivers/usb/core/sysfs.c > @@ -17,14 +17,22 @@ > #include "usb.h" > > /* Active configuration fields */ > -#define usb_actconfig_show(field, multiplier, format_string) \ > +#define usb_actconfig_show(field, ss_mult, format_string) \ > static ssize_t show_##field(struct device *dev, \ > struct device_attribute *attr, char *buf) \ > { \ > struct usb_device *udev; \ > struct usb_host_config *actconfig; \ > + unsigned multiplier; \ > \ > + multiplier = 1; \ > udev = to_usb_device(dev); \ > + if (ss_mult) { \ > + if (udev->speed == USB_SPEED_SUPER) \ > + multiplier = 8; \ > + else \ > + multiplier = 2; \ > + } \ > actconfig = udev->actconfig; \ > if (actconfig) \ > return sprintf(buf, format_string, \ This is getting pretty awkward. > @@ -33,13 +41,13 @@ static ssize_t show_##field(struct device *dev, \ > return 0; \ > } \ > > -#define usb_actconfig_attr(field, multiplier, format_string) \ > -usb_actconfig_show(field, multiplier, format_string) \ > +#define usb_actconfig_attr(field, ss_mult, format_string) \ > +usb_actconfig_show(field, ss_mult, 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, 0, "%2d\n") > +usb_actconfig_attr(bmAttributes, 0, "%2x\n") > +usb_actconfig_attr(bMaxPower, 1, "%3dmA\n") I suggest rewriting the macro without the multiplier argument and using it for bNumInterfaces and bmAttributes. Do the bMaxPower case as a separate function, not using the macro. Alan Stern -- 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