Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 40a3bfa in mainline


Ignore:
Timestamp:
2017-10-28T11:25:11Z (4 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
lfn, master
Children:
d46ceb2b
Parents:
58ac3ec
Message:

Refactoring. Moved a lot of device deallocation from root hub to bus. Also zeroing DCBAA to avoid assertion fails upon reconnection. Temporarily disabled freeing endpoint data structures due to suspected memory corruption.

Location:
uspace/drv/bus/usb/xhci
Files:
3 edited

Legend:

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

    r58ac3ec r40a3bfa  
    185185int xhci_bus_remove_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
    186186{
     187        int err;
    187188        xhci_device_t *xhci_dev = xhci_device_get(dev);
     189
     190        /* Block creation of new endpoints and transfers. */
     191        usb_log_debug2("Device '%s' going offline.", ddf_fun_get_name(dev->fun));
     192        fibril_mutex_lock(&dev->guard);
     193        xhci_dev->online = false;
     194        fibril_mutex_unlock(&dev->guard);
     195
     196        /* Abort running transfers. */
     197        usb_log_debug2("Aborting all active transfers to '%s'.", ddf_fun_get_name(dev->fun));
     198        for (size_t i = 0; i < ARRAY_SIZE(xhci_dev->endpoints); ++i) {
     199                xhci_endpoint_t *ep = xhci_dev->endpoints[i];
     200                if (!ep || !ep->base.active)
     201                        continue;
     202
     203                /* FIXME: This is racy. */
     204                if ((err = xhci_transfer_abort(&ep->active_transfer))) {
     205                        usb_log_warning("Failed to abort active %s transfer to "
     206                            " endpoint %d of detached device '%s': %s",
     207                            usb_str_transfer_type(ep->base.transfer_type),
     208                            ep->base.endpoint, ddf_fun_get_name(dev->fun),
     209                            str_error(err));
     210                }
     211        }
     212
     213        /* TODO: Figure out how to handle errors here. So far, they are reported and skipped. */
     214
     215        /* Make DDF (and all drivers) forget about the device. */
     216        if ((err = ddf_fun_unbind(dev->fun))) {
     217                usb_log_warning("Failed to unbind DDF function of detached device '%s': %s",
     218                    ddf_fun_get_name(dev->fun), str_error(err));
     219        }
     220
     221        /* Deconfigure device if it's still attached. */
     222        if (!xhci_dev->detached) {
     223                if ((err = hc_deconfigure_device(hc, xhci_dev->slot_id))) {
     224                        usb_log_warning("Failed to deconfigure detached device '%s': %s",
     225                            ddf_fun_get_name(dev->fun), str_error(err));
     226                }
     227        }
    188228
    189229        /* Unregister remaining endpoints. */
     
    192232                        continue;
    193233
    194                 const int err = unregister_endpoint(&bus->base, &xhci_dev->endpoints[i]->base);
    195                 if (err)
     234                if ((err = unregister_endpoint(&bus->base, &xhci_dev->endpoints[i]->base))) {
    196235                        usb_log_warning("Failed to unregister EP (%u:%u): %s", dev->address, i, str_error(err));
     236                }
    197237        }
    198238
    199239        // XXX: Ugly here. Move to device_destroy at endpoint.c?
     240        if ((err = hc_disable_slot(hc, xhci_dev->slot_id))) {
     241                usb_log_warning("Failed to disable slot %d for device '%s': %s",
     242                    xhci_dev->slot_id, ddf_fun_get_name(dev->fun), str_error(err));
     243        }
     244
    200245        free32(xhci_dev->dev_ctx);
    201246        hc->dcbaa[xhci_dev->slot_id] = 0;
     247
     248        bus->devices_by_slot[xhci_dev->slot_id] = NULL;
     249
    202250        return EOK;
    203251}
     
    305353        /* Tear down TRB ring / PSA. */
    306354        /* TODO: Make this method "noexcept" */
    307         if ((err = xhci_endpoint_free_transfer_ds(ep))) {
     355        /* FIXME: There is some memory corruption going on, causing this to crash. */
     356        /*if ((err = xhci_endpoint_free_transfer_ds(ep))) {
    308357                usb_log_error("Failed to free resources of an endpoint.");
    309         }
     358        }*/
    310359
    311360        return EOK;
  • uspace/drv/bus/usb/xhci/endpoint.h

    r58ac3ec r40a3bfa  
    125125        /** True if the device can add new endpoints and schedule transfers. */
    126126        volatile bool online;
     127
     128        /** True if the device has been physically detached from the socket. */
     129        volatile bool detached;
    127130} xhci_device_t;
    128131
  • uspace/drv/bus/usb/xhci/rh.c

    r58ac3ec r40a3bfa  
    187187        usb_log_info("Device '%s' at port %u has been disconnected.", ddf_fun_get_name(dev->base.fun), port_id);
    188188
    189         /* Block creation of new endpoints and transfers. */
     189        /* Mark the device as detached. */
    190190        fibril_mutex_lock(&dev->base.guard);
    191         dev->online = false;
     191        dev->detached = true;
    192192        fibril_mutex_unlock(&dev->base.guard);
    193193
     
    197197        fibril_mutex_unlock(&rh->device.base.guard);
    198198
    199         usb_log_debug2("Aborting all active transfers to '%s'.", ddf_fun_get_name(dev->base.fun));
    200 
    201         /* Abort running transfers. */
    202         for (size_t i = 0; i < ARRAY_SIZE(dev->endpoints); ++i) {
    203                 xhci_endpoint_t *ep = dev->endpoints[i];
    204                 if (!ep || !ep->base.active)
    205                         continue;
    206 
    207                 /* FIXME: This is racy. */
    208                 if ((err = xhci_transfer_abort(&ep->active_transfer))) {
    209                         usb_log_warning("Failed to abort active %s transfer to "
    210                             " endpoint %d of detached device '%s': %s",
    211                             usb_str_transfer_type(ep->base.transfer_type),
    212                             ep->base.endpoint, ddf_fun_get_name(dev->base.fun),
    213                             str_error(err));
    214                 }
    215         }
    216 
    217         /* TODO: Figure out how to handle errors here. So far, they are reported and skipped. */
    218         /* TODO: Move parts of the code below to xhci_bus_remove_device() */
    219 
    220         /* Make DDF (and all drivers) forget about the device. */
    221         if ((err = ddf_fun_unbind(dev->base.fun))) {
    222                 usb_log_warning("Failed to unbind DDF function of detached device '%s': %s",
    223                     ddf_fun_get_name(dev->base.fun), str_error(err));
    224         }
    225 
    226         /* Unregister EP0. */
    227         if ((err = bus_remove_endpoint(&rh->hc->bus.base, &dev->endpoints[0]->base))) {
    228                 usb_log_warning("Failed to unregister configuration endpoint of device '%s' from XHCI bus: %s",
    229                     ddf_fun_get_name(dev->base.fun), str_error(err));
    230         }
    231 
    232         /* Deconfigure device. */
    233         if ((err = hc_deconfigure_device(rh->hc, dev->slot_id))) {
    234                 usb_log_warning("Failed to deconfigure detached device '%s': %s",
    235                     ddf_fun_get_name(dev->base.fun), str_error(err));
    236         }
    237 
    238         /* TODO: Free EP0 structures. */
    239         /* TODO: Destroy EP0 by removing its last reference. */
    240 
    241199        /* Remove device from XHCI bus. */
    242200        if ((err = xhci_bus_remove_device(&rh->hc->bus, rh->hc, &dev->base))) {
     
    245203        }
    246204
    247         /* Disable device slot. */
    248         if ((err = hc_disable_slot(rh->hc, dev->slot_id))) {
    249                 usb_log_warning("Failed to disable slot for device '%s': %s",
    250                     ddf_fun_get_name(dev->base.fun), str_error(err));
    251         }
    252 
    253205        /* Destroy DDF device. */
    254206        hcd_ddf_device_destroy(&dev->base);
    255207
    256         // TODO: Free device context.
    257         // TODO: Free TRB rings.
    258         // TODO: Figure out what was forgotten and free that as well.
     208        /* TODO: Figure out what was forgotten and free that as well. */
    259209
    260210        return EOK;
Note: See TracChangeset for help on using the changeset viewer.