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

Changeset 472235a in mainline


Ignore:
Timestamp:
2017-10-03T16:53:47Z (4 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master
Children:
65e079b
Parents:
efe9463
Message:

xhci: refactoring

Revise error paths, refactor some code.

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

Legend:

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

    refe9463 r472235a  
    126126{
    127127        link_t *cmd_link = list_first(&hc->commands);
    128 
    129 
    130         usb_log_debug2("Searching TRB %lu...", phys);
    131128
    132129        while (cmd_link != NULL) {
  • uspace/drv/bus/usb/xhci/hc.c

    refe9463 r472235a  
    8484                                 */
    8585
    86                                 unsigned ports_from = XHCI_REG_RD(ec, XHCI_EC_SP_CP_OFF);
    87                                 unsigned ports_to = ports_from
     86                                unsigned ports_from = XHCI_REG_RD(ec, XHCI_EC_SP_CP_OFF);
     87                                unsigned ports_to = ports_from
    8888                                        + XHCI_REG_RD(ec, XHCI_EC_SP_CP_COUNT) - 1;
    8989
     
    468468}
    469469
    470 static void hc_handle_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_interrupter_regs_t *intr)
    471 {
    472         usb_log_debug2("TRB event encountered.");
    473         switch (TRB_TYPE(*trb)) {
    474         case XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT:
    475                 xhci_handle_command_completion(hc, trb);
    476                 break;
    477         case XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT:
    478                 /**
    479                  * TODO: This is a very crude hotfix, I'm not sure if
    480                  *       we can do this one level above in the event handling
    481                  *       loop (incase the xHC adds more events while we process events).
    482                  */
    483                 hc->event_ring.dequeue_ptr = host2xhci(64, addr_to_phys(hc->event_ring.dequeue_trb));
    484                 uint64_t erdp = hc->event_ring.dequeue_ptr;
    485                 XHCI_REG_WR(intr, XHCI_INTR_ERDP_LO, LOWER32(erdp));
    486                 XHCI_REG_WR(intr, XHCI_INTR_ERDP_HI, UPPER32(erdp));
    487                 XHCI_REG_SET(intr, XHCI_INTR_ERDP_EHB, 1);
    488                 xhci_handle_port_status_change_event(hc, trb);
    489                 break;
    490         default:
    491                 usb_log_debug2("Event type handling not implemented.");
    492                 break;
    493         }
     470typedef int (*event_handler) (xhci_hc_t *, xhci_trb_t *trb);
     471
     472static event_handler event_handlers [] = {
     473        [XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT] = &xhci_handle_command_completion,
     474        [XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT] = &xhci_handle_port_status_change_event,
     475};
     476
     477static int hc_handle_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_interrupter_regs_t *intr)
     478{
     479        unsigned type = TRB_TYPE(*trb);
     480        if (type >= ARRAY_SIZE(event_handlers) || !event_handlers[type])
     481                return ENOTSUP;
     482
     483        return event_handlers[type](hc, trb);
    494484}
    495485
     
    497487{
    498488        int err;
    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);
    504 
    505         while (err != ENOENT) {
    506                 if (err == EOK) {
    507                         usb_log_debug2("Dequeued trb from event ring: %s",
    508                                         xhci_trb_str_type(TRB_TYPE(trbs[last_idx])));
    509                 } else {
    510                         --last_idx; /* If there are valid trbs they should still get handled. */
     489        ssize_t size = 16;
     490        xhci_trb_t *queue = malloc(sizeof(xhci_trb_t) * size);
     491        if (!queue) {
     492                usb_log_error("Not enough memory to run the event ring.");
     493                return;
     494        }
     495
     496        xhci_trb_t *head = queue;
     497
     498        while ((err = xhci_event_ring_dequeue(event_ring, head)) != ENOENT) {
     499                if (err != EOK) {
    511500                        usb_log_warning("Error while accessing event ring: %s", str_error(err));
    512501                        break;
    513502                }
    514503
    515                 ++last_idx;
    516                 err = xhci_event_ring_dequeue(event_ring, trbs + last_idx);
     504                usb_log_debug2("Dequeued trb from event ring: %s", xhci_trb_str_type(TRB_TYPE(*head)));
     505                head++;
    517506
    518507                /* Expand the array if needed. */
    519                 if (last_idx >= size) {
    520                         xhci_trb_t *trbs_old = trbs;
    521                         size_t size_old = size;
    522 
     508                if (head - queue >= size) {
    523509                        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);
     510                        xhci_trb_t *new_queue = realloc(queue, size);
     511                        if (new_queue == NULL)
     512                                break; /* Will process only those TRBs we have memory for. */
     513
     514                        head = new_queue + (head - queue);
    529515                }
    530516        }
    531517
    532518        /* Update the ERDP to make room in the ring. */
     519        usb_log_debug2("Copying from ring finished, updating ERDP.");
    533520        hc->event_ring.dequeue_ptr = host2xhci(64, addr_to_phys(hc->event_ring.dequeue_trb));
    534521        uint64_t erdp = hc->event_ring.dequeue_ptr;
     
    538525
    539526        /* Handle all of the collected events if possible. */
    540         if (last_idx > 0) {
    541                 for (size_t i = 0; i < last_idx; ++i)
    542                         hc_handle_event(hc, trbs + i, intr);
    543                 usb_log_debug2("Event ring processing finished.");
    544         } else {
     527        if (head == queue)
    545528                usb_log_warning("No events to be handled!");
    546         }
    547 
    548         free32(trbs);
     529
     530        for (xhci_trb_t *tail = queue; tail != head; tail++) {
     531                if ((err = hc_handle_event(hc, tail, intr)) != EOK) {
     532                        usb_log_error("Failed to handle event: %s", str_error(err));
     533                }
     534        }
     535
     536        free(queue);
     537        usb_log_debug2("Event ring run finished.");
    549538}
    550539
     
    567556
    568557        if (status & XHCI_REG_MASK(XHCI_OP_EINT)) {
    569                 usb_log_debug2("Event interrupt.");
     558                usb_log_debug2("Event interrupt, running the event ring.");
    570559                hc_run_event_ring(hc, &hc->event_ring, &hc->rt_regs->ir[0]);
    571560                status &= ~XHCI_REG_MASK(XHCI_OP_EINT);
  • uspace/drv/bus/usb/xhci/rh.c

    refe9463 r472235a  
    135135        xhci_cmd_fini(&cmd);
    136136
    137         // TODO: Issue configure endpoint commands (sec 4.3.5).
     137        // TODO: Issue configure endpoint commands (sec 4.3.5).
    138138
    139139        return EOK;
     
    165165                        usb_log_debug("Detected new device on port %u, port speed id %u.", port_id, port_speed);
    166166
    167                         alloc_dev(hc, port_id, 0);
     167                        return alloc_dev(hc, port_id, 0);
    168168                }
    169169                else if (link_state == 5) {
    170170                        /* USB 3 failed to enable. */
    171171                        usb_log_error("USB 3 port couldn't be enabled.");
     172                        return EAGAIN;
    172173                }
    173174                else {
    174175                        usb_log_error("USB 3 port is in invalid state %u.", link_state);
     176                        return EINVAL;
    175177                }
    176178        }
     
    183185                        going around?
    184186                */
    185         }
    186 
    187         return EOK;
     187                return EOK;
     188        }
    188189}
    189190
    190191int xhci_handle_port_status_change_event(xhci_hc_t *hc, xhci_trb_t *trb)
    191192{
     193        int err;
     194
    192195        uint8_t port_id = xhci_get_hub_port(trb);
    193196        usb_log_debug("Port status change event detected for port %u.", port_id);
     
    202205                usb_log_debug2("Detected port reset on port %u, port speed id %u.", port_id, port_speed);
    203206                /** FIXME: only if that port is not yet initialized */
    204                 alloc_dev(hc, port_id, 0);
     207                if ((err = alloc_dev(hc, port_id, 0)) != EOK)
     208                        return err;
    205209        }
    206210
     
    210214
    211215                if (XHCI_REG_RD(regs, XHCI_PORT_CCS) == 1) {
    212                         handle_connected_device(hc, regs, port_id);
     216                        if ((err = handle_connected_device(hc, regs, port_id)) != EOK)
     217                                return err;
    213218                } else {
    214219                        // TODO: Device disconnected
     220                        return ENOTSUP;
    215221                }
    216222        }
Note: See TracChangeset for help on using the changeset viewer.