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

Changeset 3e6ff9a in mainline


Ignore:
Timestamp:
2018-02-01T14:28:41Z (4 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial
Children:
e67c50a
Parents:
77ded647
Message:

usb: dma_buffer check policy function

Location:
uspace/lib/usb
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/include/usb/dma_buffer.h

    r77ded647 r3e6ff9a  
    3232 * @brief USB host controller library: DMA buffer helpers
    3333 *
    34  * Simplifies usage of bounce buffers.
     34 * Simplifies usage of bounce buffers
    3535 *
    3636 * Currently the minimum size allocated is a page, which is wasteful. Could be
     
    4646
    4747typedef const struct dma_policy {
    48         bool use64;             /**< Whether to use more than initial 4GiB of memory */
    49         size_t alignment;       /**< What alignment is needed. At most PAGE_SIZE. */
     48        unsigned flags;
     49
     50#define DMA_POLICY_F_4GiB       (1<<0)  /**< Must use only 32-bit addresses */
     51#define DMA_POLICY_F_CONTIGUOUS (1<<1)  /**< Pages must follow each other physically */
    5052} dma_policy_t;
    5153
     
    5658
    5759extern int dma_buffer_alloc(dma_buffer_t *db, size_t size);
    58 extern int dma_buffer_alloc_policy(dma_buffer_t *, size_t, const dma_policy_t *);
     60extern int dma_buffer_alloc_policy(dma_buffer_t *, size_t, dma_policy_t *);
    5961extern void dma_buffer_free(dma_buffer_t *);
    6062extern uintptr_t dma_buffer_phys(const dma_buffer_t *, void *);
     63
     64extern bool dma_buffer_check_policy(const void *, size_t, dma_policy_t *);
    6165
    6266static inline int dma_buffer_is_set(dma_buffer_t *db)
  • uspace/lib/usb/src/dma_buffer.c

    r77ded647 r3e6ff9a  
    4040
    4141const dma_policy_t dma_policy_default = {
    42         .use64 = false,
    43         .alignment = PAGE_SIZE,
     42        .flags = DMA_POLICY_F_4GiB | DMA_POLICY_F_CONTIGUOUS,
    4443};
    4544
     
    4746 * The routine of allocating a DMA buffer. Inlined to force optimization for the
    4847 * default policy.
     48 *
     49 * FIXME: We ignore the non-presence of contiguous flag, for now.
    4950 */
    5051static inline int dma_buffer_alloc_internal(dma_buffer_t *db,
     
    5354        assert(db);
    5455
    55         if (policy->alignment > PAGE_SIZE)
    56                 return EINVAL;
     56        const size_t real_size = ALIGN_UP(size, PAGE_SIZE);
     57        const bool need_4gib = !!(policy->flags & DMA_POLICY_F_4GiB);
    5758
    58         const size_t aligned_size = ALIGN_UP(size, policy->alignment);
    59         const size_t real_size = ALIGN_UP(aligned_size, PAGE_SIZE);
    60         const uintptr_t flags = policy->use64 ? 0 : DMAMEM_4GiB;
     59        const uintptr_t flags = need_4gib ? DMAMEM_4GiB : 0;
    6160
    6261        uintptr_t phys;
     
    127126
    128127/**
     128 * Check whether a memory area is compatible with a policy.
     129 *
     130 * Useful to skip copying, if the buffer is already ready to be given to
     131 * hardware.
     132 */
     133bool dma_buffer_check_policy(const void *buffer, size_t size, dma_policy_t *policy)
     134{
     135        /* Buffer must be always page aligned */
     136        if (((uintptr_t) buffer) % PAGE_SIZE)
     137                goto violated;
     138
     139        const bool check_4gib = !!(policy->flags & DMA_POLICY_F_4GiB);
     140        const bool check_contiguous = !!(policy->flags & DMA_POLICY_F_CONTIGUOUS);
     141
     142        /*
     143         * For these conditions, we need to walk through pages and check
     144         * physical address of each one
     145         */
     146        if (check_contiguous || check_4gib) {
     147                const void * virt = buffer;
     148                uintptr_t phys;
     149
     150                /* Get the mapping of the first page */
     151                if (as_get_physical_mapping(virt, &phys))
     152                        goto error;
     153
     154                /* First page can already break 4GiB condition */
     155                if (check_4gib && (phys & DMAMEM_4GiB) != 0)
     156                        goto violated;
     157
     158                while (size <= PAGE_SIZE) {
     159                        /* Move to the next page */
     160                        virt += PAGE_SIZE;
     161                        size -= PAGE_SIZE;
     162
     163                        uintptr_t last_phys = phys;
     164                        if (as_get_physical_mapping(virt, &phys))
     165                                goto error;
     166
     167                        if (check_contiguous && (phys - last_phys) != PAGE_SIZE)
     168                                goto violated;
     169
     170                        if (check_4gib && (phys & DMAMEM_4GiB) != 0)
     171                                goto violated;
     172                }
     173        }
     174
     175        /* All checks passed */
     176        return true;
     177
     178violated:
     179error:
     180        return false;
     181}
     182
     183/**
    129184 * @}
    130185 */
Note: See TracChangeset for help on using the changeset viewer.