From 231f740cccf5ca709e2210b6528e0d1119b9494d Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Fri, 27 Jan 2023 23:26:18 -0500 Subject: [PATCH] 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. --- .../network/wlan/iaxwifi200/dev/pci/if_iwx.c | 26 ------- .../wlan/idualwifi7260/dev/pci/if_iwm.c | 17 ----- src/libs/compat/freebsd_network/bus_dma.cpp | 20 +++-- .../freebsd_network/compat/sys/bus_dma.h | 7 +- .../openbsd_network/compat/machine/bus.h | 73 +++++++++++++++++-- 5 files changed, 87 insertions(+), 56 deletions(-) diff --git a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c index f818c50884..ee7fa0378c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c +++ b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c @@ -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); diff --git a/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/pci/if_iwm.c b/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/pci/if_iwm.c index 5c982d9321..f82f14e7d7 100644 --- a/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/pci/if_iwm.c +++ b/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/pci/if_iwm.c @@ -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); diff --git a/src/libs/compat/freebsd_network/bus_dma.cpp b/src/libs/compat/freebsd_network/bus_dma.cpp index eb0cb22f26..3a24072fe7 100644 --- a/src/libs/compat/freebsd_network/bus_dma.cpp +++ b/src/libs/compat/freebsd_network/bus_dma.cpp @@ -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); } diff --git a/src/libs/compat/freebsd_network/compat/sys/bus_dma.h b/src/libs/compat/freebsd_network/compat/sys/bus_dma.h index 6cf6bef81a..a8e63d6417 100644 --- a/src/libs/compat/freebsd_network/compat/sys/bus_dma.h +++ b/src/libs/compat/freebsd_network/compat/sys/bus_dma.h @@ -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. diff --git a/src/libs/compat/openbsd_network/compat/machine/bus.h b/src/libs/compat/openbsd_network/compat/machine/bus.h index 4d7cb74721..e37a3e86c0 100644 --- a/src/libs/compat/openbsd_network/compat/machine/bus.h +++ b/src/libs/compat/openbsd_network/compat/machine/bus.h @@ -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_ */