summaryrefslogtreecommitdiffstats
path: root/drivers/usb/hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/hub.c')
-rw-r--r--drivers/usb/hub.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c
index de7c65674..c066c3c43 100644
--- a/drivers/usb/hub.c
+++ b/drivers/usb/hub.c
@@ -48,13 +48,11 @@ static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
USB_DT_HUB << 8, 0, data, size, HZ);
}
-#if 0
-static int usb_clear_hub_feature(struct usb_device *dev, int feature)
+static int usb_clear_hub_feature(struct usb_device *dev, int feature)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ);
+ USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
}
-#endif
static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
@@ -359,7 +357,8 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
}
if (tries==MAX_TRIES) {
- err("can not enable port %i after %i retries, disabling port", port+1, MAX_TRIES);
+ err("Cannot enable port %i after %i retries, disabling port.", port+1, MAX_TRIES);
+ err("Maybe the USB cable is bad?");
return;
}
/* Allocate a new device struct for it */
@@ -392,6 +391,8 @@ static void usb_hub_events(void)
struct list_head *tmp;
struct usb_device *dev;
struct usb_hub *hub;
+ struct usb_hub_status hubsts;
+ unsigned short hubstatus, hubchange;
/*
* We restart the list everytime to avoid a deadlock with
@@ -444,14 +445,32 @@ static void usb_hub_events(void)
if (portchange & USB_PORT_STAT_C_SUSPEND)
dbg("port %d suspend change", i + 1);
- if (portchange & USB_PORT_STAT_C_OVERCURRENT)
+ if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
dbg("port %d over-current change", i + 1);
+ usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
+ }
if (portchange & USB_PORT_STAT_C_RESET) {
dbg("port %d reset change", i + 1);
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
}
} /* end for i */
+
+ /* deal with hub status changes */
+ if (usb_get_hub_status(dev, &hubsts) < 0) {
+ err("get_hub_status failed");
+ } else {
+ hubstatus = le16_to_cpup(&hubsts.wHubStatus);
+ hubchange = le16_to_cpup(&hubsts.wHubChange);
+ if (hubchange & HUB_CHANGE_LOCAL_POWER) {
+ dbg("hub power change");
+ usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
+ }
+ if (hubchange & HUB_CHANGE_OVERCURRENT) {
+ dbg("hub overcurrent change");
+ usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
+ }
+ }
} /* end while (1) */
he_unlock: