Subject: Re: Valid use of bus_dma(9)?
To: None <tech-kern@NetBSD.org>
From: Jochen Kunz <jkunz@unixag-kl.fh-kl.de>
List: tech-kern
Date: 07/24/2004 10:52:13
On Fri, 23 Jul 2004 16:04:54 -0700
Matt Thomas <matt@3am-software.com> wrote:

> >The whole idea is that bus_dmamem_alloc() returns addresses that are=20
> >opaque to the driver.  The driver MUST use bus_dmamap_load*() in
> >order to translate an address to one valid for use in DMA.
> which fpa does.  It allocates a 8KB chunk of which only a small
> portion should be coherent.  it try to map/load this small chunk as
> coherent which is what that code is trying to do.
This is what I thought. I noticed that fpa(4) uses BUS_DMA_COHERENT only
in the call to bus_dmamem_map(9) that double maps an already allocated
piece of DMA memory. This brings up the question why do you do this?
Performance optimization because most of the DMA memory remains
cachable? Why don't you use an extra piece of DMA memory for that
coherent descriptor? To save an extra page of memory? Or is the hardware
unable to split off that descriptor?

The problem with fpa(4) is that it copies a bus_dma_segment_t, modifies
its "visable" values in ds_addr / ds_len and feeds that to
bus_dmamem_map(9). But bus_dmamem_alloc(9) may prepare things for a
mapping and may store MD state in the bus_dma_segment_t. So
bus_dmamem_map(9) may only work proper when bus_dmamem_alloc(9) was
caled with that bus_dma_segment_t before. Also bus_dmamem_map(9) may
ignore the values in ds_addr / ds_len and use only values of its
internal state to generate ds_addr / ds_len. In fact the hp700
bus_dma(9) code does this: bus_dmamem_alloc(9) initializes ds_addr and
ds_len to 0. Even the hp700 bus_dmamem_map(9) does not set ds_addr /
ds_len. ds_addr / ds_len are only valid after a successful call to
bus_dmamap_load(9). This is valid, to may understandig of bus_dma(9):

     bus_dmamem_alloc(tag, size, alignment, boundary, segs, ...)
              Allocates memory that is "DMA safe" for the bus corresponding to
              the given tag.

              The mapping of this memory is machine-dependent (or "opaque");
              machine-independent code is not to assume that the addresses re-
              turned are valid in kernel virtual address space, or that the
              addresses returned are system physical addresses. The address
              value returned as part of segs can thus not be used to program
              DMA controller address registers. Only the values in the dm_segs
              array of a successfully loaded DMA map (using bus_dmamap_load()
              ) can be used for this purpose.
[...]
              segs       An array of bus_dma_segment_t's, filled in as memory
                         is allocated, representing the opaque addresses of
                         the memory chunks.
--=20


tsch=FC=DF,
       Jochen

Homepage: http://www.unixag-kl.fh-kl.de/~jkunz/