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

Changeset 31cca4f3 in mainline


Ignore:
Timestamp:
2017-10-23T18:37:53Z (4 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
lfn, master
Children:
e160bfe8
Parents:
81487c4a
Message:

Corrected deadlock in IPC between USB remote interface and usbdev driver. Extracted creation of input context. Now issuing drop endpoint command when the endpoint is removed.

Location:
uspace
Files:
4 edited

Legend:

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

    r81487c4a r31cca4f3  
    139139        free32(xhci_dev->dev_ctx);
    140140        hc->dcbaa[xhci_dev->slot_id] = 0;
    141         return ENOTSUP;
     141        return EOK;
    142142}
    143143
  • uspace/drv/bus/usb/xhci/endpoint.c

    r81487c4a r31cca4f3  
    8181int xhci_endpoint_alloc_transfer_ds(xhci_endpoint_t *xhci_ep)
    8282{
    83         int err;
    84 
    8583        if (endpoint_uses_streams(xhci_ep)) {
    8684                /* Set up primary stream context array if needed. */
    8785                const size_t size = primary_stream_ctx_array_size(xhci_ep);
     86                usb_log_debug2("Allocating primary stream context array of size %lu for endpoint %d:%d.",
     87                    size, xhci_ep->base.target.address, xhci_ep->base.target.endpoint);
    8888
    8989                xhci_ep->primary_stream_ctx_array = malloc32(size * sizeof(xhci_stream_ctx_t));
     
    9494                memset(xhci_ep->primary_stream_ctx_array, 0, size * sizeof(xhci_stream_ctx_t));
    9595        } else {
     96                usb_log_debug2("Allocating main transfer ring for endpoint %d:%d.",
     97                    xhci_ep->base.target.address, xhci_ep->base.target.endpoint);
     98
    9699                xhci_ep->primary_stream_ctx_array = NULL;
     100
     101                int err;
    97102                if ((err = xhci_trb_ring_init(&xhci_ep->ring))) {
    98103                        return err;
     
    105110int xhci_endpoint_free_transfer_ds(xhci_endpoint_t *xhci_ep)
    106111{
    107         int err;
    108 
    109112        if (endpoint_uses_streams(xhci_ep)) {
     113                usb_log_debug2("Freeing primary stream context array for endpoint %d:%d.",
     114                    xhci_ep->base.target.address, xhci_ep->base.target.endpoint);
     115
    110116                // TODO: What about secondaries?
    111117                free32(xhci_ep->primary_stream_ctx_array);
    112118        } else {
     119                usb_log_debug2("Freeing main transfer ring for endpoint %d:%d.",
     120                    xhci_ep->base.target.address, xhci_ep->base.target.endpoint);
     121
     122                int err;
    113123                if ((err = xhci_trb_ring_fini(&xhci_ep->ring))) {
    114124                        return err;
     
    232242};
    233243
    234 int xhci_device_add_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
    235 {
    236         assert(dev);
    237         assert(ep);
    238 
    239         /* Offline devices don't create new endpoints other than EP0. */
    240         if (!dev->online) {
    241                 return EAGAIN;
    242         }
    243 
    244         int err = ENOMEM;
    245         const usb_endpoint_t ep_num = ep->base.target.endpoint;
    246 
    247         assert(&dev->base == ep->base.device);
    248         assert(dev->base.address == ep->base.target.address);
    249         assert(!dev->endpoints[ep_num]);
    250 
    251         dev->endpoints[ep_num] = ep;
    252         ++dev->active_endpoint_count;
    253 
    254         if (ep_num == 0)
    255                 /* EP 0 is initialized while setting up the device,
    256                  * so we must not issue the command now. */
    257                 return EOK;
    258 
    259         // FIXME: Set these from usb_superspeed_endpoint_companion_descriptor_t:
    260         ep->max_streams = 0;
    261         ep->max_burst = 0;
    262         ep->mult = 0;
    263 
    264         xhci_endpoint_alloc_transfer_ds(ep);
    265 
    266         // Prepare input context.
     244static int create_valid_input_ctx(xhci_input_ctx_t **out_ictx)
     245{
    267246        xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t));
    268         if (!ictx)
    269                 goto err;
     247        if (!ictx) {
     248                return ENOMEM;
     249        }
    270250
    271251        memset(ictx, 0, sizeof(xhci_input_ctx_t));
     
    277257        XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0);
    278258
     259        if (out_ictx) {
     260                *out_ictx = ictx;
     261        }
     262
     263        return EOK;
     264}
     265
     266int xhci_device_add_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
     267{
     268        assert(dev);
     269        assert(ep);
     270
     271        /* Offline devices don't create new endpoints other than EP0. */
     272        if (!dev->online) {
     273                return EAGAIN;
     274        }
     275
     276        int err = ENOMEM;
     277        const usb_endpoint_t ep_num = ep->base.target.endpoint;
     278
     279        assert(&dev->base == ep->base.device);
     280        assert(dev->base.address == ep->base.target.address);
     281        assert(!dev->endpoints[ep_num]);
     282
     283        dev->endpoints[ep_num] = ep;
     284        ++dev->active_endpoint_count;
     285
     286        if (ep_num == 0) {
     287                /* EP 0 is initialized while setting up the device,
     288                 * so we must not issue the command now. */
     289                return EOK;
     290        }
     291
     292        // FIXME: Set these from usb_superspeed_endpoint_companion_descriptor_t:
     293        ep->max_streams = 0;
     294        ep->max_burst = 0;
     295        ep->mult = 0;
     296
     297        /* Set up TRB ring / PSA. */
     298        if ((err = xhci_endpoint_alloc_transfer_ds(ep))) {
     299                goto err;
     300        }
     301
     302        /* Issue configure endpoint command (sec 4.3.5). */
     303        xhci_input_ctx_t *ictx;
     304        if ((err = create_valid_input_ctx(&ictx))) {
     305                goto err_ds;
     306        }
     307
    279308        const unsigned ep_idx = xhci_endpoint_index(ep);
    280309        XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
    281 
    282         xhci_ep_ctx_t *ep_ctx = &ictx->endpoint_ctx[ep_idx];
    283         setup_ep_ctx_helpers[ep->base.transfer_type](ep, ep_ctx);
    284 
    285         // Issue configure endpoint command (sec 4.3.5).
     310        setup_ep_ctx_helpers[ep->base.transfer_type](ep, &ictx->endpoint_ctx[ep_idx]);
     311
    286312        xhci_cmd_t cmd;
    287313        xhci_cmd_init(&cmd);
    288314
    289315        cmd.slot_id = dev->slot_id;
    290         xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx);
    291         if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK)
     316
     317        if ((err = xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx))) {
    292318                goto err_ictx;
     319        }
     320
     321        if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT))) {
     322                goto err_ictx;
     323        }
    293324
    294325        xhci_cmd_fini(&cmd);
     
    299330err_ictx:
    300331        free32(ictx);
     332err_ds:
     333        xhci_endpoint_free_transfer_ds(ep);
    301334err:
    302335        dev->endpoints[ep_num] = NULL;
     
    311344        assert(dev->endpoints[ep->base.target.endpoint]);
    312345
    313         // TODO: Issue configure endpoint command to drop this endpoint.
    314 
    315         // FIXME: Ignoring return code.
    316         xhci_endpoint_free_transfer_ds(ep);
     346        int err = ENOMEM;
     347        const usb_endpoint_t ep_num = ep->base.target.endpoint;
    317348
    318349        dev->endpoints[ep->base.target.endpoint] = NULL;
    319350        --dev->active_endpoint_count;
    320         return EOK;
    321 }
    322 
    323 xhci_endpoint_t * xhci_device_get_endpoint(xhci_device_t *dev, usb_endpoint_t ep)
    324 {
    325         return dev->endpoints[ep];
    326 }
    327 
    328 int xhci_device_configure(xhci_device_t *dev, xhci_hc_t *hc)
    329 {
    330         int err;
    331 
    332         // Prepare input context.
    333         xhci_input_ctx_t *ictx = malloc(sizeof(xhci_input_ctx_t));
    334         if (!ictx) {
    335                 return ENOMEM;
    336         }
    337 
    338         memset(ictx, 0, sizeof(xhci_input_ctx_t));
    339 
    340         // Quoting sec. 4.6.6: A1, D0, D1 are down, A0 is up.
    341         XHCI_INPUT_CTRL_CTX_ADD_CLEAR(ictx->ctrl_ctx, 1);
    342         XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 0);
    343         XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 1);
    344         XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0);
    345 
    346         // TODO: Set slot context and other flags. (probably forgot a lot of 'em)
    347 
    348         // Issue configure endpoint command (sec 4.3.5).
     351
     352        if (ep_num == 0) {
     353                /* EP 0 is finalized while releasing the device,
     354                 * so we must not issue the command now. */
     355                return EOK;
     356        }
     357
     358        /* Issue configure endpoint command to drop this endpoint. */
     359        xhci_input_ctx_t *ictx;
     360        if ((err = create_valid_input_ctx(&ictx))) {
     361                goto err;
     362        }
     363
     364        const unsigned ep_idx = xhci_endpoint_index(ep);
     365        XHCI_INPUT_CTRL_CTX_DROP_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
     366
    349367        xhci_cmd_t cmd;
    350368        xhci_cmd_init(&cmd);
    351369
    352370        cmd.slot_id = dev->slot_id;
    353         xhci_send_configure_endpoint_command(hc, &cmd, ictx);
    354         if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK)
     371
     372        if ((err = xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx))) {
     373                goto err_ictx;
     374        }
     375
     376        if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT))) {
     377                goto err_ictx;
     378        }
     379
     380        xhci_cmd_fini(&cmd);
     381
     382        /* Tear down TRB ring / PSA. */
     383        /* FIXME: For some reason, this causes crash at xhci_trb_ring_fini.
     384        if ((err = xhci_endpoint_free_transfer_ds(ep))) {
    355385                goto err_cmd;
     386        }
     387        */
     388
     389        free32(ictx);
     390        return EOK;
     391
     392err_ictx:
     393        free32(ictx);
     394err:
     395        dev->endpoints[ep_num] = ep;
     396        ++dev->active_endpoint_count;
     397        return err;
     398}
     399
     400xhci_endpoint_t *xhci_device_get_endpoint(xhci_device_t *dev, usb_endpoint_t ep)
     401{
     402        return dev->endpoints[ep];
     403}
     404
     405int xhci_device_configure(xhci_device_t *dev, xhci_hc_t *hc)
     406{
     407        int err;
     408
     409        /* Issue configure endpoint command (sec 4.3.5). */
     410        xhci_input_ctx_t *ictx;
     411        if ((err = create_valid_input_ctx(&ictx))) {
     412                goto err;
     413        }
     414
     415        // TODO: Set slot context and other flags. (probably forgot a lot of 'em)
     416
     417        xhci_cmd_t cmd;
     418        xhci_cmd_init(&cmd);
     419
     420        cmd.slot_id = dev->slot_id;
     421
     422        if ((err = xhci_send_configure_endpoint_command(hc, &cmd, ictx))) {
     423                goto err_cmd;
     424        }
     425
     426        if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT))) {
     427                goto err_cmd;
     428        }
    356429
    357430        xhci_cmd_fini(&cmd);
     431
     432        free32(ictx);
    358433        return EOK;
    359434
    360435err_cmd:
    361         free(ictx);
     436        free32(ictx);
     437err:
    362438        return err;
    363439}
  • uspace/drv/bus/usb/xhci/rh.c

    r81487c4a r31cca4f3  
    315315        }
    316316
     317        /* TODO: Figure out how to handle errors here. So far, they are reported and skipped. */
     318
    317319        /* Make DDF (and all drivers) forget about the device. */
    318320        if ((err = ddf_fun_unbind(dev->base.fun))) {
     
    321323        }
    322324
    323         /* FIXME:
    324          * A deadlock happens on the previous line. For some reason, the HID driver
    325          * does not fully release its DDF function (tracked it down to release_endpoint
    326          * in usb_remote.c so far).
    327          *
    328          * For that reason as well, the following 3 lines are untested.
    329          */
    330 
    331         xhci_bus_remove_device(&rh->hc->bus, rh->hc, &dev->base);
    332         hc_disable_slot(rh->hc, dev->slot_id);
     325        // TODO: Remove EP0.
     326        // TODO: Deconfigure device.
     327
     328        /* Remove device from XHCI bus. */
     329        if ((err = xhci_bus_remove_device(&rh->hc->bus, rh->hc, &dev->base))) {
     330                usb_log_warning("Failed to remove device '%s' from XHCI bus: %s",
     331                    ddf_fun_get_name(dev->base.fun), str_error(err));
     332        }
     333
     334        /* Disable device slot. */
     335        if ((err = hc_disable_slot(rh->hc, dev->slot_id))) {
     336                usb_log_warning("Failed to disable slot for device '%s': %s",
     337                    ddf_fun_get_name(dev->base.fun), str_error(err));
     338        }
     339
     340        /* Destroy DDF device. */
    333341        hcd_ddf_device_destroy(&dev->base);
    334342
  • uspace/lib/drv/generic/remote_usb.c

    r81487c4a r31cca4f3  
    510510
    511511        free(buffer);
    512         if (rc != EOK) {
    513                 async_answer_0(callid, rc);
    514         }
     512        async_answer_0(callid, rc);
    515513}
    516514
Note: See TracChangeset for help on using the changeset viewer.