/* The UHCI spec says devices must have 2 ports, and goes on to say
* they may have more but gives no way to determine how many there
- * are. However, according to the UHCI spec, Bit 7 of the port
+ * are. However according to the UHCI spec, Bit 7 of the port
* status and control register is always set to 1. So we try to
- * use this to our advantage.
+ * use this to our advantage. Another common failure mode when
+ * a nonexistent register is addressed is to return all ones, so
+ * we test for that also.
*/
for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) {
unsigned int portstatus;
portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));
- if (!(portstatus & 0x0080))
+ if (!(portstatus & 0x0080) || portstatus == 0xffff)
break;
}
if (debug)
dev_info(uhci_dev(uhci), "detected %d ports\n", port);
- /* Anything less than 2 or greater than 7 is weird,
- * so we'll ignore it.
- */
- if (port < 2 || port > UHCI_RH_MAXCHILD) {
+ /* Anything greater than 7 is weird so we'll ignore it. */
+ if (port > UHCI_RH_MAXCHILD) {
dev_info(uhci_dev(uhci), "port count misdetected? "
"forcing to 2 ports\n");
port = 2;
int retval = -EBUSY;
int i;
dma_addr_t dma_handle;
- struct usb_device *udev;
struct dentry *dentry;
hcd->uses_new_polling = 1;
goto err_create_qh_pool;
}
- /* Initialize the root hub */
-
- udev = usb_alloc_dev(NULL, &hcd->self, 0);
- if (!udev) {
- dev_err(uhci_dev(uhci), "unable to allocate root hub\n");
- goto err_alloc_root_hub;
- }
-
uhci->term_td = uhci_alloc_td(uhci);
if (!uhci->term_td) {
dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n");
configure_hc(uhci);
start_rh(uhci);
-
- udev->speed = USB_SPEED_FULL;
-
- if (usb_hcd_register_root_hub(udev, hcd) != 0) {
- dev_err(uhci_dev(uhci), "unable to start root hub\n");
- retval = -ENOMEM;
- goto err_start_root_hub;
- }
-
return 0;
/*
* error exits:
*/
-err_start_root_hub:
- reset_hc(uhci);
- del_timer_sync(&uhci->stall_timer);
-
err_alloc_skelqh:
for (i = 0; i < UHCI_NUM_SKELQH; i++)
if (uhci->skelqh[i]) {
uhci->term_td = NULL;
err_alloc_term_td:
- usb_put_dev(udev);
-
-err_alloc_root_hub:
dma_pool_destroy(uhci->qh_pool);
uhci->qh_pool = NULL;