diff options
author | Michael Brown <mcb30@ipxe.org> | 2020-11-29 10:55:14 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2020-11-29 11:25:40 +0000 |
commit | 6e01b74a8ac6a3c3c6806ae286df033f71962f9a (patch) | |
tree | e5281b29e916093266f5fce323938284faf5e287 /src/core | |
parent | a8442750e6059335f1f7f5ce8b2fb803a6953789 (diff) | |
download | ipxe-6e01b74a8ac6a3c3c6806ae286df033f71962f9a.zip ipxe-6e01b74a8ac6a3c3c6806ae286df033f71962f9a.tar.gz ipxe-6e01b74a8ac6a3c3c6806ae286df033f71962f9a.tar.bz2 |
[dma] Provide dma_umalloc() for allocating large DMA-coherent buffers
Some devices (e.g. xHCI USB host controllers) may require the use of
large areas of host memory for private use by the device. These
allocations cannot be satisfied from iPXE's limited heap space, and so
are currently allocated using umalloc() which will allocate external
system memory (and alter the system memory map as needed).
Provide dma_umalloc() to provide such allocations as part of the DMA
API, since there is otherwise no way to guarantee that the allocated
regions are usable for coherent DMA.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/dma.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/core/dma.c b/src/core/dma.c index e5fa3f3..5d68682 100644 --- a/src/core/dma.c +++ b/src/core/dma.c @@ -44,6 +44,8 @@ PROVIDE_DMAAPI_INLINE ( flat, dma_map ); PROVIDE_DMAAPI_INLINE ( flat, dma_unmap ); PROVIDE_DMAAPI_INLINE ( flat, dma_alloc ); PROVIDE_DMAAPI_INLINE ( flat, dma_free ); +PROVIDE_DMAAPI_INLINE ( flat, dma_umalloc ); +PROVIDE_DMAAPI_INLINE ( flat, dma_ufree ); PROVIDE_DMAAPI_INLINE ( flat, dma_set_mask ); PROVIDE_DMAAPI_INLINE ( flat, dma_phys ); @@ -120,6 +122,41 @@ static void dma_op_free ( struct dma_mapping *map, void *addr, size_t len ) { } /** + * Allocate and map DMA-coherent buffer from external (user) memory + * + * @v dma DMA device + * @v map DMA mapping to fill in + * @v len Length of buffer + * @v align Physical alignment + * @ret addr Buffer address, or NULL on error + */ +static userptr_t dma_op_umalloc ( struct dma_device *dma, + struct dma_mapping *map, + size_t len, size_t align ) { + struct dma_operations *op = dma->op; + + if ( ! op ) + return UNULL; + return op->umalloc ( dma, map, len, align ); +} + +/** + * Unmap and free DMA-coherent buffer from external (user) memory + * + * @v map DMA mapping + * @v addr Buffer address + * @v len Length of buffer + */ +static void dma_op_ufree ( struct dma_mapping *map, userptr_t addr, + size_t len ) { + struct dma_device *dma = map->dma; + + assert ( dma != NULL ); + assert ( dma->op != NULL ); + dma->op->ufree ( dma, map, addr, len ); +} + +/** * Set addressable space mask * * @v dma DMA device @@ -136,5 +173,7 @@ PROVIDE_DMAAPI ( op, dma_map, dma_op_map ); PROVIDE_DMAAPI ( op, dma_unmap, dma_op_unmap ); PROVIDE_DMAAPI ( op, dma_alloc, dma_op_alloc ); PROVIDE_DMAAPI ( op, dma_free, dma_op_free ); +PROVIDE_DMAAPI ( op, dma_umalloc, dma_op_umalloc ); +PROVIDE_DMAAPI ( op, dma_ufree, dma_op_ufree ); PROVIDE_DMAAPI ( op, dma_set_mask, dma_op_set_mask ); PROVIDE_DMAAPI_INLINE ( op, dma_phys ); |