Changeset 2c0564c in mainline


Ignore:
Timestamp:
2018-01-18T14:40:20Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
05770666
Parents:
2bff2cc2
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-18 14:04:07)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-18 14:40:20)
Message:

xhci: handle potentially blocking events in separate fibril

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

Legend:

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

    r2bff2cc2 r2c0564c  
    248248}
    249249
     250static int event_worker(void *arg);
     251
    250252/**
    251253 * Initialize structures kept in allocated memory.
     
    271273                goto err_cmd;
    272274
    273         return EOK;
    274 
     275        fid_t fid = fibril_create(&event_worker, hc);
     276        if (!fid)
     277                goto err_bus;
     278
     279        // TODO: completion_reset
     280        hc->event_fibril_completion.active = true;
     281        fibril_mutex_initialize(&hc->event_fibril_completion.guard);
     282        fibril_condvar_initialize(&hc->event_fibril_completion.cv);
     283
     284        xhci_sw_ring_init(&hc->sw_ring, PAGE_SIZE / sizeof(xhci_trb_t));
     285
     286        fibril_add_ready(fid);
     287
     288        return EOK;
     289
     290err_bus:
     291        xhci_bus_fini(&hc->bus);
    275292err_cmd:
    276293        xhci_fini_commands(hc);
     
    537554typedef int (*event_handler) (xhci_hc_t *, xhci_trb_t *trb);
    538555
     556/**
     557 * These events are handled by separate event handling fibril.
     558 */
    539559static event_handler event_handlers [] = {
    540         [XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT] = &xhci_handle_command_completion,
    541560        [XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT] = &handle_port_status_change_event,
    542561        [XHCI_TRB_TYPE_TRANSFER_EVENT] = &xhci_handle_transfer_event,
     562};
     563
     564/**
     565 * These events are handled directly in the interrupt handler, thus they must
     566 * not block waiting for another interrupt.
     567 */
     568static event_handler event_handlers_fast [] = {
     569        [XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT] = &xhci_handle_command_completion,
    543570        [XHCI_TRB_TYPE_MFINDEX_WRAP_EVENT] = &xhci_handle_mfindex_wrap_event,
    544571};
    545572
    546 static int hc_handle_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_interrupter_regs_t *intr)
    547 {
    548         unsigned type = TRB_TYPE(*trb);
    549         if (type >= ARRAY_SIZE(event_handlers) || !event_handlers[type])
    550                 return ENOTSUP;
    551 
    552         return event_handlers[type](hc, trb);
     573static int hc_handle_event(xhci_hc_t *hc, xhci_trb_t *trb)
     574{
     575        const unsigned type = TRB_TYPE(*trb);
     576
     577        if (type <= ARRAY_SIZE(event_handlers_fast) && event_handlers_fast[type])
     578                return event_handlers_fast[type](hc, trb);
     579
     580        if (type <= ARRAY_SIZE(event_handlers) && event_handlers[type])
     581                return xhci_sw_ring_enqueue(&hc->sw_ring, trb);
     582
     583        return ENOTSUP;
     584}
     585
     586static int event_worker(void *arg)
     587{
     588        int err;
     589        xhci_trb_t trb;
     590        xhci_hc_t * const hc = arg;
     591        assert(hc);
     592
     593        while (xhci_sw_ring_dequeue(&hc->sw_ring, &trb) != EINTR) {
     594                const unsigned type = TRB_TYPE(trb);
     595
     596                if ((err = event_handlers[type](hc, &trb)))
     597                        usb_log_error("Failed to handle event: %s", str_error(err));
     598        }
     599
     600        // TODO: completion_complete
     601        fibril_mutex_lock(&hc->event_fibril_completion.guard);
     602        hc->event_fibril_completion.active = false;
     603        fibril_condvar_wait(&hc->event_fibril_completion.cv, &hc->event_fibril_completion.guard);
     604        fibril_mutex_unlock(&hc->event_fibril_completion.guard);
     605
     606        return EOK;
    553607}
    554608
     
    571625
    572626        while ((err = xhci_event_ring_dequeue(event_ring, &trb)) != ENOENT) {
    573                 if ((err = hc_handle_event(hc, &trb, intr)) != EOK) {
    574                         usb_log_error("Failed to handle event: %s", str_error(err));
     627                if ((err = hc_handle_event(hc, &trb)) != EOK) {
     628                        usb_log_error("Failed to handle event in interrupt: %s", str_error(err));
    575629                }
    576630
     
    634688void hc_fini(xhci_hc_t *hc)
    635689{
     690        xhci_sw_ring_stop(&hc->sw_ring);
     691
     692        // TODO: completion_wait
     693        fibril_mutex_lock(&hc->event_fibril_completion.guard);
     694        while (hc->event_fibril_completion.active)
     695                fibril_condvar_wait(&hc->event_fibril_completion.cv, &hc->event_fibril_completion.guard);
     696        fibril_mutex_unlock(&hc->event_fibril_completion.guard);
     697        xhci_sw_ring_fini(&hc->sw_ring);
     698
    636699        xhci_bus_fini(&hc->bus);
    637700        xhci_event_ring_fini(&hc->event_ring);
  • uspace/drv/bus/usb/xhci/hc.h

    r2bff2cc2 r2c0564c  
    7575        xhci_cmd_ring_t cr;
    7676
     77        /* Buffer for events */
     78        xhci_sw_ring_t sw_ring;
     79
     80        struct {
     81                fibril_mutex_t guard;
     82                fibril_condvar_t cv;
     83                bool active;
     84        } event_fibril_completion;
     85
    7786        /* Root hub emulation */
    7887        xhci_rh_t rh;
Note: See TracChangeset for help on using the changeset viewer.