Changeset 998773d in mainline for uspace/drv/bus/usb/xhci/trb_ring.c
- Timestamp:
- 2018-01-22T14:27:24Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- effbef3
- Parents:
- db51a6a6
- git-author:
- Ondřej Hlavatý <aearsis@…> (2018-01-22 14:11:42)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2018-01-22 14:27:24)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/trb_ring.c
rdb51a6a6 r998773d 37 37 #include "trb_ring.h" 38 38 39 #define SEGMENT_HEADER_SIZE (sizeof(link_t) + sizeof(uintptr_t)) 40 41 /** 42 * Number of TRBs in a segment (with our header). 43 */ 44 #define SEGMENT_TRB_COUNT ((PAGE_SIZE - SEGMENT_HEADER_SIZE) / sizeof(xhci_trb_t)) 39 /** 40 * A structure representing a segment of a TRB ring. 41 */ 42 43 #define SEGMENT_FOOTER_SIZE (sizeof(link_t) + sizeof(uintptr_t)) 44 45 #define SEGMENT_TRB_COUNT ((PAGE_SIZE - SEGMENT_FOOTER_SIZE) / sizeof(xhci_trb_t)) 46 #define SEGMENT_TRB_USEFUL_COUNT (SEGMENT_TRB_COUNT - 1) 45 47 46 48 struct trb_segment { … … 51 53 } __attribute__((aligned(PAGE_SIZE))); 52 54 55 static_assert(sizeof(trb_segment_t) == PAGE_SIZE); 56 53 57 54 58 /** … … 66 70 { 67 71 return segment_begin(segment) + SEGMENT_TRB_COUNT; 72 } 73 74 /** 75 * Return a first segment of a list of segments. 76 */ 77 static inline trb_segment_t *get_first_segment(list_t *segments) 78 { 79 return list_get_instance(list_first(segments), trb_segment_t, segments_link); 80 68 81 } 69 82 … … 97 110 /** 98 111 * Initializes the ring with one segment. 99 */ 100 int xhci_trb_ring_init(xhci_trb_ring_t *ring) 101 { 102 struct trb_segment *segment; 112 * 113 * @param[in] initial_size A number of free slots on the ring, 0 leaves the 114 * choice on a reasonable default (one page-sized segment). 115 */ 116 int xhci_trb_ring_init(xhci_trb_ring_t *ring, size_t initial_size) 117 { 103 118 int err; 119 if (initial_size == 0) 120 initial_size = SEGMENT_TRB_USEFUL_COUNT; 104 121 105 122 list_initialize(&ring->segments); 106 107 if ((err = trb_segment_alloc(&segment)) != EOK) 108 return err; 109 110 list_append(&segment->segments_link, &ring->segments); 111 ring->segment_count = 1; 112 123 size_t segment_count = (initial_size + SEGMENT_TRB_USEFUL_COUNT - 1) 124 / SEGMENT_TRB_USEFUL_COUNT; 125 126 for (size_t i = 0; i < segment_count; ++i) { 127 struct trb_segment *segment; 128 if ((err = trb_segment_alloc(&segment)) != EOK) 129 return err; 130 131 list_append(&segment->segments_link, &ring->segments); 132 ring->segment_count = i + 1; 133 } 134 135 trb_segment_t * const segment = get_first_segment(&ring->segments); 113 136 xhci_trb_t *last = segment_end(segment) - 1; 114 137 xhci_trb_link_fill(last, segment->phys); … … 284 307 /** 285 308 * Initializes an event ring. 286 */ 287 int xhci_event_ring_init(xhci_event_ring_t *ring) 288 { 289 struct trb_segment *segment; 309 * 310 * @param[in] initial_size A number of free slots on the ring, 0 leaves the 311 * choice on a reasonable default (one page-sized segment). 312 */ 313 int xhci_event_ring_init(xhci_event_ring_t *ring, size_t initial_size) 314 { 290 315 int err; 316 if (initial_size == 0) 317 initial_size = SEGMENT_TRB_COUNT; 291 318 292 319 list_initialize(&ring->segments); 293 320 294 if ((err = trb_segment_alloc(&segment)) != EOK) 295 return err; 296 297 list_append(&segment->segments_link, &ring->segments); 298 ring->segment_count = 1; 299 321 size_t segment_count = (initial_size + SEGMENT_TRB_COUNT - 1) / SEGMENT_TRB_COUNT; 322 size_t erst_size = segment_count * sizeof(xhci_erst_entry_t); 323 324 if (dma_buffer_alloc(&ring->erst, erst_size)) { 325 xhci_event_ring_fini(ring); 326 return ENOMEM; 327 } 328 329 xhci_erst_entry_t *erst = ring->erst.virt; 330 memset(erst, 0, erst_size); 331 332 for (size_t i = 0; i < segment_count; i++) { 333 trb_segment_t *segment; 334 if ((err = trb_segment_alloc(&segment)) != EOK) { 335 xhci_event_ring_fini(ring); 336 return err; 337 } 338 339 list_append(&segment->segments_link, &ring->segments); 340 ring->segment_count = i + 1; 341 xhci_fill_erst_entry(&erst[i], segment->phys, SEGMENT_TRB_COUNT); 342 } 343 344 trb_segment_t * const segment = get_first_segment(&ring->segments); 300 345 ring->dequeue_segment = segment; 301 346 ring->dequeue_trb = segment_begin(segment); 302 347 ring->dequeue_ptr = segment->phys; 303 304 if (dma_buffer_alloc(&ring->erst, PAGE_SIZE)) {305 xhci_event_ring_fini(ring);306 return ENOMEM;307 }308 xhci_erst_entry_t *erst = ring->erst.virt;309 310 memset(erst, 0, PAGE_SIZE);311 xhci_fill_erst_entry(&erst[0], segment->phys, SEGMENT_TRB_COUNT);312 313 348 ring->ccs = 1; 314 349 … … 316 351 317 352 usb_log_debug("Initialized event ring."); 318 319 353 return EOK; 320 354 } … … 324 358 list_foreach_safe(ring->segments, cur, next) { 325 359 trb_segment_t *segment = list_get_instance(cur, trb_segment_t, segments_link); 326 dmamem_unmap_anonymous(segment);360 trb_segment_free(segment); 327 361 } 328 362
Note:
See TracChangeset
for help on using the changeset viewer.