Changeset 708d8fcd in mainline for uspace/drv/bus/usb/xhci/endpoint.c


Ignore:
Timestamp:
2018-01-10T00:46:29Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f92f6b1
Parents:
4793023
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-09 19:26:55)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-10 00:46:29)
Message:

xhci: rewritten isochronous transfers

There was a fundamental problem with relying on hardware to send
RING_OVERRUN/UNDERRUN events, which QEMU (and possibly others) do not
send. That resulted in not knowing if the transfer is still on schedule,
and having to ring the doorbell every time. That is not feasible,
because then the transfer can be more frequent than it should be.
Furthermore, it ignored the fact that isochronous TRBs are to be
scheduled not too late, but also not too soon (see 4.11.2.5 of the xHCI
spec).

Now, scheduling the TRBs to hardware is called feeding, and can be
delayed by setting a timer. Ring overruns/underruns are detected also at
the end of handling an event.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/xhci/endpoint.c

    r4793023 r708d8fcd  
    8484         */
    8585        if (dev->speed >= USB_SPEED_HIGH || ep->transfer_type != USB_TRANSFER_INTERRUPT) {
    86                 xhci_ep->interval = desc->endpoint.poll_interval;
     86                xhci_ep->interval = 1 << (xhci_ep->interval - 1);
    8787        }
    8888
     
    9292        }
    9393
    94         if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    95                 xhci_ep->isoch->max_size = desc->companion.bytes_per_interval
    96                         ? desc->companion.bytes_per_interval
    97                         : ep->max_transfer_size;
    98                 /* Technically there could be superspeed plus too. */
    99 
    100                 /* Allocate and setup isochronous-specific structures. */
    101                 xhci_ep->isoch->enqueue = 0;
    102                 xhci_ep->isoch->dequeue = 0;
    103                 xhci_ep->isoch->started = false;
    104 
    105                 fibril_mutex_initialize(&xhci_ep->isoch->guard);
    106                 fibril_condvar_initialize(&xhci_ep->isoch->avail);
    107         }
     94        if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS)
     95                isoch_init(xhci_ep, desc);
    10896
    10997        if ((rc = alloc_transfer_ds(xhci_ep)))
     
    272260}
    273261
    274 /** TODO document this
    275  */
    276 static int xhci_isoch_alloc_transfers(xhci_endpoint_t *xhci_ep) {
    277         int i = 0;
    278         int err = EOK;
    279         while (i < XHCI_ISOCH_BUFFER_COUNT) {
    280                 xhci_isoch_transfer_t *transfer = &xhci_ep->isoch->transfers[i];
    281                 if (dma_buffer_alloc(&transfer->data, xhci_ep->isoch->max_size)) {
    282                         err = ENOMEM;
    283                         break;
    284                 }
    285                 transfer->size = 0;
    286                 ++i;
    287         }
    288 
    289         if (err) {
    290                 --i;
    291                 while(i >= 0) {
    292                         dma_buffer_free(&xhci_ep->isoch->transfers[i].data);
    293                         --i;
    294                 }
    295         }
    296 
    297         return err;
    298 }
    299 
    300262/** Allocate transfer data structures for XHCI endpoint.
    301263 * @param[in] xhci_ep XHCI endpoint to allocate data structures for.
     
    316278
    317279        if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    318                 if ((err = xhci_isoch_alloc_transfers(xhci_ep))) {
     280                if ((err = isoch_alloc_transfers(xhci_ep))) {
    319281                        xhci_trb_ring_fini(&xhci_ep->ring);
    320282                        return err;
     
    427389        XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue);
    428390        XHCI_EP_DCS_SET(*ctx, 1);
    429         XHCI_EP_INTERVAL_SET(*ctx, fnzb32(ep->interval) % 32 - 1);
     391        XHCI_EP_INTERVAL_SET(*ctx, fnzb32(ep->interval) % 32);
    430392
    431393        XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch->max_size & 0xFFFF);
     
    446408        XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue);
    447409        XHCI_EP_DCS_SET(*ctx, 1);
    448         XHCI_EP_INTERVAL_SET(*ctx, fnzb32(ep->interval) % 32 - 1);
     410        XHCI_EP_INTERVAL_SET(*ctx, fnzb32(ep->interval) % 32);
    449411        // TODO: max ESIT payload
    450412}
Note: See TracChangeset for help on using the changeset viewer.