Changeset cc63815 in mainline for uspace/lib/usb/src/dma_buffer.c


Ignore:
Timestamp:
2018-02-05T00:54: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:
fdc2253b
Parents:
5c69377
git-author:
Ondřej Hlavatý <aearsis@…> (2018-02-02 14:35:14)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-02-05 00:54:08)
Message:

usb dma_buffer: policy is now just a flag field, implement (un)locking

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/dma_buffer.c

    r5c69377 rcc63815  
    3939#include "usb/dma_buffer.h"
    4040
    41 const dma_policy_t dma_policy_default = {
    42         .flags = DMA_POLICY_F_4GiB | DMA_POLICY_F_CONTIGUOUS,
    43 };
    44 
    45 /**
    46  * The routine of allocating a DMA buffer. Inlined to force optimization for the
    47  * default policy.
    48  *
    49  * FIXME: We ignore the non-presence of contiguous flag, for now.
    50  */
    51 static inline int dma_buffer_alloc_internal(dma_buffer_t *db,
    52     size_t size, const dma_policy_t *policy)
     41/**
     42 * Allocate a DMA buffer.
     43 *
     44 * XXX: Currently cannot make much use of missing constraints, as it always
     45 * allocates page-aligned contiguous buffer. We rely on it in dma_buffer_phys.
     46 *
     47 * @param[in] db dma_buffer_t structure to fill
     48 * @param[in] size Size of the required memory space
     49 * @param[in] policy dma_policy_t flags to guide the allocation
     50 * @return Error code.
     51 */
     52errno_t dma_buffer_alloc_policy(dma_buffer_t *db, size_t size, dma_policy_t policy)
    5353{
    5454        assert(db);
    5555
    5656        const size_t real_size = ALIGN_UP(size, PAGE_SIZE);
    57         const bool need_4gib = !!(policy->flags & DMA_POLICY_F_4GiB);
     57        const bool need_4gib = !!(policy & DMA_POLICY_4GiB);
    5858
    5959        const uintptr_t flags = need_4gib ? DMAMEM_4GiB : 0;
     
    6767
    6868        if (ret == EOK) {
     69                /* Access the pages to force mapping */
     70                volatile char *buf = address;
     71                for (size_t i = 0; i < size; i += PAGE_SIZE)
     72                        buf[i] = 0xff;
     73
    6974                db->virt = address;
    7075                db->phys = phys;
     
    7378}
    7479
    75 /**
    76  * Allocate a DMA buffer.
    77  *
    78  * @param[in] db dma_buffer_t structure to fill
    79  * @param[in] size Size of the required memory space
    80  * @param[in] policy dma_policy_t structure to guide
    81  * @return Error code.
    82  */
    83 int dma_buffer_alloc_policy(dma_buffer_t *db, size_t size,
    84     const dma_policy_t *policy)
    85 {
    86         return dma_buffer_alloc_internal(db, size, policy);
    87 }
    8880
    8981/**
     
    9486 * @return Error code.
    9587 */
    96 int dma_buffer_alloc(dma_buffer_t *db, size_t size)
    97 {
    98         return dma_buffer_alloc_internal(db, size, &dma_policy_default);
     88errno_t dma_buffer_alloc(dma_buffer_t *db, size_t size)
     89{
     90        return dma_buffer_alloc_policy(db, size, DMA_POLICY_DEFAULT);
    9991}
    10092
     
    128120 * Check whether a memory area is compatible with a policy.
    129121 *
    130  * Useful to skip copying, if the buffer is already ready to be given to
    131  * hardware.
    132  */
    133 bool 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)
     122 * Useful to skip copying when the buffer is already ready to be given to
     123 * hardware as is.
     124 *
     125 * Note that the "as_get_physical_mapping" fails when the page is not mapped
     126 * yet, and that the caller is responsible for forcing the mapping.
     127 */
     128bool dma_buffer_check_policy(const void *buffer, size_t size, const dma_policy_t policy)
     129{
     130        uintptr_t addr = (uintptr_t) buffer;
     131
     132        const bool check_4gib       = !!(policy & DMA_POLICY_4GiB);
     133        const bool check_crossing   = !!(policy & DMA_POLICY_NOT_CROSSING);
     134        const bool check_alignment  = !!(policy & DMA_POLICY_PAGE_ALIGNED);
     135        const bool check_contiguous = !!(policy & DMA_POLICY_CONTIGUOUS);
     136
     137        /* Check the two conditions that are easy */
     138        if (check_crossing && (addr + size - 1) / PAGE_SIZE != addr / PAGE_SIZE)
    137139                goto violated;
    138140
    139         const bool check_4gib = !!(policy->flags & DMA_POLICY_F_4GiB);
    140         const bool check_contiguous = !!(policy->flags & DMA_POLICY_F_CONTIGUOUS);
     141        if (check_alignment && ((uintptr_t) buffer) % PAGE_SIZE)
     142                goto violated;
    141143
    142144        /*
     
    145147         */
    146148        if (check_contiguous || check_4gib) {
    147                 const void * virt = buffer;
     149                const void *virt = buffer;
    148150                uintptr_t phys;
    149151
     
    156158                        goto violated;
    157159
    158                 while (size <= PAGE_SIZE) {
     160                while (size >= PAGE_SIZE) {
    159161                        /* Move to the next page */
    160162                        virt += PAGE_SIZE;
     
    182184
    183185/**
     186 * Lock an arbitrary buffer for DMA operations, creating a DMA buffer.
     187 *
     188 * FIXME: To handle page-unaligned buffers, we need to calculate the base
     189 *        address and lock the whole first page. But as the operation is not yet
     190 *        implemented in the kernel, it doesn't matter.
     191 */
     192errno_t dma_buffer_lock(dma_buffer_t *db, void *virt, size_t size)
     193{
     194        db->virt = virt;
     195        return dmamem_map(db->virt, size, 0, 0, &db->phys);
     196}
     197
     198/**
     199 * Unlock a buffer for DMA operations.
     200 */
     201void dma_buffer_unlock(dma_buffer_t *db, size_t size)
     202{
     203        if (db->virt) {
     204                dmamem_unmap(db->virt, size);
     205                db->virt = NULL;
     206                db->phys = 0;
     207        }
     208}
     209
     210/**
    184211 * @}
    185212 */
Note: See TracChangeset for help on using the changeset viewer.