LinuxKPI: implement dma_{alloc,free}_{noncoherent,attrs}

We use one to implement the other given direction stays unused.

This is needed by an upcoming wifi driver.

MFC after:	3 days
Reviewed by:	dumbbell
Differential Revision: https://reviews.freebsd.org/D58880
This commit is contained in:
Bjoern A. Zeeb committed 2026-09-14 19:06:00 +00:00
1 parent cfb23b01e2
commit c3fa17a6a3
2 files changed
+86

No files matched your search

@@ -108,6 +108,14 @@ void *linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag);
void linuxkpi_dmam_free_coherent(struct device *dev, size_t size,
void *addr, dma_addr_t dma_handle);
void *linuxkpi_dma_alloc_noncoherent(struct device *, size_t, dma_addr_t *,
enum dma_data_direction, gfp_t);
void linuxkpi_dma_free_noncoherent(struct device *, size_t, void *,
dma_addr_t, enum dma_data_direction);
void *linuxkpi_dma_alloc_attrs(struct device *, size_t, dma_addr_t *,
gfp_t, unsigned long);
void linuxkpi_dma_free_attrs(struct device *, size_t, void *,
dma_addr_t, unsigned long);
dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len); /* backward compat */
dma_addr_t lkpi_dma_map_phys(struct device *, vm_paddr_t, size_t,
enum dma_data_direction, unsigned long);
@@ -201,6 +209,34 @@ dmam_free_coherent(struct device *dev, size_t size, void *addr,
linuxkpi_dmam_free_coherent(dev, size, addr, dma_handle);
}
static inline void *
dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
enum dma_data_direction direction, gfp_t gfp)
{
return (linuxkpi_dma_alloc_noncoherent(dev, size, dma_handle, direction, gfp));
}
static inline void
dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, enum dma_data_direction direction)
{
linuxkpi_dma_free_noncoherent(dev, size, vaddr, dma_handle, direction);
}
static inline void *
dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t gfp, unsigned long attrs)
{
return (linuxkpi_dma_alloc_attrs(dev, size, dma_handle, gfp, attrs));
}
static inline void
dma_free_attrs(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, unsigned long attrs)
{
linuxkpi_dma_free_attrs(dev, size, vaddr, dma_handle, attrs);
}
static inline dma_addr_t
dma_map_page_attrs(struct device *dev, struct page *page, size_t offset,
size_t size, enum dma_data_direction direction, unsigned long attrs)
@@ -2016,6 +2016,56 @@ linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_ha
return (dr->mem);
}
void *
linuxkpi_dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
enum dma_data_direction direction, gfp_t gfp)
{
struct linux_dma_priv *priv;
size_t align;
void *mem;
size = PAGE_ALIGN(size);
align = PAGE_SIZE << get_order(size);
mem = kmem_alloc_contig(size, gfp & GFP_NATIVE_MASK, 0, BUS_SPACE_MAXADDR,
align, 0, VM_MEMATTR_DEFAULT);
if (mem == NULL) {
*dma_handle = 0;
return (NULL);
}
priv = dev->dma_priv;
*dma_handle = linux_dma_map_phys_common(dev, vtophys(mem), size, priv->dmat);
if (*dma_handle == 0) {
kmem_free(mem, size);
mem = NULL;
}
return (mem);
}
void
linuxkpi_dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, enum dma_data_direction direction)
{
lkpi_dma_unmap(dev, dma_handle, size, direction, 0);
kmem_free(vaddr, size);
}
void *
linuxkpi_dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t gfp, unsigned long attrs)
{
return (linuxkpi_dma_alloc_noncoherent(dev, size, dma_handle,
DMA_BIDIRECTIONAL, gfp));
}
void
linuxkpi_dma_free_attrs(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, unsigned long attrs)
{
linuxkpi_dma_free_noncoherent(dev, size, vaddr, dma_handle,
DMA_BIDIRECTIONAL);
}
void
linuxkpi_dma_sync(struct device *dev, dma_addr_t dma_addr, size_t size,
bus_dmasync_op_t op)