Date: Wed, 21 Oct 2009 11:21:15 -0500 From: Jason Harmening <jason.harmening@gmail.com> To: freebsd-hackers@freebsd.org Subject: multi-seg bus_dmamem_alloc? Message-ID: <2d1264630910210921w4a2fabb1h86e12658a3f7c714@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
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 sglist_build(). 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:) --Jason
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2d1264630910210921w4a2fabb1h86e12658a3f7c714>