diff options
author | sephe <sephe@FreeBSD.org> | 2016-06-23 03:25:18 +0000 |
---|---|---|
committer | sephe <sephe@FreeBSD.org> | 2016-06-23 03:25:18 +0000 |
commit | f973c8e224eb04204c69079b96378392b645b12c (patch) | |
tree | 121ea71c4159729aa529d07c3749b8ed0b00c90f /sys/dev/hyperv/vmbus/hyperv_busdma.c | |
parent | 7c851a7c2e1581791275ad3bb5b524e96d50937f (diff) | |
download | FreeBSD-src-f973c8e224eb04204c69079b96378392b645b12c.zip FreeBSD-src-f973c8e224eb04204c69079b96378392b645b12c.tar.gz |
MFC 300478,300479
300478
hyperv: Add helpers for busdma(9) operation
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6443
300479
hyperv/hn: Use hyperv busdma(9) helper.
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6444
Diffstat (limited to 'sys/dev/hyperv/vmbus/hyperv_busdma.c')
-rw-r--r-- | sys/dev/hyperv/vmbus/hyperv_busdma.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/sys/dev/hyperv/vmbus/hyperv_busdma.c b/sys/dev/hyperv/vmbus/hyperv_busdma.c new file mode 100644 index 0000000..07f4e74 --- /dev/null +++ b/sys/dev/hyperv/vmbus/hyperv_busdma.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <machine/bus.h> + +#include <dev/hyperv/include/hyperv_busdma.h> + +#define HYPERV_DMA_WAITMASK (BUS_DMA_WAITOK | BUS_DMA_NOWAIT) + +void +hyperv_dma_map_paddr(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + bus_addr_t *paddr = arg; + + if (error) + return; + + KASSERT(nseg == 1, ("too many segments %d!", nseg)); + *paddr = segs->ds_addr; +} + +void * +hyperv_dmamem_alloc(bus_dma_tag_t parent_dtag, bus_size_t alignment, + bus_addr_t boundary, bus_size_t size, struct hyperv_dma *dma, int flags) +{ + void *ret; + int error; + + error = bus_dma_tag_create(parent_dtag, /* parent */ + alignment, /* alignment */ + boundary, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + size, /* maxsize */ + 1, /* nsegments */ + size, /* maxsegsize */ + 0, /* flags */ + NULL, /* lockfunc */ + NULL, /* lockfuncarg */ + &dma->hv_dtag); + if (error) + return NULL; + + error = bus_dmamem_alloc(dma->hv_dtag, &ret, + (flags & HYPERV_DMA_WAITMASK) | BUS_DMA_COHERENT, &dma->hv_dmap); + if (error) { + bus_dma_tag_destroy(dma->hv_dtag); + return NULL; + } + + error = bus_dmamap_load(dma->hv_dtag, dma->hv_dmap, ret, size, + hyperv_dma_map_paddr, &dma->hv_paddr, BUS_DMA_NOWAIT); + if (error) { + bus_dmamem_free(dma->hv_dtag, ret, dma->hv_dmap); + bus_dma_tag_destroy(dma->hv_dtag); + return NULL; + } + return ret; +} + +void +hyperv_dmamem_free(struct hyperv_dma *dma, void *ptr) +{ + bus_dmamap_unload(dma->hv_dtag, dma->hv_dmap); + bus_dmamem_free(dma->hv_dtag, ptr, dma->hv_dmap); + bus_dma_tag_destroy(dma->hv_dtag); +} |