Changeset a94cbfa in mainline for uspace/drv/bus/usb/ehci/ehci_rh.c


Ignore:
Timestamp:
2018-01-26T00:55:38Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
77733a9
Parents:
047fbc8
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-26 00:15:17)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-26 00:55:38)
Message:

ehci+ohci: proper handling of unfinished transfer

Because transfers can be aborted, the RH may not store a pointer to
them. Also, it's no longer true that the batch automatically locks the
endpoint, the mechanism must be used explicitly.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/ehci_rh.c

    r047fbc8 ra94cbfa  
    127127
    128128        ehci_rh_hub_desc_init(instance, EHCI_RD(caps->hcsparams));
    129         instance->unfinished_interrupt_transfer = NULL;
     129        instance->status_change_endpoint = NULL;
    130130
    131131        return virthub_base_init(&instance->base, name, &ops, instance,
     
    150150                usb_log_debug("RH(%p): BATCH(%p) adding as unfinished",
    151151                    instance, batch);
    152                 /* This is safe because only status change interrupt transfers
    153                  * return NAK. The assertion holds true because the batch
    154                  * existence prevents communication with that ep */
    155                 assert(instance->unfinished_interrupt_transfer == NULL);
    156                 instance->unfinished_interrupt_transfer = batch;
     152
     153                /* Lock the HC guard */
     154                fibril_mutex_lock(batch->ep->guard);
     155                const int err = endpoint_activate_locked(batch->ep, batch);
     156                if (err) {
     157                        fibril_mutex_unlock(batch->ep->guard);
     158                        return err;
     159                }
     160
     161                /*
     162                 * Asserting that the HC do not run two instances of the status
     163                 * change endpoint - shall be true.
     164                 */
     165                assert(!instance->status_change_endpoint);
     166
     167                endpoint_add_ref(batch->ep);
     168                instance->status_change_endpoint = batch->ep;
     169                fibril_mutex_unlock(batch->ep->guard);
    157170        } else {
    158171                usb_log_debug("RH(%p): BATCH(%p) virtual request complete: %s",
     
    172185int ehci_rh_interrupt(ehci_rh_t *instance)
    173186{
    174         //TODO atomic swap needed
    175         usb_transfer_batch_t *batch = instance->unfinished_interrupt_transfer;
    176         instance->unfinished_interrupt_transfer = NULL;
    177         usb_log_debug2("RH(%p): Interrupt. Processing batch: %p",
    178             instance, batch);
     187        endpoint_t *ep = instance->status_change_endpoint;
     188        if (!ep)
     189                return EOK;
     190
     191        fibril_mutex_lock(ep->guard);
     192        usb_transfer_batch_t * const batch = ep->active_batch;
     193        endpoint_deactivate_locked(ep);
     194        instance->status_change_endpoint = NULL;
     195        fibril_mutex_unlock(ep->guard);
     196
     197        endpoint_del_ref(ep);
     198
    179199        if (batch) {
     200                usb_log_debug2("RH(%p): Interrupt. Processing batch: %p",
     201                    instance, batch);
    180202                batch->error = virthub_base_request(&instance->base, batch->target,
    181203                    batch->dir, (void*) batch->setup.buffer,
Note: See TracChangeset for help on using the changeset viewer.