bus_dmamem_alloc doesn't follow alignment specified

Konstantin Belousov kostikbel at gmail.com
Tue Nov 27 12:24:57 UTC 2018


On Tue, Nov 27, 2018 at 04:37:57PM +0530, Rajesh Kumar wrote:
> Hi,
> 
> I am writing a PCI-E driver, where I am trying to allocate DMA buffers. But
> seems, like the alignment requirements are not satisfied by
> bus_dmamem_alloc function. I am using stable/11 branch.
> 
> *Code :*
> dma_setup(size, align, alimit)  {
> 
>     printf ("size 0x%x align 0x%x alimit 0x%x\n", size, align, alimit);
> 
>      if (bus_dma_tag_create(parent, align, 0,
>                alimit, BUS_SPACE_MAXADDR,
>                 NULL, NULL, size, 1, size,
>                 0, NULL, NULL, &dma_tag)) {
>                 return (ENOMEM);
>     }
> 
>     if (bus_dmamem_alloc(dma_tag, &virt_addr,
>                 BUS_DMA_WAITOK | BUS_DMA_ZERO, &dma_map)) {
>                     bus_dma_tag_destroy(dma_tag);
>                     return (ENOMEM);
>     }
> 
>     if (bus_dmamap_load(dma_tag, dma_map, virt_addr,
>                 size, dma_cbfn, &arg, BUS_DMA_NOWAIT)) {
>                    bus_dmamem_free(dma_tag, virt_addr, dma_map);
>                    bus_dma_tag_destroy(mw->dma_tag);
>                    return (ENOMEM);
>    }
> 
>    printf("dma_addr 0x%lx virt_addr 0x%lx\n", (uint64_t)arg->addr,
> (uint64_t)virt_addr);
> 
> }
> 
> dma_cbfn(void *tmp, bus_dma_segment_t *segs, int nsegs, int error)
> {
>         struct dma_args *arg = (struct dma_args *)tmp;
>         arg->addr = segs[0].ds_addr;
> }
> 
> *Logs: *
> size 0x100000 align 0x100000 alimit 0xffffffff
> dma_addr *0x78e00000*  virt_addr *0xfffffe1c3665f000*
> 
> As seen above, dma_addr is as per alignment requirement, but virtual
> address from bus_dmamem_alloc doesn't seem to satisfy the alignment
> requirement).
> 
> My understanding is both the DMA addr and the virtual address should be as
> per the alignment specified.  Can anyone please clarify?

Only bus address is aligned.

For single-segment i.e. contiguous allocations, amd64 could benefit from
using dmap VA instead of kmem_alloc.  This would be only an optimization,
not done right now.


More information about the freebsd-drivers mailing list