Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 354562
b: refs/heads/master
c: 430ee58
h: refs/heads/master
v: v3
  • Loading branch information
Sebastian Andrzej Siewior authored and Greg Kroah-Hartman committed Jan 12, 2013
1 parent 0b35e61 commit 808fb4a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8d8479db3dde3ef7a9bc803e565842764fa21a53
refs/heads/master: 430ee58e03f1ed9c2a2b697e2f2e0bb870ce1a23
1 change: 0 additions & 1 deletion trunk/drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2506,7 +2506,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
}

/* starting here, usbcore will pay attention to this root hub */
rhdev->bus_mA = min(500u, hcd->power_budget);
if ((retval = register_root_hub(hcd)) != 0)
goto err_register_root_hub;

Expand Down
57 changes: 41 additions & 16 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,8 @@ static int hub_configure(struct usb_hub *hub,
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) {
Expand Down Expand Up @@ -1397,6 +1399,13 @@ static int hub_configure(struct usb_hub *hub,
}

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) &&
Expand Down Expand Up @@ -1516,40 +1525,44 @@ static int hub_configure(struct usb_hub *hub,
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);
Expand Down Expand Up @@ -4204,16 +4217,23 @@ hub_power_remaining (struct usb_hub *hub)
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)
Expand Down Expand Up @@ -4248,6 +4268,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
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",
Expand Down Expand Up @@ -4337,6 +4358,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
goto done;
return;
}
if (hub_is_superspeed(hub->hdev))
unit_load = 150;
else
unit_load = 100;

for (i = 0; i < SET_CONFIG_TRIES; i++) {

Expand Down Expand Up @@ -4384,7 +4409,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
* 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,
Expand Down

0 comments on commit 808fb4a

Please sign in to comment.