unsigned int pipe;
int maxp, ret, i;
char *message = "out of memory";
+ unsigned unit_load;
+ unsigned full_load;
hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
if (!hub->buffer) {
}
wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+ if (hub_is_superspeed(hdev)) {
+ unit_load = 150;
+ full_load = 900;
+ } else {
+ unit_load = 100;
+ full_load = 500;
+ }
/* FIXME for USB 3.0, skip for now */
if ((wHubCharacteristics & HUB_CHAR_COMPOUND) &&
goto fail;
}
le16_to_cpus(&hubstatus);
+ hcd = bus_to_hcd(hdev->bus);
if (hdev == hdev->bus->root_hub) {
- if (hdev->bus_mA == 0 || hdev->bus_mA >= 500)
- hub->mA_per_port = 500;
+ if (hcd->power_budget > 0)
+ hdev->bus_mA = hcd->power_budget;
+ else
+ hdev->bus_mA = full_load * hdev->maxchild;
+ if (hdev->bus_mA >= full_load)
+ hub->mA_per_port = full_load;
else {
hub->mA_per_port = hdev->bus_mA;
hub->limited_power = 1;
}
} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+ int remaining = hdev->bus_mA -
+ hub->descriptor->bHubContrCurrent;
+
dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
hub->descriptor->bHubContrCurrent);
hub->limited_power = 1;
- if (hdev->maxchild > 0) {
- int remaining = hdev->bus_mA -
- hub->descriptor->bHubContrCurrent;
- if (remaining < hdev->maxchild * 100)
- dev_warn(hub_dev,
+ if (remaining < hdev->maxchild * unit_load)
+ dev_warn(hub_dev,
"insufficient power available "
"to use all downstream ports\n");
- hub->mA_per_port = 100; /* 7.2.1.1 */
- }
+ hub->mA_per_port = unit_load; /* 7.2.1 */
+
} else { /* Self-powered external hub */
/* FIXME: What about battery-powered external hubs that
* provide less current per port? */
- hub->mA_per_port = 500;
+ hub->mA_per_port = full_load;
}
- if (hub->mA_per_port < 500)
+ if (hub->mA_per_port < full_load)
dev_dbg(hub_dev, "%umA bus power budget for each child\n",
hub->mA_per_port);
/* Update the HCD's internal representation of this hub before khubd
* starts getting port status changes for devices under the hub.
*/
- hcd = bus_to_hcd(hdev->bus);
if (hcd->driver->update_hub_device) {
ret = hcd->driver->update_hub_device(hcd, hdev,
&hub->tt, GFP_KERNEL);
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
struct usb_device *udev = hub->ports[port1 - 1]->child;
int delta;
+ unsigned unit_load;
if (!udev)
continue;
+ if (hub_is_superspeed(udev))
+ unit_load = 150;
+ else
+ unit_load = 100;
- /* Unconfigured devices may not use more than 100mA,
- * or 8mA for OTG ports */
+ /*
+ * Unconfigured devices may not use more than one unit load,
+ * or 8mA for OTG ports
+ */
if (udev->actconfig)
delta = usb_get_max_power(udev, udev->actconfig);
else if (port1 != udev->bus->otg_port || hdev->parent)
- delta = 100;
+ delta = unit_load;
else
delta = 8;
if (delta > hub->mA_per_port)
le16_to_cpu(hub->descriptor->wHubCharacteristics);
struct usb_device *udev;
int status, i;
+ unsigned unit_load;
dev_dbg (hub_dev,
"port %d, status %04x, change %04x, %s\n",
goto done;
return;
}
+ if (hub_is_superspeed(hub->hdev))
+ unit_load = 150;
+ else
+ unit_load = 100;
for (i = 0; i < SET_CONFIG_TRIES; i++) {
* on the parent.
*/
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
- && udev->bus_mA <= 100) {
+ && udev->bus_mA <= unit_load) {
u16 devstat;
status = usb_get_status(udev, USB_RECIP_DEVICE, 0,