[ehci] Poll child companion controllers after disowning port

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/36/head
Michael Brown 2015-05-08 15:33:18 +01:00
parent e4783add79
commit b3de9664c7
2 changed files with 59 additions and 0 deletions

View File

@ -292,6 +292,51 @@ static void ehci_legacy_release ( struct ehci_device *ehci,
DBGC ( ehci, "EHCI %p released ownership to BIOS\n", ehci ); DBGC ( ehci, "EHCI %p released ownership to BIOS\n", ehci );
} }
/******************************************************************************
*
* Companion controllers
*
******************************************************************************
*/
/**
* Poll child companion controllers
*
* @v ehci EHCI device
*/
static void ehci_poll_companions ( struct ehci_device *ehci ) {
struct usb_bus *bus;
struct device_description *desc;
/* Poll any USB buses belonging to child companion controllers */
for_each_usb_bus ( bus ) {
/* Get underlying devices description */
desc = &bus->dev->desc;
/* Skip buses that are not PCI devices */
if ( desc->bus_type != BUS_TYPE_PCI )
continue;
/* Skip buses that are not part of the same PCI device */
if ( PCI_FIRST_FUNC ( desc->location ) !=
PCI_FIRST_FUNC ( ehci->bus->dev->desc.location ) )
continue;
/* Skip buses that are not UHCI or OHCI PCI devices */
if ( ( desc->class != PCI_CLASS ( PCI_CLASS_SERIAL,
PCI_CLASS_SERIAL_USB,
PCI_CLASS_SERIAL_USB_UHCI ))&&
( desc->class != PCI_CLASS ( PCI_CLASS_SERIAL,
PCI_CLASS_SERIAL_USB,
PCI_CLASS_SERIAL_USB_OHCI ) ))
continue;
/* Poll child companion controller bus */
usb_poll ( bus );
}
}
/****************************************************************************** /******************************************************************************
* *
* Run / stop / reset * Run / stop / reset
@ -1460,9 +1505,17 @@ static int ehci_root_enable ( struct usb_hub *hub, struct usb_port *port ) {
return -ETIMEDOUT; return -ETIMEDOUT;
disown: disown:
/* Disown port */
portsc &= ~EHCI_PORTSC_CHANGE; portsc &= ~EHCI_PORTSC_CHANGE;
portsc |= EHCI_PORTSC_OWNER; portsc |= EHCI_PORTSC_OWNER;
writel ( portsc, ehci->op + EHCI_OP_PORTSC ( port->address ) ); writel ( portsc, ehci->op + EHCI_OP_PORTSC ( port->address ) );
/* Delay to allow child companion controllers to settle */
mdelay ( EHCI_DISOWN_DELAY_MS );
/* Poll child companion controllers */
ehci_poll_companions ( ehci );
return -ENODEV; return -ENODEV;
} }

View File

@ -424,6 +424,12 @@ ehci_ring_remaining ( struct ehci_ring *ring ) {
*/ */
#define EHCI_PORT_POWER_DELAY_MS 20 #define EHCI_PORT_POWER_DELAY_MS 20
/** Time to delay after releasing ownership of a port
*
* This is a policy decision.
*/
#define EHCI_DISOWN_DELAY_MS 100
/** Maximum time to wait for BIOS to release ownership /** Maximum time to wait for BIOS to release ownership
* *
* This is a policy decision. * This is a policy decision.