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/lib/usbhost/include/usb/host/endpoint.h

    ra6afb4c r4db49344  
    5353typedef struct usb_transfer_batch usb_transfer_batch_t;
    5454
    55 /** Host controller side endpoint structure. */
     55/**
     56 * Host controller side endpoint structure.
     57 *
     58 * This structure, though reference-counted, is very fragile. It is responsible
     59 * for synchronizing transfer batch scheduling and completion.
     60 *
     61 * To avoid situations, in which two locks must be obtained to schedule/finish
     62 * a transfer, the endpoint inherits a lock from the outside. Because the
     63 * concrete instance of mutex can be unknown at the time of initialization,
     64 * the HC shall pass the right lock at the time of onlining the endpoint.
     65 *
     66 * The fields used for scheduling (online, active_batch) are to be used only
     67 * under that guard and by functions designed for this purpose. The driver can
     68 * also completely avoid using this mechanism, in which case it is on its own in
     69 * question of transfer aborting.
     70 *
     71 * Relevant information can be found in the documentation of HelenOS xHCI
     72 * project.
     73 */
    5674typedef struct endpoint {
    5775        /** USB device */
     
    5977        /** Reference count. */
    6078        atomic_t refcnt;
    61         /** Reserved bandwidth. */
    62         size_t bandwidth;
    63         /** The currently active transfer batch. Write using methods, read under guard. */
     79
     80        /** An inherited guard */
     81        fibril_mutex_t *guard;
     82        /** Whether it's allowed to schedule on this endpoint */
     83        bool online;
     84        /** The currently active transfer batch. */
    6485        usb_transfer_batch_t *active_batch;
    65         /** Protects resources and active status changes. */
    66         fibril_mutex_t guard;
    6786        /** Signals change of active status. */
    6887        fibril_condvar_t avail;
    6988
    70         /** Enpoint number */
     89        /** Reserved bandwidth. Needed for USB2 bus. */
     90        size_t bandwidth;
     91        /** Endpoint number */
    7192        usb_endpoint_t endpoint;
    7293        /** Communication direction. */
     
    79100        /** Maximum size of one transfer */
    80101        size_t max_transfer_size;
    81         /** Number of packats that can be sent in one service interval (not necessarily uframe) */
     102        /**
     103         * Number of packets that can be sent in one service interval
     104         * (not necessarily uframe, despite its name)
     105         */
    82106        unsigned packets_per_uframe;
    83107
     
    90114extern void endpoint_del_ref(endpoint_t *);
    91115
     116extern void endpoint_set_online(endpoint_t *, fibril_mutex_t *);
     117extern void endpoint_set_offline_locked(endpoint_t *);
     118
    92119extern void endpoint_wait_timeout_locked(endpoint_t *ep, suseconds_t);
    93 extern void endpoint_activate_locked(endpoint_t *, usb_transfer_batch_t *);
     120extern int endpoint_activate_locked(endpoint_t *, usb_transfer_batch_t *);
    94121extern void endpoint_deactivate_locked(endpoint_t *);
    95122
Note: See TracChangeset for help on using the changeset viewer.