aboutsummaryrefslogtreecommitdiff
path: root/payloads/libpayload/drivers/usb/ehci_rh.c
diff options
context:
space:
mode:
Diffstat (limited to 'payloads/libpayload/drivers/usb/ehci_rh.c')
-rw-r--r--payloads/libpayload/drivers/usb/ehci_rh.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/payloads/libpayload/drivers/usb/ehci_rh.c b/payloads/libpayload/drivers/usb/ehci_rh.c
index 67f63cc481..6109505c7f 100644
--- a/payloads/libpayload/drivers/usb/ehci_rh.c
+++ b/payloads/libpayload/drivers/usb/ehci_rh.c
@@ -48,6 +48,17 @@ typedef struct {
static void
ehci_rh_destroy (usbdev_t *dev)
{
+ int port;
+
+ /* Tear down all devices below the root hub (in bottom-up order). */
+ for (port = 0; port < RH_INST(dev)->n_ports; port++) {
+ if (RH_INST(dev)->devices[port] != -1) {
+ usb_detach_device(dev->controller,
+ RH_INST(dev)->devices[port]);
+ RH_INST(dev)->devices[port] = -1;
+ }
+ }
+
free (RH_INST(dev)->devices);
free (RH_INST(dev));
}
@@ -156,10 +167,10 @@ ehci_rh_init (usbdev_t *dev)
dev->destroy = ehci_rh_destroy;
dev->poll = ehci_rh_poll;
- dev->data = malloc(sizeof(rh_inst_t));
-
+ dev->data = xmalloc(sizeof(rh_inst_t));
RH_INST(dev)->n_ports = EHCI_INST(dev->controller)->capabilities->hcsparams & HCS_NPORTS_MASK;
RH_INST(dev)->ports = EHCI_INST(dev->controller)->operation->portsc;
+ RH_INST(dev)->devices = xmalloc(RH_INST(dev)->n_ports * sizeof(int));
usb_debug("root hub has %x ports\n", RH_INST(dev)->n_ports);
@@ -175,7 +186,6 @@ ehci_rh_init (usbdev_t *dev)
}
mdelay(20); // ehci spec 2.3.9
- RH_INST(dev)->devices = malloc(RH_INST(dev)->n_ports * sizeof(int));
for (i=0; i < RH_INST(dev)->n_ports; i++) {
RH_INST(dev)->devices[i] = -1;
ehci_rh_scanport(dev, i);