Changeset a94cbfa in mainline for uspace/drv/bus/usb/ohci


Ignore:
Timestamp:
2018-01-26T00:55:38Z (8 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.

Location:
uspace/drv/bus/usb/ohci
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/ohci_rh.c

    r047fbc8 ra94cbfa  
    162162
    163163        ohci_rh_hub_desc_init(instance);
    164         instance->unfinished_interrupt_transfer = NULL;
     164        instance->status_change_endpoint = NULL;
    165165        return virthub_base_init(&instance->base, name, &ops, instance,
    166166            NULL, &instance->hub_descriptor.header, HUB_STATUS_CHANGE_PIPE);
     
    182182            batch->buffer, batch->buffer_size, &batch->transferred_size);
    183183        if (batch->error == ENAK) {
    184                 /* This is safe because only status change interrupt transfers
    185                  * return NAK. The assertion holds true because the batch
    186                  * existence prevents communication with that ep */
    187                 assert(instance->unfinished_interrupt_transfer == NULL);
    188                 instance->unfinished_interrupt_transfer = batch;
     184                /* Lock the HC guard */
     185                fibril_mutex_lock(batch->ep->guard);
     186                const int err = endpoint_activate_locked(batch->ep, batch);
     187                if (err) {
     188                        fibril_mutex_unlock(batch->ep->guard);
     189                        return err;
     190                }
     191
     192                /*
     193                 * Asserting that the HC do not run two instances of the status
     194                 * change endpoint - shall be true.
     195                 */
     196                assert(!instance->status_change_endpoint);
     197
     198                endpoint_add_ref(batch->ep);
     199                instance->status_change_endpoint = batch->ep;
     200                fibril_mutex_unlock(batch->ep->guard);
    189201        } else {
    190202                usb_transfer_batch_finish(batch);
     
    202214int ohci_rh_interrupt(ohci_rh_t *instance)
    203215{
    204         //TODO atomic swap needed
    205         usb_transfer_batch_t *batch = instance->unfinished_interrupt_transfer;
    206         instance->unfinished_interrupt_transfer = NULL;
     216        endpoint_t *ep = instance->status_change_endpoint;
     217        if (!ep)
     218                return EOK;
     219
     220        fibril_mutex_lock(ep->guard);
     221        usb_transfer_batch_t * const batch = ep->active_batch;
     222        endpoint_deactivate_locked(ep);
     223        instance->status_change_endpoint = NULL;
     224        fibril_mutex_unlock(ep->guard);
     225
     226        endpoint_del_ref(ep);
     227
    207228        if (batch) {
    208229                batch->error = virthub_base_request(&instance->base, batch->target,
  • uspace/drv/bus/usb/ohci/ohci_rh.h

    r047fbc8 ra94cbfa  
    6161                uint8_t rempow[STATUS_BYTES(OHCI_MAX_PORTS) * 2];
    6262        } __attribute__((packed)) hub_descriptor;
    63         /** interrupt transfer waiting for an actual interrupt to occur */
    64         usb_transfer_batch_t *unfinished_interrupt_transfer;
     63        /** A hacky way to emulate interrupts over polling. See ehci_rh. */
     64        endpoint_t *status_change_endpoint;
    6565} ohci_rh_t;
    6666
Note: See TracChangeset for help on using the changeset viewer.