Changeset a4e26882 in mainline for uspace/drv/bus/usb/xhci/rh.c


Ignore:
Timestamp:
2017-10-22T16:37:44Z (7 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4594baa
Parents:
2c091a6
Message:

Very rudimentary support for device disconnection.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/xhci/rh.c

    r2c091a6 ra4e26882  
    6868        rh->hc = hc;
    6969        rh->max_ports = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PORTS);
    70         rh->devices = (xhci_device_t **) malloc(rh->max_ports * sizeof(xhci_device_t *));
     70        rh->devices = (xhci_device_t **) calloc(rh->max_ports, sizeof(xhci_device_t *));
    7171        hc->rh.hc_device = device;
    72 
    73         memset(rh->devices, 0, rh->max_ports * sizeof(xhci_device_t *));
    7472
    7573        return device_init(&hc->rh.device);
     
    149147        usb_log_debug2("Obtained USB address: %d.\n", dev->address);
    150148
     149        /* From now on, the device is officially online, yay! */
     150        fibril_mutex_lock(&dev->guard);
     151        xhci_dev->online = true;
     152        fibril_mutex_unlock(&dev->guard);
     153
    151154        // XXX: Going around bus, duplicating code
    152155        ep0_base->device = dev;
     
    264267static int handle_disconnected_device(xhci_rh_t *rh, uint8_t port_id)
    265268{
     269        assert(rh);
     270        int err;
     271
    266272        /* Find XHCI device by the port. */
    267273        xhci_device_t *dev = rh->devices[port_id - 1];
    268274        if (!dev) {
    269                 /* Must be extraneous call */
     275                /* Must be extraneous call. */
    270276                return EOK;
    271277        }
    272278
    273         usb_log_info("Device at port %u has been disconnected.", port_id);
    274 
    275         // TODO: Destroy DDF function using _gone.
    276         // TODO: Remove device endpoints on the bus.
     279        usb_log_info("Device '%s' at port %u has been disconnected.", ddf_fun_get_name(dev->base.fun), port_id);
     280
     281        /* Block creation of new endpoints and transfers. */
     282        fibril_mutex_lock(&dev->base.guard);
     283        dev->online = false;
     284        fibril_mutex_unlock(&dev->base.guard);
     285
     286        fibril_mutex_lock(&rh->device.guard);
     287        list_remove(&dev->base.link);
     288        fibril_mutex_unlock(&rh->device.guard);
     289
     290        rh->devices[port_id - 1] = NULL;
     291        usb_log_debug2("Aborting all active transfers to '%s'.", ddf_fun_get_name(dev->base.fun));
     292
     293        /* Abort running transfers. */
     294        for (size_t i = 0; i < ARRAY_SIZE(dev->endpoints); ++i) {
     295                xhci_endpoint_t *ep = dev->endpoints[i];
     296                if (!ep || !ep->base.active)
     297                        continue;
     298
     299                if ((err = xhci_transfer_abort(&ep->active_transfer))) {
     300                        usb_log_warning("Failed to abort active %s transfer to "
     301                            " endpoint %d of detached device '%s': %s",
     302                            usb_str_transfer_type(ep->base.transfer_type),
     303                            ep->base.target.endpoint, ddf_fun_get_name(dev->base.fun),
     304                            str_error(err));
     305                }
     306        }
     307
     308        /* Make DDF (and all drivers) forget about the device. */
     309        if ((err = ddf_fun_unbind(dev->base.fun))) {
     310                usb_log_warning("Failed to unbind DDF function of detached device '%s': %s",
     311                    ddf_fun_get_name(dev->base.fun), str_error(err));
     312        }
     313
     314        /* FIXME:
     315         * A deadlock happens on the previous line. For some reason, the HID driver
     316         * does not fully release its DDF function (tracked it down to release_endpoint
     317         * in usb_remote.c so far).
     318         *
     319         * For that reason as well, the following 3 lines are untested.
     320         */
     321
     322        xhci_bus_remove_device(&rh->hc->bus, rh->hc, &dev->base);
     323        hc_disable_slot(rh->hc, dev->slot_id);
     324        hcd_ddf_device_destroy(&dev->base);
     325
    277326        // TODO: Free device context.
    278327        // TODO: Free TRB rings.
Note: See TracChangeset for help on using the changeset viewer.