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

Changeset 3f6c94ed in mainline


Ignore:
Timestamp:
2017-10-27T11:33:13Z (3 years ago)
Author:
Michal Staruch <salmelu@…>
Branches:
master
Children:
7010861
Parents:
5bc8250
Message:

Stubs for stream initialization

Streams should not be initialized always because the drivers may not support it.
Moved streams initialization to on-demand function.
Needs more work, but allows usbmast to initialize again and not crash.

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

Legend:

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

    r5bc8250 r3f6c94ed  
    6666}
    6767
    68 static bool endpoint_uses_streams(xhci_endpoint_t *xhci_ep)
    69 {
    70         return xhci_ep->base.transfer_type == USB_TRANSFER_BULK
    71             && xhci_ep->max_streams;
    72 }
    73 
    74 static size_t primary_stream_ctx_array_size(xhci_endpoint_t *xhci_ep)
    75 {
    76         if (!endpoint_uses_streams(xhci_ep))
     68static int xhci_endpoint_type(xhci_endpoint_t *ep)
     69{
     70        const bool in = ep->base.direction == USB_DIRECTION_IN;
     71
     72        switch (ep->base.transfer_type) {
     73        case USB_TRANSFER_CONTROL:
     74                return EP_TYPE_CONTROL;
     75
     76        case USB_TRANSFER_ISOCHRONOUS:
     77                return in ? EP_TYPE_ISOCH_IN
     78                          : EP_TYPE_ISOCH_OUT;
     79
     80        case USB_TRANSFER_BULK:
     81                return in ? EP_TYPE_BULK_IN
     82                          : EP_TYPE_BULK_OUT;
     83
     84        case USB_TRANSFER_INTERRUPT:
     85                return in ? EP_TYPE_INTERRUPT_IN
     86                          : EP_TYPE_INTERRUPT_OUT;
     87        }
     88
     89        return EP_TYPE_INVALID;
     90}
     91
     92static bool endpoint_using_streams(xhci_endpoint_t *xhci_ep)
     93{
     94        return xhci_ep->primary_stream_ctx_array != NULL;
     95}
     96
     97static size_t primary_stream_ctx_array_max_size(xhci_endpoint_t *xhci_ep)
     98{
     99        if (!xhci_ep->max_streams)
    77100                return 0;
    78101
     
    81104}
    82105
    83 static bool primary_stream_ctx_has_secondary_array(xhci_stream_ctx_t *primary_ctx) {
    84         /* Section 6.2.4.1, SCT values */
    85         return XHCI_STREAM_SCT(*primary_ctx) >= 2;
    86 }
    87 
    88 static size_t secondary_stream_ctx_array_size(xhci_stream_ctx_t *primary_ctx) {
    89         if (XHCI_STREAM_SCT(*primary_ctx) < 2) return 0;
    90         return 2 << XHCI_STREAM_SCT(*primary_ctx);
    91 }
    92 
    93 int xhci_endpoint_alloc_transfer_ds(xhci_endpoint_t *xhci_ep)
    94 {
    95         if (endpoint_uses_streams(xhci_ep)) {
    96                 /* Set up primary stream context array if needed. */
    97                 const size_t size = primary_stream_ctx_array_size(xhci_ep);
    98                 usb_log_debug2("Allocating primary stream context array of size %lu for endpoint " XHCI_EP_FMT,
    99                     size, XHCI_EP_ARGS(*xhci_ep));
    100 
    101                 xhci_ep->primary_stream_ctx_array = malloc32(size * sizeof(xhci_stream_ctx_t));
     106// static bool primary_stream_ctx_has_secondary_array(xhci_stream_ctx_t *primary_ctx) {
     107//      /* Section 6.2.4.1, SCT values */
     108//      return XHCI_STREAM_SCT(*primary_ctx) >= 2;
     109// }
     110//
     111// static size_t secondary_stream_ctx_array_size(xhci_stream_ctx_t *primary_ctx) {
     112//      if (XHCI_STREAM_SCT(*primary_ctx) < 2) return 0;
     113//      return 2 << XHCI_STREAM_SCT(*primary_ctx);
     114// }
     115
     116static void initialize_primary_streams(xhci_hc_t *hc, xhci_endpoint_t *xhci_ep, unsigned count) {
     117        for (size_t index = 0; index < count; ++index) {
     118                // Create trb ring for every primary stream
     119                // Store it somewhere
     120                // Set the dequeue pointer in stream context structure
     121
     122                // Set to linear stream array
     123                XHCI_STREAM_SCT_SET(xhci_ep->primary_stream_ctx_array[index], 1);
     124        }
     125}
     126
     127static void setup_stream_context(xhci_endpoint_t *xhci_ep, xhci_ep_ctx_t *ctx, unsigned pstreams) {
     128        XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(xhci_ep));
     129        XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, xhci_ep->base.max_packet_size);
     130        XHCI_EP_MAX_BURST_SIZE_SET(*ctx, xhci_ep->max_burst);
     131        XHCI_EP_ERROR_COUNT_SET(*ctx, 3);
     132
     133        XHCI_EP_MAX_P_STREAMS_SET(*ctx, pstreams);
     134        XHCI_EP_TR_DPTR_SET(*ctx, addr_to_phys(xhci_ep->primary_stream_ctx_array));
     135        // TODO: set HID?
     136        XHCI_EP_LSA_SET(*ctx, 1);
     137}
     138
     139int xhci_endpoint_request_streams(xhci_hc_t *hc, xhci_device_t *dev, xhci_endpoint_t *xhci_ep, unsigned count) {
     140        if (xhci_ep->base.transfer_type != USB_TRANSFER_BULK
     141                || xhci_ep->base.speed != USB_SPEED_SUPER) {
     142                usb_log_error("Streams are only supported by superspeed bulk endpoints.");
     143                return EINVAL;
     144        }
     145
     146        if (!primary_stream_ctx_array_max_size(xhci_ep)) {
     147                usb_log_error("Streams are not supported by endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep));
     148                return EINVAL;
     149        }
     150
     151        uint8_t max_psa_size = 2 << XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PSA_SIZE);
     152        if (count > max_psa_size) {
     153                // We don't support secondary stream arrays yet, so we just give up for this
     154                return ENOTSUP;
     155        }
     156
     157        if (count > (unsigned) (1 << xhci_ep->max_streams)) {
     158                usb_log_error("Endpoint " XHCI_EP_FMT " supports only %u streams.",
     159                        XHCI_EP_ARGS(*xhci_ep), (1 << xhci_ep->max_streams));
     160                return EINVAL;
     161        }
     162
     163        if (count <= 1024) {
     164                usb_log_debug2("Allocating primary stream context array of size %u for endpoint " XHCI_EP_FMT,
     165                        count, XHCI_EP_ARGS(*xhci_ep));
     166                xhci_ep->primary_stream_ctx_array = malloc32(count * sizeof(xhci_stream_ctx_t));
    102167                if (!xhci_ep->primary_stream_ctx_array) {
    103168                        return ENOMEM;
    104169                }
    105170
    106                 memset(xhci_ep->primary_stream_ctx_array, 0, size * sizeof(xhci_stream_ctx_t));
    107         } else {
    108                 usb_log_debug2("Allocating main transfer ring for endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep));
    109 
    110                 xhci_ep->primary_stream_ctx_array = NULL;
    111 
    112                 int err;
    113                 if ((err = xhci_trb_ring_init(&xhci_ep->ring))) {
    114                         return err;
    115                 }
     171                // FIXME: count should be rounded to nearest power of 2 for xHC, workaround for now
     172                count = 1024;
     173                // FIXME: pstreams are "log2(count) - 1"
     174                const size_t pstreams = 9;
     175                xhci_ep->primary_stream_ctx_array_size = count;
     176
     177                memset(xhci_ep->primary_stream_ctx_array, 0, count * sizeof(xhci_stream_ctx_t));
     178                initialize_primary_streams(hc, xhci_ep, count);
     179
     180                xhci_ep_ctx_t ep_ctx;
     181                setup_stream_context(xhci_ep, &ep_ctx, pstreams);
     182                return hc_add_endpoint(hc, dev->slot_id, xhci_endpoint_index(xhci_ep), &ep_ctx);
     183        }
     184        // Complex stuff not supported yet
     185        return ENOTSUP;
     186}
     187
     188int xhci_endpoint_alloc_transfer_ds(xhci_endpoint_t *xhci_ep)
     189{
     190
     191        usb_log_debug2("Allocating main transfer ring for endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep));
     192
     193        xhci_ep->primary_stream_ctx_array = NULL;
     194
     195        int err;
     196        if ((err = xhci_trb_ring_init(&xhci_ep->ring))) {
     197                return err;
    116198        }
    117199
     
    121203int xhci_endpoint_free_transfer_ds(xhci_endpoint_t *xhci_ep)
    122204{
    123         if (endpoint_uses_streams(xhci_ep)) {
     205        if (endpoint_using_streams(xhci_ep)) {
    124206                usb_log_debug2("Freeing primary stream context array for endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep));
    125207
    126208                // maybe check if LSA, then skip?
    127                 for (size_t index = 0; index < primary_stream_ctx_array_size(xhci_ep); ++index) {
    128                         xhci_stream_ctx_t *primary_ctx = xhci_ep->primary_stream_ctx_array + index;
    129                         if (primary_stream_ctx_has_secondary_array(primary_ctx)) {
    130                                 // uintptr_t phys = XHCI_STREAM_DEQ_PTR(*primary_ctx);
    131                                 /* size_t size = */ secondary_stream_ctx_array_size(primary_ctx);
    132                                 // TODO: somehow map the address to virtual and free the secondary array
    133                         }
     209                // for (size_t index = 0; index < primary_stream_ctx_array_size(xhci_ep); ++index) {
     210                //      xhci_stream_ctx_t *primary_ctx = xhci_ep->primary_stream_ctx_array + index;
     211                //      if (primary_stream_ctx_has_secondary_array(primary_ctx)) {
     212                //              // uintptr_t phys = XHCI_STREAM_DEQ_PTR(*primary_ctx);
     213                //              /* size_t size = */ secondary_stream_ctx_array_size(primary_ctx);
     214                //              // TODO: somehow map the address to virtual and free the secondary array
     215                //      }
     216                // }
     217                for (size_t index = 0; index < xhci_ep->primary_stream_ctx_array_size; ++index) {
     218                        // FIXME: Get the trb ring associated with stream [index] and fini it
    134219                }
    135220                free32(xhci_ep->primary_stream_ctx_array);
     
    170255}
    171256
    172 static int xhci_endpoint_type(xhci_endpoint_t *ep)
    173 {
    174         const bool in = ep->base.direction == USB_DIRECTION_IN;
    175 
    176         switch (ep->base.transfer_type) {
    177         case USB_TRANSFER_CONTROL:
    178                 return EP_TYPE_CONTROL;
    179 
    180         case USB_TRANSFER_ISOCHRONOUS:
    181                 return in ? EP_TYPE_ISOCH_IN
    182                           : EP_TYPE_ISOCH_OUT;
    183 
    184         case USB_TRANSFER_BULK:
    185                 return in ? EP_TYPE_BULK_IN
    186                           : EP_TYPE_BULK_OUT;
    187 
    188         case USB_TRANSFER_INTERRUPT:
    189                 return in ? EP_TYPE_INTERRUPT_IN
    190                           : EP_TYPE_INTERRUPT_OUT;
    191         }
    192 
    193         return EP_TYPE_INVALID;
    194 }
    195 
    196257static void setup_control_ep_ctx(xhci_endpoint_t *ep, xhci_ep_ctx_t *ctx)
    197258{
     
    212273        XHCI_EP_ERROR_COUNT_SET(*ctx, 3);
    213274
    214         if (endpoint_uses_streams(ep)) {
    215                 XHCI_EP_MAX_P_STREAMS_SET(*ctx, ep->max_streams);
    216                 XHCI_EP_TR_DPTR_SET(*ctx, addr_to_phys(ep->primary_stream_ctx_array));
    217                 // TODO: set HID
    218                 // TODO: set LSA
    219         } else {
    220                 XHCI_EP_MAX_P_STREAMS_SET(*ctx, 0);
    221                 XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue);
    222                 XHCI_EP_DCS_SET(*ctx, 1);
    223         }
     275        XHCI_EP_MAX_P_STREAMS_SET(*ctx, 0);
     276        XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue);
     277        XHCI_EP_DCS_SET(*ctx, 1);
    224278}
    225279
  • uspace/drv/bus/usb/xhci/endpoint.h

    r5bc8250 r3f6c94ed  
    7777        xhci_stream_ctx_t *primary_stream_ctx_array;
    7878
     79        /** Size of the allocated primary stream context array. */
     80        uint16_t primary_stream_ctx_array_size;
     81
    7982        /** 2-log of maximum number of primary streams (0-16). Not to be used directly. */
    8083        uint8_t max_streams;
     
    129132int xhci_endpoint_free_transfer_ds(xhci_endpoint_t *);
    130133
     134int xhci_endpoint_request_streams(xhci_hc_t *, xhci_device_t *, xhci_endpoint_t *, unsigned);
     135
    131136uint8_t xhci_endpoint_dci(xhci_endpoint_t *);
    132137uint8_t xhci_endpoint_index(xhci_endpoint_t *);
  • uspace/drv/bus/usb/xhci/hw_struct/context.h

    r5bc8250 r3f6c94ed  
    8080#define XHCI_EP_MAX_P_STREAMS_SET(ctx, val) \
    8181        xhci_dword_set_bits(&(ctx).data[0], val, 14, 10)
     82#define XHCI_EP_LSA_SET(ctx, val) \
     83        xhci_dword_set_bits(&(ctx).data[0], val, 15, 15)
    8284#define XHCI_EP_MULT_SET(ctx, val) \
    8385        xhci_dword_set_bits(&(ctx).data[0], val, 9, 8)
     
    164166#define XHCI_STREAM_DEQ_PTR(ctx)   XHCI_QWORD_EXTRACT((ctx).data[0], 63, 4)
    165167#define XHCI_STREAM_EDTLA(ctx)     XHCI_QWORD_EXTRACT((ctx).data[1], 24, 0)
     168
     169#define XHCI_STREAM_SCT_SET(ctx, val) \
     170        xhci_qword_set_bits(&(ctx).data[0], val, 3, 1)
    166171} __attribute__((packed)) xhci_stream_ctx_t;
    167172
Note: See TracChangeset for help on using the changeset viewer.