Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset adb4e683 in mainline


Ignore:
Timestamp:
2017-10-03T15:17:26Z (4 years ago)
Author:
Jaroslav Jindrak <dzejrou@…>
Branches:
lfn, master
Children:
efe9463
Parents:
a1eb7c67
Message:

Refactored the way event handling works, now we fetch all of the event TRBs from the event ring, advance the dequeue pointer and clear EHB and then we handle all of the events.

File:
1 edited

Legend:

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

    ra1eb7c67 radb4e683  
    497497{
    498498        int err;
    499         xhci_trb_t trb;
    500 
    501         err = xhci_event_ring_dequeue(event_ring, &trb);;
     499        size_t last_idx = 0;
     500        size_t size = 16; // TODO: Define a macro, possibly do size += initial_size instead of *= 2.
     501        xhci_trb_t *trbs = malloc32(sizeof(xhci_trb_t) * size);
     502
     503        err = xhci_event_ring_dequeue(event_ring, trbs + last_idx);
    502504
    503505        while (err != ENOENT) {
    504506                if (err == EOK) {
    505507                        usb_log_debug2("Dequeued trb from event ring: %s",
    506                                         xhci_trb_str_type(TRB_TYPE(trb)));
    507 
    508                         hc_handle_event(hc, &trb, intr);
     508                                        xhci_trb_str_type(TRB_TYPE(trbs[last_idx])));
    509509                } else {
     510                        --last_idx; /* If there are valid trbs they should still get handled. */
    510511                        usb_log_warning("Error while accessing event ring: %s", str_error(err));
    511512                        break;
    512513                }
    513514
    514                 err = xhci_event_ring_dequeue(event_ring, &trb);;
    515         }
    516         usb_log_debug2("Event ring processing finished.");
    517 
    518         /* Update the ERDP to make room in the ring */
     515                ++last_idx;
     516                err = xhci_event_ring_dequeue(event_ring, trbs + last_idx);
     517
     518                /* Expand the array if needed. */
     519                if (last_idx >= size) {
     520                        xhci_trb_t *trbs_old = trbs;
     521                        size_t size_old = size;
     522
     523                        size *= 2;
     524                        trbs = malloc32(sizeof(xhci_trb_t) * size);
     525
     526                        for (size_t i = 0; i < size_old; ++i)
     527                                xhci_trb_copy(trbs + i, trbs_old + i);
     528                        free32(trbs_old);
     529                }
     530        }
     531
     532        /* Update the ERDP to make room in the ring. */
    519533        hc->event_ring.dequeue_ptr = host2xhci(64, addr_to_phys(hc->event_ring.dequeue_trb));
    520534        uint64_t erdp = hc->event_ring.dequeue_ptr;
     
    522536        XHCI_REG_WR(intr, XHCI_INTR_ERDP_HI, UPPER32(erdp));
    523537        XHCI_REG_SET(intr, XHCI_INTR_ERDP_EHB, 1);
     538
     539        /**
     540         * After changing the way this function works, second port status change
     541         * would not raise an interrupt because of IE being set to 0. This is
     542         * a temporary hotfix that fixes this issue.
     543         * TODO: Research & properly fix this.
     544         */
     545        XHCI_REG_SET(intr, XHCI_INTR_IE, 1);
     546
     547        /* Handle all of the collected events if possible. */
     548        if (last_idx > 0) {
     549                for (size_t i = 0; i < last_idx; ++i)
     550                        hc_handle_event(hc, trbs + i, intr);
     551                usb_log_debug2("Event ring processing finished.");
     552        } else {
     553                usb_log_warning("No events to be handled!");
     554        }
     555
     556        free32(trbs);
    524557}
    525558
Note: See TracChangeset for help on using the changeset viewer.