Changeset 35c37fc in mainline for uspace/drv/bus/usb/ehci/ehci_batch.c


Ignore:
Timestamp:
2018-01-05T20:15: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:
9e5b162
Parents:
b60944b
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-05 16:11:04)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-05 20:15:08)
Message:

ehci: refactor to dma_buffers

One big hidden thing was refactored - now TDs are allocated in one
buffer together with setup and data buffers themselves. This reduces the
number of allocated pages per transfer to minimum.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/ehci_batch.c

    rb60944b r35c37fc  
    4242#include <usb/usb.h>
    4343#include <usb/debug.h>
    44 #include <usb/host/utils/malloc32.h>
    4544
    4645#include "ehci_batch.h"
     
    6261{
    6362        assert(ehci_batch);
    64         if (ehci_batch->tds) {
    65                 for (size_t i = 0; i < ehci_batch->td_count; ++i) {
    66                         free32(ehci_batch->tds[i]);
    67                 }
    68                 free(ehci_batch->tds);
    69         }
    70         free32(ehci_batch->device_buffer);
     63        dma_buffer_free(&ehci_batch->dma_buffer);
    7164        free(ehci_batch);
    7265        usb_log_debug2("Batch(%p): disposed", ehci_batch);
     
    112105        const size_t size = ehci_batch->base.buffer_size;
    113106
    114         /* Mix setup stage and data together, we have enough space */
    115         if (size + setup_size > 0) {
    116                 /* Use one buffer for setup and data stage */
    117                 ehci_batch->device_buffer = malloc32(size + setup_size);
    118                 if (!ehci_batch->device_buffer) {
     107        /* Add TD left over by the previous transfer */
     108        ehci_batch->qh = ehci_endpoint_get(ehci_batch->base.ep)->qh;
     109
     110        /* Determine number of TDs needed */
     111        ehci_batch->td_count = (size + EHCI_TD_MAX_TRANSFER - 1)
     112                / EHCI_TD_MAX_TRANSFER;
     113
     114        /* Control transfer need Setup and Status stage */
     115        if (ehci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL) {
     116                ehci_batch->td_count += 2;
     117        }
     118
     119        const size_t tds_size = ehci_batch->td_count * sizeof(td_t);
     120
     121        /* Mix setup stage, data and TDs together, we have enough space */
     122        if (size + setup_size + tds_size > 0) {
     123                if (dma_buffer_alloc(&ehci_batch->dma_buffer, tds_size + setup_size + size)) {
    119124                        usb_log_error("Batch %p: Failed to allocate device "
    120125                            "buffer", ehci_batch);
    121126                        return ENOMEM;
    122127                }
     128                /* Clean TDs */
     129                ehci_batch->tds = ehci_batch->dma_buffer.virt;
     130                memset(ehci_batch->tds, 0, tds_size);
    123131                /* Copy setup data */
    124                 memcpy(ehci_batch->device_buffer, ehci_batch->base.setup.buffer,
    125                     setup_size);
     132                ehci_batch->setup_buffer = ehci_batch->dma_buffer.virt + tds_size;
     133                memcpy(ehci_batch->setup_buffer, ehci_batch->base.setup.buffer, setup_size);
    126134                /* Copy generic data */
     135                ehci_batch->data_buffer = ehci_batch->setup_buffer + setup_size;
    127136                if (ehci_batch->base.dir != USB_DIRECTION_IN)
    128                         memcpy(ehci_batch->device_buffer + setup_size,
    129                             ehci_batch->base.buffer, ehci_batch->base.buffer_size);
    130         }
    131 
    132         /* Add TD left over by the previous transfer */
    133         ehci_batch->qh = ehci_endpoint_get(ehci_batch->base.ep)->qh;
    134 
    135         /* Determine number of TDs needed */
    136         ehci_batch->td_count = (size + EHCI_TD_MAX_TRANSFER - 1)
    137                 / EHCI_TD_MAX_TRANSFER;
    138 
    139         /* Control transfer need Setup and Status stage */
    140         if (ehci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL) {
    141                 ehci_batch->td_count += 2;
    142         }
    143 
    144         ehci_batch->tds = calloc(ehci_batch->td_count, sizeof(td_t*));
    145         if (!ehci_batch->tds) {
    146                 usb_log_error("Batch %p: Failed to allocate EHCI transfer "
    147                     "descriptors.", ehci_batch);
    148                 return ENOMEM;
    149         }
    150 
    151         for (unsigned i = 0; i < ehci_batch->td_count; ++i) {
    152                 ehci_batch->tds[i] = malloc32(sizeof(td_t));
    153                 if (!ehci_batch->tds[i]) {
    154                         usb_log_error("Batch %p: Failed to allocate TD %d.",
    155                             ehci_batch, i);
    156                         return ENOMEM;
    157                 }
    158                 memset(ehci_batch->tds[i], 0, sizeof(td_t));
     137                        memcpy(ehci_batch->data_buffer,
     138                            ehci_batch->base.buffer,
     139                            ehci_batch->base.buffer_size);
    159140        }
    160141
     
    203184        /* Check all TDs */
    204185        for (size_t i = 0; i < ehci_batch->td_count; ++i) {
    205                 assert(ehci_batch->tds[i] != NULL);
    206186                usb_log_debug("Batch %p: TD %zu: %08x:%08x:%08x.",
    207187                    ehci_batch, i,
    208                     ehci_batch->tds[i]->status, ehci_batch->tds[i]->next,
    209                     ehci_batch->tds[i]->alternate);
    210 
    211                 ehci_batch->base.error = td_error(ehci_batch->tds[i]);
     188                    ehci_batch->tds[i].status, ehci_batch->tds[i].next,
     189                    ehci_batch->tds[i].alternate);
     190
     191                ehci_batch->base.error = td_error(&ehci_batch->tds[i]);
    212192                if (ehci_batch->base.error == EOK) {
    213193                        /* If the TD got all its data through, it will report
     
    224204                         */
    225205                        ehci_batch->base.transfered_size
    226                             -= td_remain_size(ehci_batch->tds[i]);
     206                            -= td_remain_size(&ehci_batch->tds[i]);
    227207                } else {
    228208                        usb_log_debug("Batch %p found error TD(%zu):%08x (%d).",
    229209                            ehci_batch, i,
    230                             ehci_batch->tds[i]->status,
     210                            ehci_batch->tds[i].status,
    231211                            ehci_batch->base.error);
    232212                        /* Clear possible ED HALT */
     
    238218        assert(ehci_batch->base.transfered_size <= ehci_batch->base.buffer_size);
    239219
    240         const size_t setup_size = (ehci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)
    241                 ? USB_SETUP_PACKET_SIZE
    242                 : 0;
    243 
    244220        if (ehci_batch->base.dir == USB_DIRECTION_IN)
    245221                memcpy(ehci_batch->base.buffer,
    246                     ehci_batch->device_buffer + setup_size,
     222                    ehci_batch->data_buffer,
    247223                    ehci_batch->base.transfered_size);
    248224
     
    263239{
    264240        assert(ehci_batch);
    265         qh_set_next_td(ehci_batch->qh, ehci_batch->tds[0]);
     241        qh_set_next_td(ehci_batch->qh, dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[0]));
    266242}
    267243
     
    281257        assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT);
    282258
    283         usb_log_debug2("Batch %p: Control QH(%"PRIxn"): "
     259        usb_log_debug2("Batch %p: Control QH(%p): "
    284260            "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch,
    285             addr_to_phys(ehci_batch->qh),
     261            ehci_batch->qh,
    286262            ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap,
    287263            ehci_batch->qh->status, ehci_batch->qh->current,
     
    293269
    294270        int toggle = 0;
    295         const char* buffer = ehci_batch->device_buffer;
    296271        const usb_direction_t data_dir = dir;
    297272        const usb_direction_t status_dir = reverse_dir[dir];
    298273
    299274        /* Setup stage */
    300         td_init(ehci_batch->tds[0], ehci_batch->tds[1], USB_DIRECTION_BOTH,
    301             buffer, USB_SETUP_PACKET_SIZE, toggle, false);
     275        td_init(&ehci_batch->tds[0],
     276            dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[1]),
     277            dma_buffer_phys(&ehci_batch->dma_buffer, ehci_batch->setup_buffer),
     278            USB_DIRECTION_BOTH, USB_SETUP_PACKET_SIZE, toggle, false);
    302279        usb_log_debug2("Batch %p: Created CONTROL SETUP TD(%"PRIxn"): "
    303280            "%08x:%08x:%08x", ehci_batch,
    304             addr_to_phys(ehci_batch->tds[0]),
    305             ehci_batch->tds[0]->status, ehci_batch->tds[0]->next,
    306             ehci_batch->tds[0]->alternate);
    307         buffer += USB_SETUP_PACKET_SIZE;
     281            dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[0]),
     282            ehci_batch->tds[0].status, ehci_batch->tds[0].next,
     283            ehci_batch->tds[0].alternate);
    308284
    309285        /* Data stage */
    310         size_t td_current = 1;
     286        unsigned td_current = 1;
    311287        size_t remain_size = ehci_batch->base.buffer_size;
     288        uintptr_t buffer = dma_buffer_phys(&ehci_batch->dma_buffer, ehci_batch->data_buffer);
    312289        while (remain_size > 0) {
    313                 const size_t transfer_size =
    314                     min(remain_size, EHCI_TD_MAX_TRANSFER);
     290                const size_t transfer_size = min(remain_size, EHCI_TD_MAX_TRANSFER);
    315291                toggle = 1 - toggle;
    316292
    317                 td_init(ehci_batch->tds[td_current],
    318                     ehci_batch->tds[td_current + 1], data_dir, buffer,
    319                     transfer_size, toggle, false);
     293                td_init(&ehci_batch->tds[td_current],
     294                    dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current + 1]),
     295                    buffer, data_dir, transfer_size, toggle, false);
    320296                usb_log_debug2("Batch %p: Created CONTROL DATA TD(%"PRIxn"): "
    321297                    "%08x:%08x:%08x", ehci_batch,
    322                     addr_to_phys(ehci_batch->tds[td_current]),
    323                     ehci_batch->tds[td_current]->status,
    324                     ehci_batch->tds[td_current]->next,
    325                     ehci_batch->tds[td_current]->alternate);
     298                    dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current]),
     299                    ehci_batch->tds[td_current].status,
     300                    ehci_batch->tds[td_current].next,
     301                    ehci_batch->tds[td_current].alternate);
    326302
    327303                buffer += transfer_size;
     
    333309        /* Status stage */
    334310        assert(td_current == ehci_batch->td_count - 1);
    335         td_init(ehci_batch->tds[td_current], NULL, status_dir, NULL, 0, 1, true);
    336         usb_log_debug2("Batch %p: Created CONTROL STATUS TD(%"PRIxn"): "
    337             "%08x:%08x:%08x", ehci_batch,
    338             addr_to_phys(ehci_batch->tds[td_current]),
    339             ehci_batch->tds[td_current]->status,
    340             ehci_batch->tds[td_current]->next,
    341             ehci_batch->tds[td_current]->alternate);
     311        td_init(&ehci_batch->tds[td_current], 0, 0, status_dir, 0, 1, true);
     312        usb_log_debug2("Batch %p: Created CONTROL STATUS TD %d(%"PRIxn"): "
     313            "%08x:%08x:%08x", ehci_batch, td_current,
     314            dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current]),
     315            ehci_batch->tds[td_current].status,
     316            ehci_batch->tds[td_current].next,
     317            ehci_batch->tds[td_current].alternate);
    342318}
    343319
     
    354330        assert(ehci_batch);
    355331
    356         usb_log_debug2("Batch %p: Data QH(%"PRIxn"): "
     332        usb_log_debug2("Batch %p: Data QH(%p): "
    357333            "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch,
    358             addr_to_phys(ehci_batch->qh),
     334            ehci_batch->qh,
    359335            ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap,
    360336            ehci_batch->qh->status, ehci_batch->qh->current,
     
    363339        size_t td_current = 0;
    364340        size_t remain_size = ehci_batch->base.buffer_size;
    365         char *buffer = ehci_batch->device_buffer;
     341        uintptr_t buffer = dma_buffer_phys(&ehci_batch->dma_buffer, ehci_batch->data_buffer);
    366342        while (remain_size > 0) {
    367343                const size_t transfer_size = remain_size > EHCI_TD_MAX_TRANSFER
     
    369345
    370346                const bool last = (remain_size == transfer_size);
    371                 td_init(
    372                     ehci_batch->tds[td_current],
    373                     last ? NULL : ehci_batch->tds[td_current + 1],
    374                     ehci_batch->base.dir, buffer, transfer_size, -1, last);
     347                td_init(&ehci_batch->tds[td_current],
     348                    last ? 0 : dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current + 1]),
     349                    buffer, ehci_batch->base.dir, transfer_size, -1, last);
    375350
    376351                usb_log_debug2("Batch %p: DATA TD(%"PRIxn": %08x:%08x:%08x",
    377352                    ehci_batch,
    378                     addr_to_phys(ehci_batch->tds[td_current]),
    379                     ehci_batch->tds[td_current]->status,
    380                     ehci_batch->tds[td_current]->next,
    381                     ehci_batch->tds[td_current]->alternate);
     353                    dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current]),
     354                    ehci_batch->tds[td_current].status,
     355                    ehci_batch->tds[td_current].next,
     356                    ehci_batch->tds[td_current].alternate);
    382357
    383358                buffer += transfer_size;
Note: See TracChangeset for help on using the changeset viewer.