Changeset 31cca4f3 in mainline for uspace/drv/bus/usb/xhci/endpoint.c


Ignore:
Timestamp:
2017-10-23T18:37:53Z (6 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.