openbsd_network & drivers: Implement the real bus_dmamem functions.

This required the addition of some slight modifications to the main
(FreeBSD compat) bus_dma implementation.

Allows some #ifdefs from iaxwifi/idualwifi to be dropped, and will
ease the porting of some future drivers.

Tested with idualwifi7260, seems to work as before.
This commit is contained in:
Augustin Cavalier 2023-01-27 23:26:18 -05:00
parent 88864ff1f9
commit 231f740ccc
5 changed files with 87 additions and 56 deletions

View File

@ -1819,17 +1819,6 @@ iwx_dma_contig_alloc(bus_dma_tag_t tag, struct iwx_dma_info *dma,
dma->tag = tag;
dma->size = size;
#ifdef __FreeBSD_version
err = bus_dmamap_create_obsd(tag, size, 1, size, 0, alignment, BUS_DMA_NOWAIT,
&dma->map, 1);
if (err)
goto fail;
err = bus_dmamem_alloc(dma->map->_dmat, (void **)&dma->vaddr,
BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, &dma->map->_dmamp);
if (err)
goto fail;
#else
err = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,
&dma->map);
if (err)
@ -1839,9 +1828,7 @@ iwx_dma_contig_alloc(bus_dma_tag_t tag, struct iwx_dma_info *dma,
BUS_DMA_NOWAIT | BUS_DMA_ZERO);
if (err)
goto fail;
#endif
#ifndef __FreeBSD_version
if (nsegs > 1) {
err = ENOMEM;
goto fail;
@ -1852,20 +1839,12 @@ iwx_dma_contig_alloc(bus_dma_tag_t tag, struct iwx_dma_info *dma,
if (err)
goto fail;
dma->vaddr = va;
#endif
err = bus_dmamap_load(tag, dma->map, dma->vaddr, size, NULL,
BUS_DMA_NOWAIT);
if (err)
goto fail;
#ifdef __FreeBSD_version
if (dma->map->dm_nsegs > 1) {
err = ENOMEM;
goto fail;
}
#endif
bus_dmamap_sync(tag, dma->map, 0, size, BUS_DMASYNC_PREWRITE);
dma->paddr = dma->map->dm_segs[0].ds_addr;
@ -1883,13 +1862,8 @@ iwx_dma_contig_free(struct iwx_dma_info *dma)
bus_dmamap_sync(dma->tag, dma->map, 0, dma->size,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(dma->tag, dma->map);
#ifdef __FreeBSD_version
bus_dmamem_free(dma->tag, dma->vaddr, dma->map->_dmamp);
dma->map->_dmamp = NULL;
#else
bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size);
bus_dmamem_free(dma->tag, &dma->seg, 1);
#endif
dma->vaddr = NULL;
}
bus_dmamap_destroy(dma->tag, dma->map);

View File

@ -1235,17 +1235,6 @@ iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma,
dma->tag = tag;
dma->size = size;
#ifdef __FreeBSD_version
err = bus_dmamap_create_obsd(tag, size, 1, size, 0, alignment, BUS_DMA_NOWAIT,
&dma->map, 1);
if (err)
goto fail;
err = bus_dmamem_alloc(dma->map->_dmat, (void **)&dma->vaddr,
BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, &dma->map->_dmamp);
if (err)
goto fail;
#else
err = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,
&dma->map);
if (err)
@ -1261,7 +1250,6 @@ iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma,
if (err)
goto fail;
dma->vaddr = va;
#endif
err = bus_dmamap_load(tag, dma->map, dma->vaddr, size, NULL,
BUS_DMA_NOWAIT);
@ -1286,13 +1274,8 @@ iwm_dma_contig_free(struct iwm_dma_info *dma)
bus_dmamap_sync(dma->tag, dma->map, 0, dma->size,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(dma->tag, dma->map);
#ifdef __FreeBSD_version
bus_dmamem_free(dma->tag, dma->vaddr, dma->map->_dmamp);
dma->map->_dmamp = NULL;
#else
bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size);
bus_dmamem_free(dma->tag, &dma->seg, 1);
#endif
dma->vaddr = NULL;
}
bus_dmamap_destroy(dma->tag, dma->map);

View File

@ -253,10 +253,13 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
if (flags & BUS_DMA_ZERO)
mflags |= M_ZERO;
bus_dmamap_create(dmat, flags, mapp);
// FreeBSD does not permit the "mapp" argument to be NULL, but we do.
if (mapp != NULL) {
bus_dmamap_create(dmat, flags, mapp);
// Drivers assume dmamem will never be bounced, so ensure that.
(*mapp)->buffer_type = bus_dmamap::BUFFER_PROHIBITED;
// Drivers assume dmamem will never be bounced, so ensure that.
(*mapp)->buffer_type = bus_dmamap::BUFFER_PROHIBITED;
}
// FreeBSD uses standard malloc() for the case where maxsize <= PAGE_SIZE,
// but we want to keep DMA'd memory a bit more separate, so we always use
@ -289,17 +292,24 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
} else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
dprintf("bus_dmamem_alloc: failed to align memory: wanted %#x, got %#x\n",
dmat->alignment, vtophys(vaddr));
bus_dmamem_free(dmat, *vaddr, *mapp);
bus_dmamem_free(dmat, *vaddr, (mapp != NULL) ? *mapp : NULL);
return ENOMEM;
}
return 0;
}
extern "C" void
bus_dmamem_free_tagless(void* vaddr, size_t size)
{
kernel_contigfree(vaddr, size, M_DEVBUF);
}
extern "C" void
bus_dmamem_free(bus_dma_tag_t dmat, void* vaddr, bus_dmamap_t map)
{
kernel_contigfree(vaddr, dmat->maxsize, M_DEVBUF);
bus_dmamem_free_tagless(vaddr, dmat->maxsize);
bus_dmamap_destroy(dmat, map);
}

View File

@ -211,6 +211,9 @@ int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
*/
void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
/* Haiku extension, OpenBSD compatibility */
void bus_dmamem_free_tagless(void *vaddr, size_t size);
/*
* Map the buffer buf into bus space using the dmamap map.
*/
@ -245,8 +248,10 @@ int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map,
* is NULL we have a fully IO-coherent system.
*/
void bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t dmamap, bus_dmasync_op_t op);
/* Haiku extension, OpenBSD compatibility */
void bus_dmamap_sync_etc(bus_dma_tag_t dmat, bus_dmamap_t dmamap,
bus_addr_t offset, bus_size_t length, bus_dmasync_op_t op); /* Haiku extension */
bus_addr_t offset, bus_size_t length, bus_dmasync_op_t op);
/*
* Release the mapping held by map.

View File

@ -28,26 +28,24 @@ typedef struct bus_dmamap_obsd* bus_dmamap_obsd_t;
static int
bus_dmamap_create_obsd(bus_dma_tag_t tag, bus_size_t maxsize,
int nsegments, bus_size_t maxsegsz, bus_size_t boundary, bus_size_t alignment,
int flags, bus_dmamap_t* dmamp, int no_alloc_map)
int nsegments, bus_size_t maxsegsz, bus_size_t boundary,
int flags, bus_dmamap_t* dmamp)
{
*dmamp = calloc(sizeof(struct bus_dmamap_obsd) + (sizeof(bus_dma_segment_t) * nsegments), 1);
if ((*dmamp) == NULL)
return ENOMEM;
int error = bus_dma_tag_create(tag, alignment, boundary,
int error = bus_dma_tag_create(tag, 1, boundary,
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
maxsize, nsegments, maxsegsz, flags, NULL, NULL,
&(*dmamp)->_dmat);
if (error != 0)
return error;
if (!no_alloc_map)
error = bus_dmamap_create((*dmamp)->_dmat, flags, &(*dmamp)->_dmamp);
error = bus_dmamap_create((*dmamp)->_dmat, flags, &(*dmamp)->_dmamp);
return error;
}
#define bus_dmamap_create(tag, maxsize, nsegments, maxsegsz, boundary, flags, dmamp) \
bus_dmamap_create_obsd(tag, maxsize, nsegments, maxsegsz, boundary, 1, flags, dmamp, 0)
#define bus_dmamap_create bus_dmamap_create_obsd
static void
@ -111,4 +109,65 @@ bus_dmamap_sync_obsd(bus_dma_tag_t tag, bus_dmamap_t dmam,
#define bus_dmamap_sync bus_dmamap_sync_obsd
static int
bus_dmamem_alloc_obsd(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment, bus_size_t boundary,
bus_dma_segment_t* segs, int nsegs, int* rsegs, int flags)
{
// OpenBSD distinguishes between three different types of addresses:
// 1. virtual addresses (caddr_t)
// 2. opaque "bus" addresses
// 3. physical addresses
// This function returns the second type. We simply return the virtual address for it.
bus_dma_tag_t local;
int error = bus_dma_tag_create(tag, alignment, boundary,
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
size, nsegs, size, flags, NULL, NULL, &local);
if (error)
return error;
error = bus_dmamem_alloc(local, (void**)&segs[0].ds_addr, flags, NULL);
if (error)
return error;
segs[0].ds_len = size;
error = bus_dma_tag_destroy(local);
if (error)
return error;
*rsegs = 1;
return 0;
}
#define bus_dmamem_alloc bus_dmamem_alloc_obsd
static void
bus_dmamem_free_obsd(bus_dma_tag_t tag, bus_dma_segment_t* segs, int nsegs)
{
for (int i = 0; i < nsegs; i++)
bus_dmamem_free_tagless(segs[i].ds_addr, segs[i].ds_len);
}
#define bus_dmamem_free bus_dmamem_free_obsd
static int
bus_dmamem_map_obsd(bus_dma_tag_t tag, bus_dma_segment_t* segs, int nsegs, size_t size, caddr_t* kvap, int flags)
{
if (nsegs != 1)
return EINVAL;
*kvap = (caddr_t)segs[0].ds_addr;
return 0;
}
#define bus_dmamem_map bus_dmamem_map_obsd
static void
bus_dmamem_unmap_obsd(bus_dma_tag_t tag, caddr_t kva, size_t size)
{
// Nothing to do.
}
#define bus_dmamem_unmap bus_dmamem_unmap_obsd
#endif /* _OBSD_COMPAT_MACHINE_BUS_H_ */