Changeset 0892663a in mainline for uspace/drv/bus/usb/xhci/bus.c


Ignore:
Timestamp:
2018-01-11T04:14:37Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9848c77
Parents:
bad4a05
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-11 03:59:03)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-11 04:14:37)
Message:

usbhost: device removal and off/onlining moved into the library

Also, it is just not possible to make generic transfer abortion. So the
current semantics of endpoint unregistering is also aborting the pending
transfer. As it is not yet implemented in XHCI, and the stub in UHCI is
missing the magic, it breaks offlining interrupt devices, such as mouse.

When finishing this commit, I came across the fact we need some more
synchronization above device. Guard can protect internal structures, but
it cannot synchronize multiple calls to offline, or offline & removal
between each other - they both need to allow driver to unregister
endpoints, and as such must release the guard.

File:
1 edited

Legend:

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

    rbad4a05 r0892663a  
    209209        xhci_device_t *xhci_dev = xhci_device_get(dev);
    210210
    211         /* Block creation of new endpoints and transfers. */
    212         usb_log_debug2("Device " XHCI_DEV_FMT " going offline.", XHCI_DEV_ARGS(*xhci_dev));
    213         fibril_mutex_lock(&dev->guard);
    214         dev->online = false;
    215         fibril_mutex_unlock(&dev->guard);
    216 
    217         /* Abort running transfers. */
    218         usb_log_debug2("Aborting all active transfers to device " XHCI_DEV_FMT ".", XHCI_DEV_ARGS(*xhci_dev));
    219         for (usb_endpoint_t i = 0; i < USB_ENDPOINT_MAX; ++i) {
    220                 xhci_endpoint_t *ep = xhci_device_get_endpoint(xhci_dev, i);
    221                 if (!ep)
    222                         continue;
    223 
    224                 endpoint_abort(&ep->base);
    225         }
    226 
    227         /* TODO: Figure out how to handle errors here. So far, they are reported and skipped. */
    228 
    229         /* Make DDF (and all drivers) forget about the device. */
    230         if ((err = ddf_fun_unbind(dev->fun))) {
    231                 usb_log_warning("Failed to unbind DDF function of device " XHCI_DEV_FMT ": %s",
    232                     XHCI_DEV_ARGS(*xhci_dev), str_error(err));
    233         }
    234 
    235211        /* Disable the slot, dropping all endpoints. */
    236212        const uint32_t slot_id = xhci_dev->slot_id;
     
    241217
    242218        bus->devices_by_slot[slot_id] = NULL;
    243 
    244         /* Unregister remaining endpoints, freeing memory. */
    245         for (usb_endpoint_t i = 0; i < USB_ENDPOINT_MAX; ++i) {
    246                 if (!dev->endpoints[i])
    247                         continue;
    248 
    249                 bus_endpoint_remove(dev->endpoints[i]);
    250         }
    251 
    252         /* Destroy DDF device. */
    253         /* XXX: Not a good idea, this method should not destroy devices. */
    254         hcd_ddf_fun_destroy(dev);
    255219}
    256220
     
    273237        if ((err = hc_configure_device(bus->hc, dev->slot_id))) {
    274238                usb_log_warning("Failed to configure device " XHCI_DEV_FMT ".", XHCI_DEV_ARGS(*dev));
    275         }
    276 
    277         /* Allow creation of new endpoints and transfers. */
    278         usb_log_debug2("Device " XHCI_DEV_FMT " going online.", XHCI_DEV_ARGS(*dev));
    279         fibril_mutex_lock(&dev_base->guard);
    280         dev_base->online = true;
    281         fibril_mutex_unlock(&dev_base->guard);
    282 
    283         if ((err = ddf_fun_online(dev_base->fun))) {
    284239                return err;
    285240        }
     
    294249 * Bus callback.
    295250 */
    296 static int device_offline(device_t *dev_base)
     251static void device_offline(device_t *dev_base)
    297252{
    298253        int err;
     
    303258        xhci_device_t *dev = xhci_device_get(dev_base);
    304259        assert(dev);
    305 
    306         /* Tear down all drivers working with the device. */
    307         if ((err = ddf_fun_offline(dev_base->fun))) {
    308                 return err;
    309         }
    310 
    311         /* Block creation of new endpoints and transfers. */
    312         usb_log_debug2("Device " XHCI_DEV_FMT " going offline.", XHCI_DEV_ARGS(*dev));
    313         fibril_mutex_lock(&dev_base->guard);
    314         dev_base->online = false;
    315         fibril_mutex_unlock(&dev_base->guard);
    316 
    317         /* We will need the endpoint array later for DS deallocation. */
    318         endpoint_t *endpoints[USB_ENDPOINT_MAX];
    319         memcpy(endpoints, dev->base.endpoints, sizeof(endpoints));
    320 
    321         for (usb_endpoint_t i = 1; i < USB_ENDPOINT_MAX; ++i) {
    322                 /* FIXME: Asserting here that the endpoint is not active. If not, EBUSY? */
    323                 dev->base.endpoints[i] = NULL;
    324         }
    325260
    326261        /* Issue one HC command to simultaneously drop all endpoints except zero. */
     
    329264                    XHCI_DEV_ARGS(*dev));
    330265        }
    331 
    332         /* Tear down TRB ring / PSA. */
    333         for (unsigned i = 1; i < ARRAY_SIZE(endpoints); ++i) {
    334                 if (!endpoints[i])
    335                         continue;
    336 
    337                 /* Bus reference */
    338                 endpoint_del_ref(endpoints[i]);
    339         }
    340 
    341         return EOK;
    342266}
    343267
     
    378302
    379303/**
    380  * Register an andpoint to the bus. Allocate its transfer ring(s) and inform
    381  * xHC about it.
     304 * Register an andpoint to the xHC.
    382305 *
    383306 * Bus callback.
    384307 */
    385308static int endpoint_register(endpoint_t *ep_base)
    386 {
    387         int err;
    388         xhci_bus_t *bus = bus_to_xhci_bus(endpoint_get_bus(ep_base));
    389         xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);
    390 
    391         xhci_device_t *dev = xhci_device_get(ep_base->device);
    392 
    393         usb_log_info("Endpoint " XHCI_EP_FMT " registered to XHCI bus.", XHCI_EP_ARGS(*ep));
    394 
    395         xhci_ep_ctx_t ep_ctx;
    396         xhci_setup_endpoint_context(ep, &ep_ctx);
    397 
    398         if ((err = hc_add_endpoint(bus->hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx)))
    399                 return err;
    400 
    401         return EOK;
    402 }
    403 
    404 /**
    405  * Unregister an endpoint. If the device is still available, inform the xHC
    406  * about it. Destroy resources allocated when registering.
    407  *
    408  * Bus callback.
    409  */
    410 static void endpoint_unregister(endpoint_t *ep_base)
    411309{
    412310        int err;
     
    415313        xhci_device_t *dev = xhci_device_get(ep_base->device);
    416314
    417         usb_log_info("Endpoint " XHCI_EP_FMT " unregistered from XHCI bus.", XHCI_EP_ARGS(*ep));
     315        xhci_ep_ctx_t ep_ctx;
     316        xhci_setup_endpoint_context(ep, &ep_ctx);
     317
     318        if ((err = hc_add_endpoint(bus->hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx)))
     319                return err;
     320
     321        return EOK;
     322}
     323
     324/**
     325 * Unregister an endpoint. If the device is still available, inform the xHC
     326 * about it.
     327 *
     328 * Bus callback.
     329 */
     330static void endpoint_unregister(endpoint_t *ep_base)
     331{
     332        int err;
     333        xhci_bus_t *bus = bus_to_xhci_bus(endpoint_get_bus(ep_base));
     334        xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);
     335        xhci_device_t *dev = xhci_device_get(ep_base->device);
    418336
    419337        /* If device slot is still available, drop the endpoint. */
Note: See TracChangeset for help on using the changeset viewer.