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


Ignore:
Timestamp:
2018-01-23T21:52:28Z (6 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/hc.c

    ra6afb4c r4db49344  
    297297                return ohci_rh_schedule(&hc->rh, batch);
    298298        }
    299         ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
    300         if (!ohci_batch)
    301                 return ENOMEM;
    302 
    303         const int err = ohci_transfer_batch_prepare(ohci_batch);
    304         if (err)
    305                 return err;
    306299
    307300        endpoint_t *ep = batch->ep;
    308301        ohci_endpoint_t * const ohci_ep = ohci_endpoint_get(ep);
    309 
    310         /* creating local reference */
    311         endpoint_add_ref(ep);
    312 
    313         fibril_mutex_lock(&ep->guard);
    314         endpoint_activate_locked(ep, batch);
     302        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
     303
     304        int err;
     305        if ((err = ohci_transfer_batch_prepare(ohci_batch)))
     306                return err;
     307
     308        fibril_mutex_lock(&hc->guard);
     309        if ((err = endpoint_activate_locked(ep, batch))) {
     310                fibril_mutex_unlock(&hc->guard);
     311                return err;
     312        }
     313
    315314        ohci_transfer_batch_commit(ohci_batch);
    316         fibril_mutex_unlock(&ep->guard);
     315        list_append(&ohci_ep->pending_link, &hc->pending_endpoints);
     316        fibril_mutex_unlock(&hc->guard);
    317317
    318318        /* Control and bulk schedules need a kick to start working */
     
    328328                break;
    329329        }
    330 
    331         fibril_mutex_lock(&hc->guard);
    332         list_append(&ohci_ep->pending_link, &hc->pending_endpoints);
    333         fibril_mutex_unlock(&hc->guard);
    334330
    335331        return EOK;
     
    369365                                = list_get_instance(current, ohci_endpoint_t, pending_link);
    370366
    371                         fibril_mutex_lock(&ep->base.guard);
    372367                        ohci_transfer_batch_t *batch
    373368                                = ohci_transfer_batch_get(ep->base.active_batch);
     
    377372                                endpoint_deactivate_locked(&ep->base);
    378373                                list_remove(current);
    379                                 endpoint_del_ref(&ep->base);
    380374                                hc_reset_toggles(&batch->base, &ohci_ep_toggle_reset);
    381375                                usb_transfer_batch_finish(&batch->base);
    382376                        }
    383                         fibril_mutex_unlock(&ep->base.guard);
    384377                }
    385378                fibril_mutex_unlock(&hc->guard);
Note: See TracChangeset for help on using the changeset viewer.