Ignore:
Timestamp:
2018-02-12T10:11:47Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5fe3f954
Parents:
2f762a7
git-author:
Ondřej Hlavatý <aearsis@…> (2018-02-05 03:28:50)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-02-12 10:11:47)
Message:

usb: rethinking DMA buffers

File:
1 edited

Legend:

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

    r2f762a7 r1d758fc  
    3737 * shared through IPC).
    3838 *
    39  * Note that although allocated memory is always page-aligned, the buffer itself
    40  * may be only a part of it, justifying the existence of page-alignment and
    41  * page-crossing flags.
     39 * Currently, it is possible to allocate either completely contiguous buffers
     40 * (with dma_map_anonymous) or arbitrary memory (with as_area_create). Shall the
     41 * kernel be updated, this is a subject of major optimization of memory usage.
     42 * The other way to do it without the kernel is building an userspace IO vector
     43 * in a similar way how QEMU does it.
    4244 *
    43  * Also, currently the buffers that are allocated are always contiguous and
    44  * page-aligned, regardless of whether the policy requires it. We blindly
    45  * believe this fact in dma_buffer_phys, which will yield wrong results if the
    46  * buffer is not contiguous.
     45 * The structures themselves are defined in usbhc_iface, because they need to be
     46 * passed through IPC.
    4747 */
    4848#ifndef LIB_USB_DMA_BUFFER
    4949#define LIB_USB_DMA_BUFFER
    5050
     51#include <as.h>
     52#include <bitops.h>
     53#include <errno.h>
    5154#include <stdint.h>
    5255#include <stdlib.h>
    5356#include <usbhc_iface.h>
    54 #include <errno.h>
    5557
    56 #define DMA_POLICY_4GiB         (1<<0)  /**< Must use only 32-bit addresses */
    57 #define DMA_POLICY_PAGE_ALIGNED (1<<1)  /**< The first pointer must be page-aligned */
    58 #define DMA_POLICY_CONTIGUOUS   (1<<2)  /**< Pages must follow each other physically */
    59 #define DMA_POLICY_NOT_CROSSING (1<<3)  /**< Buffer must not cross page boundary. (Implies buffer is no larger than page).  */
     58/**
     59 * The DMA policy describes properties of the buffer. It is used in two
     60 * different contexts. Either it represents requirements, which shall be
     61 * satisfied to avoid copying the buffer to a more strict one. Or, it is the
     62 * actual property of the buffer, which can be more strict than requested. It
     63 * always holds that more bits set means more restrictive policy, and that by
     64 * computing a bitwise OR one gets the restriction that holds for both.
     65 *
     66 * The high bits of a DMA policy represent a physical contiguity. If bit i is
     67 * set, it means that chunks of a size 2^(i+1) are contiguous in memory. It
     68 * shall never happen that bit i > j is set when j is not.
     69 *
     70 * The previous applies for i >= PAGE_WIDTH. Lower bits are used as bit flags.
     71 */
     72#define DMA_POLICY_FLAGS_MASK           (PAGE_SIZE - 1)
     73#define DMA_POLICY_CHUNK_SIZE_MASK      (~DMA_POLICY_FLAGS_MASK)
    6074
    61 #define DMA_POLICY_STRICT       (-1U)
    62 #define DMA_POLICY_DEFAULT      DMA_POLICY_STRICT
     75#define DMA_POLICY_4GiB (1<<0)          /**< Must use only 32-bit addresses */
    6376
    64 typedef struct dma_buffer {
    65         void *virt;
    66         uintptr_t phys;
    67 } dma_buffer_t;
     77#define DMA_POLICY_STRICT               (-1UL)
     78#define DMA_POLICY_DEFAULT              DMA_POLICY_STRICT
     79
     80extern dma_policy_t dma_policy_create(unsigned, size_t);
     81
     82/**
     83 * Get mask which defines bits of offset in chunk.
     84 */
     85static inline size_t dma_policy_chunk_mask(const dma_policy_t policy)
     86{
     87        return policy | DMA_POLICY_FLAGS_MASK;
     88}
    6889
    6990extern errno_t dma_buffer_alloc(dma_buffer_t *db, size_t size);
    7091extern errno_t dma_buffer_alloc_policy(dma_buffer_t *, size_t, dma_policy_t);
    7192extern void dma_buffer_free(dma_buffer_t *);
    72 extern uintptr_t dma_buffer_phys(const dma_buffer_t *, void *);
    7393
    74 extern bool dma_buffer_check_policy(const void *, size_t, const dma_policy_t);
     94extern uintptr_t dma_buffer_phys(const dma_buffer_t *, const void *);
     95
     96static inline uintptr_t dma_buffer_phys_base(const dma_buffer_t *db)
     97{
     98        return dma_buffer_phys(db, db->virt);
     99}
    75100
    76101extern errno_t dma_buffer_lock(dma_buffer_t *, void *, size_t);
    77102extern void dma_buffer_unlock(dma_buffer_t *, size_t);
    78103
    79 static inline int dma_buffer_is_set(dma_buffer_t *db)
     104extern void dma_buffer_acquire(dma_buffer_t *);
     105extern void dma_buffer_release(dma_buffer_t *);
     106
     107static inline bool dma_buffer_is_set(const dma_buffer_t *db)
    80108{
    81109        return !!db->virt;
Note: See TracChangeset for help on using the changeset viewer.