Changeset 548c123 in mainline for uspace/drv/bus/usb/xhci/commands.c


Ignore:
Timestamp:
2017-09-29T21:46:08Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
cc9ac7c
Parents:
ab5a0830
Message:

xhci commands: embed TRB into the command structure

Previously, a pointer into the TRB ring itself was contained. That could cause
problems, because the ring does not care and can move/deallocate segments, or
overwrite TRBs inside. To solve the original issue, xhci_trb_ring_enqueue can
now fill physical address of the TRB enqueued.

Also, this eliminates the need to track ownage of TRB.

File:
1 edited

Legend:

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

    rab5a0830 r548c123  
    5555 */
    5656#define TRB_SET_DEQUEUE_PTR(trb, dptr) (trb).parameter |= host2xhci(64, (dptr))
    57 #define TRB_SET_ICTX(trb, phys) (trb).parameter |= host2xhci(32, phys_addr & (~0xF))
     57#define TRB_SET_ICTX(trb, phys) (trb).parameter |= host2xhci(64, phys_addr & (~0xF))
    5858
    5959#define TRB_GET_CODE(trb) XHCI_DWORD_EXTRACT((trb).status, 31, 24)
     
    108108         */
    109109        cmd->has_owner = true;
    110         cmd->owns_trb = false;
    111110
    112111        return cmd;
     
    119118        if (cmd->ictx)
    120119                free32(cmd->ictx);
    121         if (cmd->owns_trb && cmd->trb)
    122                 free32(cmd->trb);
    123120
    124121        free32(cmd);
     
    128125{
    129126        link_t *cmd_link = list_first(&hc->commands);
     127
     128
     129        usb_log_debug2("Searching TRB %lu...", phys);
    130130
    131131        while (cmd_link != NULL) {
    132132                xhci_cmd_t *cmd = list_get_instance(cmd_link, xhci_cmd_t, link);
    133133
    134                 if (addr_to_phys(cmd->trb) == phys)
     134                if (cmd->trb_phys == phys)
    135135                        break;
    136136
     
    155155}
    156156
    157 static inline int enqueue_trb(xhci_hc_t *hc, xhci_trb_t *trb,
    158                               unsigned doorbell, unsigned target)
    159 {
    160         assert(hc);
    161         assert(trb);
    162 
    163         xhci_trb_ring_enqueue(&hc->command_ring, trb);
     157static inline int enqueue_command(xhci_hc_t *hc, xhci_cmd_t *cmd, unsigned doorbell, unsigned target)
     158{
     159        assert(hc);
     160        assert(cmd);
     161
     162        list_append(&cmd->link, &hc->commands);
     163
     164        xhci_trb_ring_enqueue(&hc->command_ring, &cmd->trb, &cmd->trb_phys);
    164165        ring_doorbell(hc, doorbell, target);
    165166
    166         xhci_dump_trb(trb);
    167         usb_log_debug2("HC(%p): Sent TRB", hc);
     167        usb_log_debug2("HC(%p): Sent command:", hc);
     168        xhci_dump_trb(&cmd->trb);
    168169
    169170        return EOK;
    170 }
    171 
    172 static inline void add_cmd(xhci_hc_t *hc, xhci_cmd_t *cmd)
    173 {
    174         assert(cmd);
    175 
    176         list_append(&cmd->link, &hc->commands);
    177         cmd->trb = hc->command_ring.enqueue_trb;
    178171}
    179172
     
    263256        assert(hc);
    264257
    265         xhci_trb_t trb;
    266         memset(&trb, 0, sizeof(trb));
    267 
    268         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_NO_OP_CMD);
    269 
    270         add_cmd(hc, cmd);
    271 
    272         return enqueue_trb(hc, &trb, 0, 0);
     258        xhci_trb_clean(&cmd->trb);
     259
     260        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_NO_OP_CMD);
     261
     262        return enqueue_command(hc, cmd, 0, 0);
    273263}
    274264
     
    277267        assert(hc);
    278268
    279         xhci_trb_t trb;
    280         memset(&trb, 0, sizeof(trb));
    281 
    282         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_ENABLE_SLOT_CMD);
    283         trb.control |= host2xhci(32, XHCI_REG_RD(hc->xecp, XHCI_EC_SP_SLOT_TYPE) << 16);
    284 
    285         add_cmd(hc, cmd);
    286 
    287         return enqueue_trb(hc, &trb, 0, 0);
     269        xhci_trb_clean(&cmd->trb);
     270
     271        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_ENABLE_SLOT_CMD);
     272        cmd->trb.control |= host2xhci(32, XHCI_REG_RD(hc->xecp, XHCI_EC_SP_SLOT_TYPE) << 16);
     273
     274        return enqueue_command(hc, cmd, 0, 0);
    288275}
    289276
     
    293280        assert(cmd);
    294281
    295         xhci_trb_t trb;
    296         memset(&trb, 0, sizeof(trb));
    297 
    298         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_DISABLE_SLOT_CMD);
    299         TRB_SET_SLOT(trb, cmd->slot_id);
    300 
    301         add_cmd(hc, cmd);
    302 
    303         return enqueue_trb(hc, &trb, 0, 0);
     282        xhci_trb_clean(&cmd->trb);
     283
     284        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_DISABLE_SLOT_CMD);
     285        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     286
     287        return enqueue_command(hc, cmd, 0, 0);
    304288}
    305289
     
    316300         *           other should be ignored at this point (see section 4.6.5).
    317301         */
    318         xhci_trb_t trb;
    319         memset(&trb, 0, sizeof(trb));
     302        xhci_trb_clean(&cmd->trb);
    320303
    321304        uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
    322         TRB_SET_ICTX(trb, phys_addr);
     305        TRB_SET_ICTX(cmd->trb, phys_addr);
    323306
    324307        /**
     
    329312         *       that require their device descriptor to be read before such request.
    330313         */
    331         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD);
    332         TRB_SET_SLOT(trb, cmd->slot_id);
    333 
    334         add_cmd(hc, cmd);
    335 
    336         return enqueue_trb(hc, &trb, 0, 0);
     314        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD);
     315        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     316
     317        return enqueue_command(hc, cmd, 0, 0);
    337318}
    338319
     
    343324        assert(cmd->ictx);
    344325
    345         xhci_trb_t trb;
    346         memset(&trb, 0, sizeof(trb));
     326        xhci_trb_clean(&cmd->trb);
    347327
    348328        uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
    349         TRB_SET_ICTX(trb, phys_addr);
    350 
    351         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD);
    352         TRB_SET_SLOT(trb, cmd->slot_id);
    353 
    354         add_cmd(hc, cmd);
    355 
    356         return enqueue_trb(hc, &trb, 0, 0);
     329        TRB_SET_ICTX(cmd->trb, phys_addr);
     330
     331        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD);
     332        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     333
     334        return enqueue_command(hc, cmd, 0, 0);
    357335}
    358336
     
    369347         *       Refer to sections 6.2.2.3 and 6.3.3.3 for further info.
    370348         */
    371         xhci_trb_t trb;
    372         memset(&trb, 0, sizeof(trb));
     349        xhci_trb_clean(&cmd->trb);
    373350
    374351        uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
    375         TRB_SET_ICTX(trb, phys_addr);
    376 
    377         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD);
    378         TRB_SET_SLOT(trb, cmd->slot_id);
    379 
    380         add_cmd(hc, cmd);
    381 
    382         return enqueue_trb(hc, &trb, 0, 0);
     352        TRB_SET_ICTX(cmd->trb, phys_addr);
     353
     354        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD);
     355        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     356
     357        return enqueue_command(hc, cmd, 0, 0);
    383358}
    384359
     
    392367         *       information about this flag.
    393368         */
    394         xhci_trb_t trb;
    395         memset(&trb, 0, sizeof(trb));
    396 
    397         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_RESET_ENDPOINT_CMD);
    398         TRB_SET_TCS(trb, tcs);
    399         TRB_SET_EP(trb, ep_id);
    400         TRB_SET_SLOT(trb, cmd->slot_id);
    401 
    402         add_cmd(hc, cmd);
    403 
    404         return enqueue_trb(hc, &trb, 0, 0);
     369        xhci_trb_clean(&cmd->trb);
     370
     371        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_RESET_ENDPOINT_CMD);
     372        TRB_SET_TCS(cmd->trb, tcs);
     373        TRB_SET_EP(cmd->trb, ep_id);
     374        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     375
     376        return enqueue_command(hc, cmd, 0, 0);
    405377}
    406378
     
    410382        assert(cmd);
    411383
    412         xhci_trb_t trb;
    413         memset(&trb, 0, sizeof(trb));
    414 
    415         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_STOP_ENDPOINT_CMD);
    416         TRB_SET_EP(trb, ep_id);
    417         TRB_SET_SUSP(trb, susp);
    418         TRB_SET_SLOT(trb, cmd->slot_id);
    419 
    420         add_cmd(hc, cmd);
    421 
    422         return enqueue_trb(hc, &trb, 0, 0);
     384        xhci_trb_clean(&cmd->trb);
     385
     386        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_STOP_ENDPOINT_CMD);
     387        TRB_SET_EP(cmd->trb, ep_id);
     388        TRB_SET_SUSP(cmd->trb, susp);
     389        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     390
     391        return enqueue_command(hc, cmd, 0, 0);
    423392}
    424393
     
    430399        assert(cmd);
    431400
    432         xhci_trb_t trb;
    433         memset(&trb, 0, sizeof(trb));
    434 
    435         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_SET_TR_DEQUEUE_POINTER_CMD);
    436         TRB_SET_EP(trb, ep_id);
    437         TRB_SET_STREAM(trb, stream_id);
    438         TRB_SET_SLOT(trb, cmd->slot_id);
    439         TRB_SET_DEQUEUE_PTR(trb, dequeue_ptr);
     401        xhci_trb_clean(&cmd->trb);
     402
     403        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_SET_TR_DEQUEUE_POINTER_CMD);
     404        TRB_SET_EP(cmd->trb, ep_id);
     405        TRB_SET_STREAM(cmd->trb, stream_id);
     406        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     407        TRB_SET_DEQUEUE_PTR(cmd->trb, dequeue_ptr);
    440408
    441409        /**
     
    443411         */
    444412
    445         add_cmd(hc, cmd);
    446 
    447         return enqueue_trb(hc, &trb, 0, 0);
     413        return enqueue_command(hc, cmd, 0, 0);
    448414}
    449415
     
    453419        assert(cmd);
    454420
    455         xhci_trb_t trb;
    456         memset(&trb, 0, sizeof(trb));
    457 
    458         TRB_SET_TYPE(trb, XHCI_TRB_TYPE_RESET_DEVICE_CMD);
    459         TRB_SET_SLOT(trb, cmd->slot_id);
    460 
    461         add_cmd(hc, cmd);
    462 
    463         return enqueue_trb(hc, &trb, 0, 0);
     421        xhci_trb_clean(&cmd->trb);
     422
     423        TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_RESET_DEVICE_CMD);
     424        TRB_SET_SLOT(cmd->trb, cmd->slot_id);
     425
     426        return enqueue_command(hc, cmd, 0, 0);
    464427}
    465428
     
    475438        uint64_t phys;
    476439        xhci_cmd_t *command;
    477         xhci_trb_t *command_trb;
    478440
    479441        code = TRB_GET_CODE(*trb);
     
    490452        }
    491453
    492         command_trb = command->trb;
    493454        command->status = code;
    494455        command->slot_id = TRB_GET_SLOT(*trb);
    495456
    496         usb_log_debug2("Completed command trb: %s", xhci_trb_str_type(TRB_TYPE(*command_trb)));
    497         if (TRB_TYPE(*command_trb) != XHCI_TRB_TYPE_NO_OP_CMD) {
     457        usb_log_debug2("Completed command trb: %s", xhci_trb_str_type(TRB_TYPE(command->trb)));
     458        if (TRB_TYPE(command->trb) != XHCI_TRB_TYPE_NO_OP_CMD) {
    498459                if (code != XHCI_TRBC_SUCCESS) {
    499460                        report_error(code);
    500                         xhci_dump_trb(command_trb);
     461                        xhci_dump_trb(&command->trb);
    501462                }
    502463        }
    503464
    504         switch (TRB_TYPE(*command_trb)) {
     465        switch (TRB_TYPE(command->trb)) {
    505466        case XHCI_TRB_TYPE_NO_OP_CMD:
    506467                assert(code == XHCI_TRBC_TRB_ERROR);
     
    526487                break;
    527488        default:
    528                 usb_log_debug2("Unsupported command trb: %s", xhci_trb_str_type(TRB_TYPE(*command_trb)));
     489                usb_log_debug2("Unsupported command trb: %s", xhci_trb_str_type(TRB_TYPE(command->trb)));
    529490
    530491                command->completed = true;
     
    536497        if (!command->has_owner) {
    537498                usb_log_debug2("Command has no owner, deallocating.");
    538                 command->trb = NULL; // It was statically allocated.
    539499                xhci_free_command(command);
    540500        } else {
    541501                usb_log_debug2("Command has owner, don't forget to deallocate!");
    542                 /* Copy the trb for later use so that we can free space on the cmd ring. */
    543                 command->trb = malloc32(sizeof(xhci_trb_t));
    544                 xhci_trb_copy(command->trb, command_trb);
    545                 command->owns_trb = true;
    546502        }
    547503
Note: See TracChangeset for help on using the changeset viewer.