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

Changeset 548c123 in mainline


Ignore:
Timestamp:
2017-09-29T21:46:08Z (4 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master
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.

Location:
uspace/drv/bus/usb/xhci
Files:
5 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
  • uspace/drv/bus/usb/xhci/commands.h

    rab5a0830 r548c123  
    3939#include <adt/list.h>
    4040#include <stdbool.h>
     41#include "hw_struct/trb.h"
    4142
    4243typedef struct xhci_hc xhci_hc_t;
    43 typedef struct xhci_trb xhci_trb_t;
    4444typedef struct xhci_input_ctx xhci_input_ctx_t;
    4545
     
    4747        link_t link;
    4848
    49         xhci_trb_t *trb;
     49        xhci_trb_t trb;
     50        uintptr_t trb_phys;
    5051        xhci_input_ctx_t *ictx;
    5152        uint32_t slot_id;
  • uspace/drv/bus/usb/xhci/hw_struct/trb.h

    rab5a0830 r548c123  
    138138    dst->status = src->status;
    139139    dst->control = src->control;
     140}
     141
     142static inline void xhci_trb_clean(xhci_trb_t *trb)
     143{
     144        memset(trb, 0, sizeof(*trb));
    140145}
    141146
  • uspace/drv/bus/usb/xhci/trb_ring.c

    rab5a0830 r548c123  
    164164 *
    165165 * @param td the first TRB of TD
     166 * @param phys returns address of the first TRB enqueued
    166167 * @return EOK on success,
    167168 *         EAGAIN when the ring is too full to fit all TRBs (temporary)
    168169 */
    169 int xhci_trb_ring_enqueue(xhci_trb_ring_t *ring, xhci_trb_t *td)
     170int xhci_trb_ring_enqueue(xhci_trb_ring_t *ring, xhci_trb_t *td, uintptr_t *phys)
    170171{
    171172        xhci_trb_t * const saved_enqueue_trb = ring->enqueue_trb;
    172173        trb_segment_t * const saved_enqueue_segment = ring->enqueue_segment;
     174        if (phys)
     175                *phys = NULL;
    173176
    174177        /*
     
    189192        ring->enqueue_segment = saved_enqueue_segment;
    190193        ring->enqueue_trb = saved_enqueue_trb;
     194        if (phys)
     195                *phys = trb_ring_enqueue_phys(ring);
    191196
    192197        /*
  • uspace/drv/bus/usb/xhci/trb_ring.h

    rab5a0830 r548c123  
    7272int xhci_trb_ring_init(xhci_trb_ring_t *, xhci_hc_t *);
    7373int xhci_trb_ring_fini(xhci_trb_ring_t *);
    74 int xhci_trb_ring_enqueue(xhci_trb_ring_t *, xhci_trb_t *);
     74int xhci_trb_ring_enqueue(xhci_trb_ring_t *, xhci_trb_t *, uintptr_t *);
    7575
    7676/**
Note: See TracChangeset for help on using the changeset viewer.