patch-2.3.35 linux/drivers/usb/hub.c
Next file: linux/drivers/usb/inits.h
Previous file: linux/drivers/usb/hp_scanner.c
Back to the patch index
Back to the overall index
- Lines: 90
- Date:
Tue Dec 28 10:24:11 1999
- Orig file:
v2.3.34/linux/drivers/usb/hub.c
- Orig date:
Mon Dec 20 18:48:22 1999
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
@@ -4,6 +4,8 @@
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999 Johannes Erdfelt
* (C) Copyright 1999 Gregory P. Smith
+ *
+ * $Id: hub.c,v 1.15 1999/12/27 15:17:45 acher Exp $
*/
#include <linux/kernel.h>
@@ -45,6 +47,12 @@
USB_DT_HUB << 8, 0, data, size, HZ);
}
+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);
+}
+
static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -190,7 +198,6 @@
printk(KERN_INFO "hub: enabling power on all ports\n");
for (i = 0; i < hub->nports; i++)
usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
-
return 0;
}
@@ -305,7 +312,9 @@
struct usb_device *usb;
struct usb_port_status portsts;
unsigned short portstatus, portchange;
+ int tries;
+ wait_ms(100);
/* Check status */
if (usb_get_port_status(hub, port + 1, &portsts)<0) {
printk(KERN_ERR "get_port_status failed\n");
@@ -314,7 +323,8 @@
portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange);
- printk("hub.c: portstatus %x, change %x\n",portstatus,portchange);
+ printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
+ (portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
/* If it's not in CONNECT and ENABLE state, we're done */
if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
(!(portstatus & USB_PORT_STAT_ENABLE))) {
@@ -324,10 +334,37 @@
return;
}
wait_ms(400);
+
/* Reset the port */
- usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
- wait_ms(100);
+
+#define MAX_TRIES 5
+
+ for(tries=0;tries<MAX_TRIES;tries++) {
+
+ usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
+ wait_ms(200);
+
+ if (usb_get_port_status(hub, port + 1, &portsts)<0) {
+ printk(KERN_ERR "get_port_status failed\n");
+ return;
+ }
+ portstatus = le16_to_cpu(portsts.wPortStatus);
+ portchange = le16_to_cpu(portsts.wPortChange);
+ printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
+ (portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
+
+ if ((portstatus&(1<<USB_PORT_FEAT_ENABLE)))
+ break;
+
+ wait_ms(200);
+ }
+
+ if (tries==MAX_TRIES) {
+ printk("hub.c: Can not enable port %i after %i retries, disabling port\n",port+1,MAX_TRIES);
+ return;
+ }
/* Allocate a new device struct for it */
+
usb = usb_alloc_dev(hub, hub->bus);
if (!usb) {
printk(KERN_ERR "couldn't allocate usb_device\n");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)