Changeset 2f762a7 in mainline


Ignore:
Timestamp:
2018-02-11T17:18:17Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1d758fc
Parents:
d345ce2
git-author:
Ondřej Hlavatý <aearsis@…> (2018-02-05 03:52:09)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-02-11 17:18:17)
Message:

usbhost: allow the driver to bounce later

Location:
uspace/lib/usbhost
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    rd345ce2 r2f762a7  
    7070        } setup;
    7171
    72         /** DMA buffer with enforced policy */
    73         dma_buffer_t dma_buffer;
     72        /**
     73         * In case a bounce buffer is allocated, the original buffer must to be
     74         * stored to be filled after the IN transaction is finished.
     75         */
     76        char *buffer;
    7477        /** Size of memory buffer */
    7578        size_t buffer_size;
    7679
    77         /**
    78          * In case the DMA buffer is allocated, the original buffer must to be
    79          * stored to be filled after the IN transaction is finished.
    80          */
    81         char *original_buffer;
     80        /** DMA buffer with enforced policy */
     81        dma_buffer_t dma_buffer;
     82        bool is_bounced;
    8283
    8384        /** Indicates success/failure of the communication */
     
    114115void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);
    115116
     117errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *);
    116118/** Buffer preparation */
    117119errno_t usb_transfer_batch_prepare_buffer(usb_transfer_batch_t *, char *);
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    rd345ce2 r2f762a7  
    103103}
    104104
     105errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *batch)
     106{
     107        assert(batch);
     108        assert(!batch->is_bounced);
     109
     110        if (dma_buffer_is_set(&batch->dma_buffer))
     111                dma_buffer_unlock(&batch->dma_buffer, batch->buffer_size);
     112
     113        usb_log_debug("Batch(%p): Buffer cannot be used directly, "
     114            "falling back to bounce buffer!", batch);
     115
     116        const errno_t err = dma_buffer_alloc_policy(&batch->dma_buffer,
     117            batch->buffer_size, batch->ep->transfer_buffer_policy);
     118        if (err)
     119                return err;
     120
     121        /* Copy the data out */
     122        if (batch->dir == USB_DIRECTION_OUT)
     123                memcpy(batch->dma_buffer.virt, batch->buffer, batch->buffer_size);
     124
     125        batch->is_bounced = true;
     126        return err;
     127}
     128
    105129/**
    106130 * Prepare a DMA buffer according to endpoint policy.
     
    109133 * buffer is created.
    110134 */
    111 errno_t usb_transfer_batch_prepare_buffer(
    112     usb_transfer_batch_t *batch, char *buf)
     135errno_t usb_transfer_batch_prepare_buffer(usb_transfer_batch_t *batch, char *buf)
    113136{
    114         const dma_policy_t policy = batch->ep->transfer_buffer_policy;
    115 
    116137        /* Empty transfers do not need a buffer */
    117138        if (batch->buffer_size == 0)
    118139                return EOK;
    119140
    120         if (dma_buffer_check_policy(buf, batch->buffer_size, policy)) {
    121                 /* Mark this case with invalid address */
    122                 batch->original_buffer = NULL;
     141        batch->buffer = buf;
    123142
    124                 /* Fill the buffer with virtual address and lock it for DMA */
    125                 return dma_buffer_lock(&batch->dma_buffer, buf, batch->buffer_size);
    126         }
    127         else {
    128                 usb_log_debug("Batch(%p): Buffer cannot be used directly, "
    129                     "falling back to bounce buffer!", batch);
    130                 const errno_t err = dma_buffer_alloc_policy(&batch->dma_buffer,
    131                     batch->buffer_size, policy);
     143        const dma_policy_t policy = batch->ep->transfer_buffer_policy;
    132144
    133                 /* Copy the data out */
    134                 if (!err && batch->dir == USB_DIRECTION_OUT)
    135                         memcpy(batch->dma_buffer.virt, buf, batch->buffer_size);
     145        /*
     146         * We don't have enough information (yet, WIP) to know if we can skip
     147         * the bounce, so check the conditions carefully.
     148         */
     149        if (!dma_buffer_check_policy(buf, batch->buffer_size, policy))
     150                return usb_transfer_batch_bounce(batch);
    136151
    137                 /* Store the buffer to store the data back before finishing */
    138                 batch->original_buffer = buf;
    139 
    140                 return err;
    141         }
     152        /* Fill the buffer with virtual address and lock it for DMA */
     153        return dma_buffer_lock(&batch->dma_buffer, buf, batch->buffer_size);
    142154}
    143155
     
    156168
    157169        if (batch->error == EOK && batch->buffer_size > 0) {
    158                 if (batch->original_buffer == NULL) {
     170                if (!batch->is_bounced) {
    159171                        /* Unlock the buffer for DMA */
    160172                        dma_buffer_unlock(&batch->dma_buffer,
     
    164176                        /* We we're forced to use bounce buffer, copy it back */
    165177                        if (batch->dir == USB_DIRECTION_IN)
    166                                 memcpy(batch->original_buffer,
     178                                memcpy(batch->buffer,
    167179                                    batch->dma_buffer.virt,
    168180                                    batch->transferred_size);
Note: See TracChangeset for help on using the changeset viewer.