/* * test_find_usbdev * using our driver, attempt to find * a usb device that our driver can use, * and set the pointers in our test interface * structure to the device pointer so that * it can be used future test calls */ static int test_find_usbdev() { struct usb_device *udev = (struct usb_device *)kmalloc(sizeof(struct usb_device), GFP_KERNEL); struct usb_bus *bus = (struct usb_bus *)kmalloc(sizeof(struct usb_bus), GFP_KERNEL); /* Zero out the ltp_usb */ memset(<p_usb, 0, sizeof(tusb_user_t)); ltp_usb.bus = bus; ltp_usb.dev = udev; /* allocate the usb_bus pointer */ #if 0 bus = usb_alloc_bus(&test_device_operations); if (!bus) { printk("tusb: Did not allocate a bus\n"); return 1; } else { printk("tusb: Allocated a bus pointer\n"); memcpy(ltp_usb.bus, bus, sizeof(struct usb_bus)); printk("test1\n"); } /* allocate the usb_device pointer */ udev = usb_alloc_dev(NULL, bus); if (udev) { printk("tusb: Found a usb device pointer\n"); memcpy(ltp_usb.dev, udev, sizeof(struct usb_device)); } else { printk("tusb: Failed find usb device pointer\n"); return 1; } /* connect the new device and setup pointers */ usb_connect(udev); usb_new_device(udev); #endif return 0; }
/*************************************************************************** * Function Name : rh_connect_rh * * This function connect the virtual root hub to the USB stack * * Input: urb = USB request block * * Return: 0 **************************************************************************/ static int rh_connect_rh (hci_t * hci) { struct usb_device *usb_dev; hci->rh.devnum = 0; usb_dev = usb_alloc_dev (NULL, hci->bus, 0); if (!usb_dev) return -ENOMEM; hci->bus->root_hub = usb_dev; usb_dev->devnum = 1; usb_dev->bus->devnum_next = usb_dev->devnum + 1; set_bit (usb_dev->devnum, usb_dev->bus->devmap.devicemap); if (usb_new_device (usb_dev) != 0) { usb_put_dev (usb_dev); return -ENODEV; } return 0; }
static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port, u16 portstatus, u16 portchange) { struct usb_device *hub = hubstate->dev; struct usb_device *dev; unsigned int delay = HUB_SHORT_RESET_TIME; int i; char *portstr, *tempstr; DBG_HOST_HUB("### >>> Enter hub.c file --> usb_hub_port_connect_change function \n"); dbg("port %d, portstatus %x, change %x, %s", port + 1, portstatus, portchange, portspeed (portstatus)); /* Clear the connection change status */ usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); /* Disconnect any existing devices under this port */ if (hub->children[port]) usb_disconnect(&hub->children[port]); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { if (portstatus & USB_PORT_STAT_ENABLE) usb_hub_port_disable(hub, port); return; } if (usb_hub_port_debounce(hub, port)) { err("connect-debounce failed, port %d disabled", port+1); usb_hub_port_disable(hub, port); return; } down(&usb_address0_sem); tempstr = kmalloc(1024, GFP_KERNEL); portstr = kmalloc(1024, GFP_KERNEL); for (i = 0; i < HUB_PROBE_TRIES; i++) { struct usb_device *pdev, *cdev; /* Allocate a new device struct */ dev = usb_alloc_dev(hub, hub->bus); if (!dev) { err("couldn't allocate usb_device"); break; } hub->children[port] = dev; /* Reset the device */ if (usb_hub_port_reset(hub, port, dev, delay)) { usb_free_dev(dev); break; } /* Find a new device ID for it */ usb_connect(dev); /* Set up TT records, if needed */ if (hub->tt) { dev->tt = hub->tt; dev->ttport = hub->ttport; } else if (dev->speed != USB_SPEED_HIGH && hub->speed == USB_SPEED_HIGH) { dev->tt = &hubstate->tt; dev->ttport = port + 1; } /* Create a readable topology string */ cdev = dev; pdev = dev->parent; if (portstr && tempstr) { portstr[0] = 0; while (pdev) { int port; for (port = 0; port < pdev->maxchild; port++) if (pdev->children[port] == cdev) break; strcpy(tempstr, portstr); if (!strlen(tempstr)) sprintf(portstr, "%d", port + 1); else sprintf(portstr, "%d/%s", port + 1, tempstr); cdev = pdev; pdev = pdev->parent; } info("USB new device connect on bus%d/%s, assigned device number %d", dev->bus->busnum, portstr, dev->devnum); } else info("USB new device connect on bus%d, assigned device number %d", dev->bus->busnum, dev->devnum); /* Run it through the hoops (find a driver, etc) */ if (!usb_new_device(dev)) goto done; /* Free the configuration if there was an error */ usb_free_dev(dev); /* Switch to a long reset time */ delay = HUB_LONG_RESET_TIME; } hub->children[port] = NULL; usb_hub_port_disable(hub, port); done: up(&usb_address0_sem); if (portstr) kfree(portstr); if (tempstr) kfree(tempstr); }
static void usb_hub_port_connect_change(struct usb_device *hub, int port, struct usb_port_status *portsts) { struct usb_device *dev; unsigned short portstatus, portchange; unsigned int delay = HUB_SHORT_RESET_TIME; int i; char *portstr, *tempstr; int devnum; portstatus = le16_to_cpu(portsts->wPortStatus); portchange = le16_to_cpu(portsts->wPortChange); dbg("port %d, portstatus %x, change %x, %s", port + 1, portstatus, portchange, portspeed (portstatus)); /* Clear the connection change status */ usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); /* Disconnect any existing devices under this port */ down(&hub->bus->dev_tree_sem); if (hub->children[port]) usb_disconnect(&hub->children[port]); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { if (portstatus & USB_PORT_STAT_ENABLE) usb_hub_port_disable(hub, port); up(&hub->bus->dev_tree_sem); return; } up(&hub->bus->dev_tree_sem); /* Some low speed devices have problems with the quick delay, so */ /* be a bit pessimistic with those devices. RHbug #23670 */ if (portstatus & USB_PORT_STAT_LOW_SPEED) { wait_ms(400); delay = HUB_LONG_RESET_TIME; } down(&usb_address0_sem); down(&hub->bus->dev_tree_sem); tempstr = kmalloc(1024, GFP_KERNEL); portstr = kmalloc(1024, GFP_KERNEL); for (i = 0; i < HUB_PROBE_TRIES; i++) { struct usb_device *pdev, *cdev; /* Allocate a new device struct */ dev = usb_alloc_dev(hub, hub->bus); if (!dev) { err("couldn't allocate usb_device"); break; } hub->children[port] = dev; /* Reset the device */ if (usb_hub_port_reset(hub, port, dev, delay)) { usb_free_dev(dev); break; } /* Find a new device ID for it */ usb_connect(dev); /* Create a readable topology string */ cdev = dev; pdev = dev->parent; if (portstr && tempstr) { portstr[0] = 0; while (pdev) { int port; for (port = 0; port < pdev->maxchild; port++) if (pdev->children[port] == cdev) break; strcpy(tempstr, portstr); if (!strlen(tempstr)) sprintf(portstr, "%d", port + 1); else sprintf(portstr, "%d/%s", port + 1, tempstr); cdev = pdev; pdev = pdev->parent; } info("USB new device connect on bus%d/%s, assigned device number %d", dev->bus->busnum, portstr, dev->devnum); } else info("USB new device connect on bus%d, assigned device number %d", dev->bus->busnum, dev->devnum); devnum = dev->devnum; /* Run it through the hoops (find a driver, etc) */ if (!usb_new_device(dev)) goto done; /* Free the configuration if there was an error */ usb_free_dev(dev); /* Switch to a long reset time */ delay = HUB_LONG_RESET_TIME; } err("failed adding a new device. Address=%d",devnum); hub->children[port] = NULL; usb_hub_port_disable(hub, port); done: up(&hub->bus->dev_tree_sem); up(&usb_address0_sem); if (portstr) kfree(portstr); if (tempstr) kfree(tempstr); }
static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port, u16 portstatus, u16 portchange) { struct usb_device *hub = hubstate->dev; struct usb_device *dev; unsigned int delay = HUB_SHORT_RESET_TIME; int i; dbg("port %d, portstatus %x, change %x, %s", port + 1, portstatus, portchange, portspeed (portstatus)); /* Clear the connection change status */ usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); /* Disconnect any existing devices under this port */ if (hub->children[port]) usb_disconnect(&hub->children[port]); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { if (portstatus & USB_PORT_STAT_ENABLE) usb_hub_port_disable(hub, port); return; } if (usb_hub_port_debounce(hub, port)) { err("connect-debounce failed, port %d disabled", port+1); usb_hub_port_disable(hub, port); return; } down(&usb_address0_sem); for (i = 0; i < HUB_PROBE_TRIES; i++) { struct usb_device *pdev; int len; /* Allocate a new device struct */ dev = usb_alloc_dev(hub, hub->bus); if (!dev) { err("couldn't allocate usb_device"); break; } /* Reset the device */ if (usb_hub_port_reset(hub, port, dev, delay)) { usb_free_dev(dev); break; } /* Find a new device ID for it */ usb_connect(dev); /* Set up TT records, if needed */ if (hub->tt) { dev->tt = hub->tt; dev->ttport = hub->ttport; } else if (dev->speed != USB_SPEED_HIGH && hub->speed == USB_SPEED_HIGH) { dev->tt = &hubstate->tt; dev->ttport = port + 1; } /* Save readable and stable topology id, distinguishing * devices by location for diagnostics, tools, etc. The * string is a path along hub ports, from the root. Each * device's id will be stable until USB is re-cabled, and * hubs are often labeled with these port numbers. * * Initial size: ".NN" times five hubs + NUL = 16 bytes max * (quite rare, since most hubs have 4-6 ports). */ pdev = dev->parent; if (pdev->devpath [0] != '0') /* parent not root? */ len = snprintf (dev->devpath, sizeof dev->devpath, "%s.%d", pdev->devpath, port + 1); /* root == "0", root port 2 == "2", port 3 that hub "2.3" */ else len = snprintf (dev->devpath, sizeof dev->devpath, "%d", port + 1); if (len == sizeof dev->devpath) warn ("devpath size! usb/%03d/%03d path %s", dev->bus->busnum, dev->devnum, dev->devpath); USB_SET_LED(USB_CONNECT); //2005-02-24 by kanki for USB LED info("new USB device %s-%s, assigned address %d", dev->bus->bus_name, dev->devpath, dev->devnum); /* Run it through the hoops (find a driver, etc) */ if (!usb_new_device(dev)) { hub->children[port] = dev; goto done; } /* Free the configuration if there was an error */ usb_free_dev(dev); /* Switch to a long reset time */ delay = HUB_LONG_RESET_TIME; } usb_hub_port_disable(hub, port); done: up(&usb_address0_sem); }
/** * usb_add_hcd - finish generic HCD structure initialization and register * @hcd: the usb_hcd structure to initialize * @irqnum: Interrupt line to allocate * @irqflags: Interrupt type flags * * Finish the remaining parts of generic HCD initialization: allocate the * buffers of consistent memory, register the bus, request the IRQ line, * and call the driver's reset() and start() routines. */ int mtk_usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags) { int retval; struct usb_device *rhdev; dev_info(hcd->self.controller, "%s\n", hcd->product_desc); hcd->authorized_default = hcd->wireless? 0 : 1; set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); /* HC is in reset state, but accessible. Now do the one-time init, * bottom up so that hcds can customize the root hubs before khubd * starts talking to them. (Note, bus id is assigned early too.) */ if ((retval = hcd_buffer_create(hcd)) != 0) { dev_dbg(hcd->self.controller, "pool alloc failed\n"); return retval; } if ((rhdev = mtk_usb_alloc_rhdev(NULL, &hcd->self, 0)) == NULL) { dev_err(hcd->self.controller, "unable to allocate root hub\n"); retval = -ENOMEM; goto err_allocate_root_hub; } hcd->self.root_hub = rhdev; #if 0 if ((retval = usb_register_bus(&hcd->self)) < 0) goto err_register_bus; if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { dev_err(hcd->self.controller, "unable to allocate root hub\n"); retval = -ENOMEM; goto err_allocate_root_hub; } switch (hcd->driver->flags & HCD_MASK) { case HCD_USB11: rhdev->speed = USB_SPEED_FULL; break; case HCD_USB2: rhdev->speed = USB_SPEED_HIGH; break; case HCD_USB3: rhdev->speed = USB_SPEED_SUPER; break; default: goto err_allocate_root_hub; } hcd->self.root_hub = rhdev; /* wakeup flag init defaults to "everything works" for root hubs, * but drivers can override it in reset() if needed, along with * recording the overall controller's system wakeup capability. */ device_init_wakeup(&rhdev->dev, 1); #endif /* "reset" is misnamed; its role is now one-time init. the controller * should already have been reset (and boot firmware kicked off etc). */ printk(KERN_DEBUG "call xhci_mtk_setup\n"); if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { dev_err(hcd->self.controller, "can't setup\n"); goto err_hcd_driver_setup; } #if 0 /* NOTE: root hub and controller capabilities may not be the same */ if (device_can_wakeup(hcd->self.controller) && device_can_wakeup(&hcd->self.root_hub->dev)) dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); #endif /* enable irqs just before we start the controller */ if (hcd->driver->irq) { /* IRQF_DISABLED doesn't work as advertised when used together * with IRQF_SHARED. As usb_hcd_irq() will always disable * interrupts we can remove it here. */ if (irqflags & IRQF_SHARED) irqflags &= ~IRQF_DISABLED; snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags, hcd->irq_descr, hcd)) != 0) { dev_err(hcd->self.controller, "request interrupt %d failed\n", irqnum); goto err_request_irq; } hcd->irq = irqnum; dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum, (hcd->driver->flags & HCD_MEMORY) ? "io mem" : "io base", (unsigned long long)hcd->rsrc_start); } else { hcd->irq = -1; if (hcd->rsrc_start) dev_info(hcd->self.controller, "%s 0x%08llx\n", (hcd->driver->flags & HCD_MEMORY) ? "io mem" : "io base", (unsigned long long)hcd->rsrc_start); } if ((retval = hcd->driver->start(hcd)) < 0) { dev_err(hcd->self.controller, "startup error %d\n", retval); goto err_hcd_driver_start; } #if 0 /* 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; retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group); if (retval < 0) { printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n", retval); goto error_create_attr_group; } if (hcd->uses_new_polling && hcd->poll_rh) usb_hcd_poll_rh_status(hcd); #endif return retval; error_create_attr_group: mutex_lock(&usb_bus_list_lock); usb_disconnect(&hcd->self.root_hub); mutex_unlock(&usb_bus_list_lock); err_register_root_hub: hcd->driver->stop(hcd); err_hcd_driver_start: if (hcd->irq >= 0) free_irq(irqnum, hcd); err_request_irq: err_hcd_driver_setup: hcd->self.root_hub = NULL; usb_put_dev(rhdev); #if 1 err_allocate_root_hub: hcd->driver->stop(hcd); #endif err_register_bus: hcd_buffer_destroy(hcd); return retval; }
static void hub_port_connect_change(struct usb_hub *hubstate, int port, u16 portstatus, u16 portchange) { struct usb_device *hub = interface_to_usbdev(hubstate->intf); struct usb_device *dev; unsigned int delay = HUB_SHORT_RESET_TIME; int i; dev_dbg (&hubstate->intf->dev, "port %d, status %x, change %x, %s\n", port + 1, portstatus, portchange, portspeed (portstatus)); /* Clear the connection change status */ clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); /* Disconnect any existing devices under this port */ if (hub->children[port]) usb_disconnect(&hub->children[port]); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { if (portstatus & USB_PORT_STAT_ENABLE) hub_port_disable(hub, port); return; } if (hub_port_debounce(hub, port)) { dev_err (&hubstate->intf->dev, "connect-debounce failed, port %d disabled\n", port+1); hub_port_disable(hub, port); return; } /* Some low speed devices have problems with the quick delay, so */ /* be a bit pessimistic with those devices. RHbug #23670 */ if (portstatus & USB_PORT_STAT_LOW_SPEED) delay = HUB_LONG_RESET_TIME; down(&usb_address0_sem); for (i = 0; i < HUB_PROBE_TRIES; i++) { struct usb_device *pdev; int len; /* Allocate a new device struct */ dev = usb_alloc_dev(hub, hub->bus); if (!dev) { dev_err (&hubstate->intf->dev, "couldn't allocate usb_device\n"); break; } hub->children[port] = dev; dev->state = USB_STATE_POWERED; /* Reset the device, and detect its speed */ if (hub_port_reset(hub, port, dev, delay)) { usb_put_dev(dev); break; } /* Find a new address for it */ usb_connect(dev); /* Set up TT records, if needed */ if (hub->tt) { dev->tt = hub->tt; dev->ttport = hub->ttport; } else if (dev->speed != USB_SPEED_HIGH && hub->speed == USB_SPEED_HIGH) { dev->tt = &hubstate->tt; dev->ttport = port + 1; } /* Save readable and stable topology id, distinguishing * devices by location for diagnostics, tools, etc. The * string is a path along hub ports, from the root. Each * device's id will be stable until USB is re-cabled, and * hubs are often labeled with these port numbers. * * Initial size: ".NN" times five hubs + NUL = 16 bytes max * (quite rare, since most hubs have 4-6 ports). */ pdev = dev->parent; if (pdev->devpath [0] != '0') /* parent not root? */ len = snprintf (dev->devpath, sizeof dev->devpath, "%s.%d", pdev->devpath, port + 1); /* root == "0", root port 2 == "2", port 3 that hub "2.3" */ else len = snprintf (dev->devpath, sizeof dev->devpath, "%d", port + 1); if (len == sizeof dev->devpath) dev_err (&hubstate->intf->dev, "devpath size! usb/%03d/%03d path %s\n", dev->bus->busnum, dev->devnum, dev->devpath); dev_info (&hubstate->intf->dev, "new USB device on port %d, assigned address %d\n", port + 1, dev->devnum); /* put the device in the global device tree. the hub port * is the "bus_id"; hubs show in hierarchy like bridges */ dev->dev.parent = dev->parent->dev.parent->parent; /* Run it through the hoops (find a driver, etc) */ if (!usb_new_device(dev, &hub->dev)) goto done; /* Free the configuration if there was an error */ usb_put_dev(dev); /* Switch to a long reset time */ delay = HUB_LONG_RESET_TIME; } hub->children[port] = NULL; hub_port_disable(hub, port); done: up(&usb_address0_sem); }
static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port, u16 portstatus, u16 portchange) { struct usb_device *hub = hubstate->dev; struct usb_device *dev; unsigned int delay = HUB_SHORT_RESET_TIME; int i; dbg("port %d, portstatus %x, change %x, %s", port + 1, portstatus, portchange, portspeed (portstatus)); /* Clear the connection change status */ usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); /* Disconnect any existing devices under this port */ if (hub->children[port]) usb_disconnect(&hub->children[port]); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { if (portstatus & USB_PORT_STAT_ENABLE) usb_hub_port_disable(hub, port); return; } if (usb_hub_port_debounce(hub, port)) { err("connect-debounce failed, port %d disabled", port+1); usb_hub_port_disable(hub, port); return; } down(&usb_address0_sem); for (i = 0; i < HUB_PROBE_TRIES; i++) { struct usb_device *pdev; int len; /* Allocate a new device struct */ dev = usb_alloc_dev(hub, hub->bus); if (!dev) { err("couldn't allocate usb_device"); break; } hub->children[port] = dev; /* add by Levis for wakeup BP */ int begin = 0; #ifdef CONFIG_ARCH_EZXBASE set_GPIO_mode(GPIO_IN | GPIO_BP_RDY); if(!GPIO_is_high(GPIO_BP_RDY)) { if(GPIO_is_high(GPIO_AP_RDY )) { GPCR(GPIO_AP_RDY ) = GPIO_bit(GPIO_AP_RDY ); udelay(WAKE_UP_BP_UDELAY); GPSR(GPIO_AP_RDY ) = GPIO_bit(GPIO_AP_RDY ); }else { GPSR(GPIO_AP_RDY ) = GPIO_bit(GPIO_AP_RDY ); udelay(WAKE_UP_BP_UDELAY); GPCR(GPIO_AP_RDY ) = GPIO_bit(GPIO_AP_RDY ); } begin = jiffies; while(!GPIO_is_high(GPIO_BP_RDY) && (jiffies < (begin+HZ))) ; if(!GPIO_is_high(GPIO_BP_RDY)) { printk("%s: Wakeup BP timeout! BP is still in sleep state!\n", __FUNCTION__); } } #else set_GPIO_mode(GPIO_IN | 41); if(GPIO_is_high(41)) { if(GPIO_is_high(GPIO_MCU_INT_SW)) GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW); else { GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW); } begin = jiffies; while(GPIO_is_high(41) && (jiffies < (begin+HZ))) printk("%s: waitting for BP active!\n", __FUNCTION__); if(GPIO_is_high(GPIO_MCU_INT_SW)) GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW); else { GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW); } } #endif /* end Levis */ /* Reset the device */ if (usb_hub_port_reset(hub, port, dev, delay)) { usb_free_dev(dev); break; } /* Find a new device ID for it */ usb_connect(dev); /* Set up TT records, if needed */ if (hub->tt) { dev->tt = hub->tt; dev->ttport = hub->ttport; } else if (dev->speed != USB_SPEED_HIGH && hub->speed == USB_SPEED_HIGH) { dev->tt = &hubstate->tt; dev->ttport = port + 1; } /* Save readable and stable topology id, distinguishing * devices by location for diagnostics, tools, etc. The * string is a path along hub ports, from the root. Each * device's id will be stable until USB is re-cabled, and * hubs are often labeled with these port numbers. * * Initial size: ".NN" times five hubs + NUL = 16 bytes max * (quite rare, since most hubs have 4-6 ports). */ pdev = dev->parent; if (pdev->devpath [0] != '0') /* parent not root? */ len = snprintf (dev->devpath, sizeof dev->devpath, "%s.%d", pdev->devpath, port + 1); /* root == "0", root port 2 == "2", port 3 that hub "2.3" */ else len = snprintf (dev->devpath, sizeof dev->devpath, "%d", port + 1); if (len == sizeof dev->devpath) warn ("devpath size! usb/%03d/%03d path %s", dev->bus->busnum, dev->devnum, dev->devpath); info("new USB device %s-%s, assigned address %d", dev->bus->bus_name, dev->devpath, dev->devnum); /* Run it through the hoops (find a driver, etc) */ if (!usb_new_device(dev)) goto done; /* Free the configuration if there was an error */ usb_free_dev(dev); /* Switch to a long reset time */ delay = HUB_LONG_RESET_TIME; } hub->children[port] = NULL; usb_hub_port_disable(hub, port); done: up(&usb_address0_sem); }