Changeset 4db49344 in mainline for uspace/drv/bus/usb/ohci/ohci_bus.c


Ignore:
Timestamp:
2018-01-23T21:52:28Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3dd80f8
Parents:
a6afb4c
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-23 20:49:35)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-23 21:52:28)
Message:

usb: fix wrong design of transfer aborting

Apparently, we didn't do a good job in thinking through the problem.
In older HCs, it was done just wrong - the UHCI implementation commited
a batch that could have been already aborted, and EHCI+OHCI might miss
an interrupt because they commited the batch sooner than they added it
to their checked list.

This commit takes everything from the other end, which is probably the
only right one. Instead of an endpoint having an extra mutex, it
inherits a mutex from the outside. It never locks it though, it just
checks if the mutex is locked and uses it for waiting on condition
variables.

This mutex is supposed to be the one which the HC driver uses for
locking its structures in scheduling. This way, we avoid the ABBA
deadlock completely, while preserving the synchronization on an
endpoint.

The good thing is that this implementation is much easier to extend with
multiple active batches per endpoint.

File:
1 edited

Legend:

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

    ra6afb4c r4db49344  
    115115        ed_init(ohci_ep->ed, ep, ohci_ep->td);
    116116        hc_enqueue_endpoint(bus->hc, ep);
     117        endpoint_set_online(ep, &bus->hc->guard);
    117118
    118119        return EOK;
     
    128129        hc_dequeue_endpoint(bus->hc, ep);
    129130
    130         ohci_endpoint_t * const ohci_ep = ohci_endpoint_get(ep);
     131        /*
     132         * Now we can be sure the active transfer will not be completed,
     133         * as it's out of the schedule, and HC acknowledged it.
     134         */
    131135
    132         /*
    133          * Now we can be sure the active transfer will not be completed. But first,
    134          * make sure that the handling fibril won't use its link in pending list.
    135          */
     136        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
     137
    136138        fibril_mutex_lock(&hc->guard);
    137         if (link_in_use(&ohci_ep->pending_link))
    138                 /* pending list reference */
    139                 endpoint_del_ref(ep);
     139        endpoint_set_offline_locked(ep);
    140140        list_remove(&ohci_ep->pending_link);
    141         fibril_mutex_unlock(&hc->guard);
    142 
    143         /*
    144          * Finally, the endpoint shall not be used anywhere else. Finish the
    145          * pending batch.
    146          */
    147         fibril_mutex_lock(&ep->guard);
    148141        usb_transfer_batch_t * const batch = ep->active_batch;
    149142        endpoint_deactivate_locked(ep);
    150         fibril_mutex_unlock(&ep->guard);
     143        fibril_mutex_unlock(&hc->guard);
    151144
    152145        if (batch) {
Note: See TracChangeset for help on using the changeset viewer.