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