multi-seg bus_dmamem_alloc?

Jason Harmening jason.harmening at
Wed Oct 21 16:42:48 UTC 2009

Hi everyone,

It seems like there are starting to be some drivers that need to
allocate large chunks of DMA-able memory, and since bus_dmamem_alloc()
on most architectures is always physically contiguous, it may not work
for them.

It seems like we could use the new sglist routines to help us here:

--Define 2 new functions:

     int bus_dmamem_alloc_sglist(bus_dma_tag_t dmat, size_t size,
struct sglist *sg, int flags, bus_dmamap_t *mapp)

     void bus_dmamem_free_sglist(bus_dma_tag_t dmat, struct sglist
*sg, bus_dmamap_t map);

--For sparc64 (or anywhere else we want to use an IOMMU):

     malloc() the buffer, feed it to sglist_build(), program the IOMMU
to meet the constraints in dmat--Isn't this what we already do for
sparc64, minus the sglist part?

--For direct-mapped architectures:

     If the constraints in dmat are lenient enough, do malloc() and
     Otherwise, do contigmalloc(M_NOWAIT) in a loop, in which we try
to allocate as much of the buffer as possible.  Anytime an allocation
fails, we divide the allocation size by (roughly) 2 until the
allocation succeeds, and continue allocating until either we've
allocated enough space, or the allocation size drops below PAGE_SIZE,
or we exceed dmat->maxsegs.

--Some other things we'd need:
     --bus_dmamap_load_sglist()--I think jhb already did this as part
of the sglist work, at least for amd64
     --Structures in the busdma map to track allocated buffers so we
could free them later.
     --Are there lower-level calls we could make to just allocate the
physical pages instead of malloc()/contigmalloc()?  The kva mapping
for each allocated buffer segment isn't necessary.  A lot of drivers
would probably just want to mmap the sglist to userspace anyway.
     --Could we instead just integrate this multi-seg functionality
into the default bus_dmamem_alloc()?  We'd at least have to be able
map the physical segments into a contiguous kva area--we wouldn't
necessarily have to use an sglist in this case either.

Let me know if this idea has any potential--if it does, I'd love to
try implementing it:)


More information about the freebsd-hackers mailing list