Changeset 6455d39 in mainline


Ignore:
Timestamp:
2017-12-14T14:09:31Z (6 years ago)
Author:
Salmelu <salmelu@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
10cd715
Parents:
7d957b2
Message:

Added isochronous locks, over/underrun detection

Location:
uspace/drv/bus/usb/xhci
Files:
3 edited

Legend:

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

    r7d957b2 r6455d39  
    8383                ep->isoch_dequeue = XHCI_ISOCH_BUFFER_COUNT - 1;
    8484                ep->isoch_started = false;
     85
     86                fibril_mutex_initialize(&ep->isoch_guard);
     87                fibril_condvar_initialize(&ep->isoch_avail);
    8588        }
    8689
  • uspace/drv/bus/usb/xhci/endpoint.h

    r7d957b2 r6455d39  
    102102        /** Are isochronous transfers started? */
    103103        bool isoch_started;
     104
     105        /** Protects common buffers. */
     106        fibril_mutex_t isoch_guard;
     107
     108        /** Signals filled buffer. */
     109        fibril_condvar_t isoch_avail;
     110
    104111} xhci_endpoint_t;
    105112
  • uspace/drv/bus/usb/xhci/transfers.c

    r7d957b2 r6455d39  
    280280        xhci_trb_clean(&trb);
    281281
    282         // FIXME add some locks
     282        fibril_mutex_lock(&xhci_ep->isoch_guard);
    283283        xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    284284        while (!isoch_transfer) {
    285                 // FIXME: add condvar sleep;
     285                fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
     286                isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    286287        }
    287288
     
    297298                &isoch_transfer->interrupt_trb_phys);
    298299        if (err) {
     300                fibril_mutex_unlock(&xhci_ep->isoch_guard);
    299301                return err;
    300302        }
     
    306308                const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
    307309                err = hc_ring_doorbell(hc, slot_id, target);
    308                 if (err) {
    309                         return err;
    310                 }
    311310                xhci_ep->isoch_started = true;
     311        }
     312        fibril_mutex_unlock(&xhci_ep->isoch_guard);
     313        if (err) {
     314                return err;
    312315        }
    313316
     
    322325        xhci_device_t *xhci_dev)
    323326{
     327        fibril_mutex_lock(&xhci_ep->isoch_guard);
    324328        /* If not yet started, start the isochronous endpoint transfers - before first read */
    325329        if (!xhci_ep->isoch_started) {
     
    328332                int err = hc_ring_doorbell(hc, slot_id, target);
    329333                if (err) {
     334                        fibril_mutex_unlock(&xhci_ep->isoch_guard);
    330335                        return err;
    331336                }
     
    333338        }
    334339
    335         // FIXME add some locks
    336340        xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    337341        while(!isoch_transfer) {
    338                 // FIXME: add condvar sleep;
     342                fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
     343                isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    339344        }
    340345
     
    364369        int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size,
    365370                &isoch_transfer->interrupt_trb_phys);
     371        fibril_mutex_unlock(&xhci_ep->isoch_guard);
     372
    366373        if (err) {
    367374                return err;
     
    391398
    392399static int handle_isochronous_transfer_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_endpoint_t *ep) {
    393         fibril_mutex_lock(&ep->base.guard);
     400        fibril_mutex_lock(&ep->isoch_guard);
     401
     402        int err = EOK;
     403
     404        const xhci_trb_completion_code_t completion_code = TRB_COMPLETION_CODE(*trb);
     405        switch (completion_code) {
     406                case XHCI_TRBC_RING_OVERRUN:
     407                case XHCI_TRBC_RING_UNDERRUN:
     408                        // TODO: abort the phone; rings are unscheduled by xHC by now
     409                        ep->isoch_started = false;
     410                        err = EIO;
     411                        break;
     412                case XHCI_TRBC_SHORT_PACKET:
     413                        usb_log_debug("Short transfer.");
     414                        /* fallthrough */
     415                case XHCI_TRBC_SUCCESS:
     416                        break;
     417                default:
     418                        usb_log_warning("Transfer not successfull: %u", completion_code);
     419                        err = EIO;
     420        }
    394421
    395422        xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_dequeue(ep);
     
    397424                usb_log_error("Non-matching trb to isochronous transfer, skipping.");
    398425                // FIXME: what to do? probably just kill the whole endpoint
    399                 return ENOENT;
     426                err = ENOENT;
    400427        }
    401428
     
    405432        }
    406433
    407         // TODO: Send notify to waiting fibrils in case they are waiting here
    408 
    409         fibril_mutex_unlock(&ep->base.guard);
    410         return EOK;
     434        fibril_condvar_signal(&ep->isoch_avail);
     435        fibril_mutex_unlock(&ep->isoch_guard);
     436        return err;
    411437}
    412438
Note: See TracChangeset for help on using the changeset viewer.