problem with bus_dmamap_load_uio

John Baldwin jhb at freebsd.org
Mon Nov 3 14:51:25 PST 2008


On Monday 03 November 2008 03:50:21 pm Patrick Lamaizière wrote:
> Hello,
> 
> (8-Current/i386)
> 
> I've got a problem with bus_dmamap_load_uio(9). I want to use it to
> map an uio for DMA with the Geode security block (glxsb(4)).
> 
> It works, i can make milions of crypto operations with cryptotest.
> 
> But when (i guess, i'm not sure) the free memory becomes low,
> bus_dmamap_load_uio() fails with errno == EFBIG.
> 
> I can reproduce the problem by running "periodic daily", "dd
> if=/dev/zero of=foo", ...
> 
> By sample i run into problems with Mem: 33M Active, 310M Inact, 82M
> Wired, 60M Buf, 69M Free.
> 
> When it fails the uio is :
> uio_segflg = UIO_SYSSPACE
> uio_iovcnt = 1, 
> totlen = 16384 (the total length for iov)
> uio_resid = 16384
> 
> (i've got some failure with size between 4000 and 16384)
> 
> I don't understand why bus_dmamap_load_uio() cannot load the uio. Also
> when it fails, i copy the uio into a buffer and then a
> bus_dmamap_load() of the buffer always works.
> 
> The dma tag is allocated with:
> 
> bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),/* parent */
>  16, 0,                   /* alignments, bounds */
>  BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
>  BUS_SPACE_MAXADDR,       /* highaddr */
>  NULL, NULL,              /* filter, filterarg */
>  16384,                   /* maxsize */
>  1,                       /* nsegments */
>  16384,                   /* maxsegsize */
>  BUS_DMA_ALLOCNOW,        /* flags */
>  NULL, NULL,              /* lockfunc, lockarg */
>  &sc->sc_dmat);
> 
> The dma map is created just before the bus_dmamap_load_uio() and
> destroyed later.
> 
> (source : http://user.lamaiziere.net/patrick/glxsb.c , see
> glxsb_crypto_encdec() ).
> 
> I'm trying to understand and fix this problem for several days, so any
> idea will be very cool...

Your dma tag only allows a single scatter/gather entry (nsegments).  What is 
happening is that under memory pressure, the virtual buffer in userland is 
not built from physically contiguous pages, so you would need multiple s/g 
entries to describe the buffer.  Hence EFBIG.  If your hardware can handle 
multiple s/g entries, then just increase 'nsegments' and handle the multiple 
segments in your callback routine.

-- 
John Baldwin


More information about the freebsd-hackers mailing list