171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 271d10453SEric Joyner /* Copyright (c) 2020, Intel Corporation 371d10453SEric Joyner * All rights reserved. 471d10453SEric Joyner * 571d10453SEric Joyner * Redistribution and use in source and binary forms, with or without 671d10453SEric Joyner * modification, are permitted provided that the following conditions are met: 771d10453SEric Joyner * 871d10453SEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 971d10453SEric Joyner * this list of conditions and the following disclaimer. 1071d10453SEric Joyner * 1171d10453SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 1271d10453SEric Joyner * notice, this list of conditions and the following disclaimer in the 1371d10453SEric Joyner * documentation and/or other materials provided with the distribution. 1471d10453SEric Joyner * 1571d10453SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 1671d10453SEric Joyner * contributors may be used to endorse or promote products derived from 1771d10453SEric Joyner * this software without specific prior written permission. 1871d10453SEric Joyner * 1971d10453SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2071d10453SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2171d10453SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2271d10453SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2371d10453SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2471d10453SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2571d10453SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2671d10453SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2771d10453SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2871d10453SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2971d10453SEric Joyner * POSSIBILITY OF SUCH DAMAGE. 3071d10453SEric Joyner */ 3171d10453SEric Joyner /*$FreeBSD$*/ 3271d10453SEric Joyner 3371d10453SEric Joyner /** 3471d10453SEric Joyner * @file ice_osdep.c 3571d10453SEric Joyner * @brief Functions used to implement OS compatibility layer 3671d10453SEric Joyner * 3771d10453SEric Joyner * Contains functions used by ice_osdep.h to implement the OS compatibility 3871d10453SEric Joyner * layer used by some of the hardware files. Specifically, it is for the bits 3971d10453SEric Joyner * of OS compatibility which don't make sense as macros or inline functions. 4071d10453SEric Joyner */ 4171d10453SEric Joyner 4271d10453SEric Joyner #include "ice_common.h" 4371d10453SEric Joyner #include "ice_iflib.h" 4471d10453SEric Joyner #include <machine/stdarg.h> 4571d10453SEric Joyner #include <sys/time.h> 4671d10453SEric Joyner 4771d10453SEric Joyner /** 4871d10453SEric Joyner * @var M_ICE_OSDEP 4971d10453SEric Joyner * @brief OS compatibility layer allocation type 5071d10453SEric Joyner * 5171d10453SEric Joyner * malloc(9) allocation type used by the OS compatibility layer for 5271d10453SEric Joyner * distinguishing allocations by this layer from those of the rest of the 5371d10453SEric Joyner * driver. 5471d10453SEric Joyner */ 5571d10453SEric Joyner MALLOC_DEFINE(M_ICE_OSDEP, "ice-osdep", "Intel(R) 100Gb Network Driver osdep allocations"); 5671d10453SEric Joyner 5771d10453SEric Joyner /** 5871d10453SEric Joyner * @var ice_lock_count 5971d10453SEric Joyner * @brief Global count of # of ice_lock mutexes initialized 6071d10453SEric Joyner * 6171d10453SEric Joyner * A global count of the total number of times that ice_init_lock has been 6271d10453SEric Joyner * called. This is used to generate unique lock names for each ice_lock, to 6371d10453SEric Joyner * aid in witness lock checking. 6471d10453SEric Joyner */ 6571d10453SEric Joyner u16 ice_lock_count = 0; 6671d10453SEric Joyner 6771d10453SEric Joyner static void ice_dmamap_cb(void *arg, bus_dma_segment_t * segs, int __unused nseg, int error); 6871d10453SEric Joyner 6971d10453SEric Joyner /** 7071d10453SEric Joyner * ice_hw_to_dev - Given a hw private struct, find the associated device_t 7171d10453SEric Joyner * @hw: the hardware private structure 7271d10453SEric Joyner * 7371d10453SEric Joyner * Given a hw structure pointer, lookup the softc and extract the device 7471d10453SEric Joyner * pointer. Assumes that hw is embedded within the ice_softc, instead of being 7571d10453SEric Joyner * allocated separately, so that __containerof math will work. 7671d10453SEric Joyner * 7771d10453SEric Joyner * This can't be defined in ice_osdep.h as it depends on the complete 7871d10453SEric Joyner * definition of struct ice_softc. That can't be easily included in 7971d10453SEric Joyner * ice_osdep.h without creating circular header dependencies. 8071d10453SEric Joyner */ 8171d10453SEric Joyner device_t 8271d10453SEric Joyner ice_hw_to_dev(struct ice_hw *hw) { 8371d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 8471d10453SEric Joyner 8571d10453SEric Joyner return sc->dev; 8671d10453SEric Joyner } 8771d10453SEric Joyner 8871d10453SEric Joyner /** 8971d10453SEric Joyner * ice_debug - Log a debug message if the type is enabled 9071d10453SEric Joyner * @hw: device private hardware structure 9171d10453SEric Joyner * @mask: the debug message type 9271d10453SEric Joyner * @fmt: printf format specifier 9371d10453SEric Joyner * 9471d10453SEric Joyner * Check if hw->debug_mask has enabled the given message type. If so, log the 9571d10453SEric Joyner * message to the console using vprintf. Mimic the output of device_printf by 9671d10453SEric Joyner * using device_print_prettyname(). 9771d10453SEric Joyner */ 9871d10453SEric Joyner void 9971d10453SEric Joyner ice_debug(struct ice_hw *hw, uint64_t mask, char *fmt, ...) 10071d10453SEric Joyner { 10171d10453SEric Joyner device_t dev = ice_hw_to_dev(hw); 10271d10453SEric Joyner va_list args; 10371d10453SEric Joyner 10471d10453SEric Joyner if (!(mask & hw->debug_mask)) 10571d10453SEric Joyner return; 10671d10453SEric Joyner 10771d10453SEric Joyner device_print_prettyname(dev); 10871d10453SEric Joyner va_start(args, fmt); 10971d10453SEric Joyner vprintf(fmt, args); 11071d10453SEric Joyner va_end(args); 11171d10453SEric Joyner } 11271d10453SEric Joyner 11371d10453SEric Joyner /** 11471d10453SEric Joyner * ice_debug_array - Format and print an array of values to the console 11571d10453SEric Joyner * @hw: private hardware structure 11671d10453SEric Joyner * @mask: the debug message type 11771d10453SEric Joyner * @rowsize: preferred number of rows to use 11871d10453SEric Joyner * @groupsize: preferred size in bytes to print each chunk 11971d10453SEric Joyner * @buf: the array buffer to print 12071d10453SEric Joyner * @len: size of the array buffer 12171d10453SEric Joyner * 12271d10453SEric Joyner * Format the given array as a series of uint8_t values with hexadecimal 12371d10453SEric Joyner * notation and log the contents to the console log. 12471d10453SEric Joyner * 12571d10453SEric Joyner * TODO: Currently only supports a group size of 1, due to the way hexdump is 12671d10453SEric Joyner * implemented. 12771d10453SEric Joyner */ 12871d10453SEric Joyner void 12971d10453SEric Joyner ice_debug_array(struct ice_hw *hw, uint64_t mask, uint32_t rowsize, 13071d10453SEric Joyner uint32_t __unused groupsize, uint8_t *buf, size_t len) 13171d10453SEric Joyner { 13271d10453SEric Joyner device_t dev = ice_hw_to_dev(hw); 13371d10453SEric Joyner char prettyname[20]; 13471d10453SEric Joyner 13571d10453SEric Joyner if (!(mask & hw->debug_mask)) 13671d10453SEric Joyner return; 13771d10453SEric Joyner 13871d10453SEric Joyner /* Format the device header to a string */ 13971d10453SEric Joyner snprintf(prettyname, sizeof(prettyname), "%s: ", device_get_nameunit(dev)); 14071d10453SEric Joyner 14171d10453SEric Joyner /* Make sure the row-size isn't too large */ 14271d10453SEric Joyner if (rowsize > 0xFF) 14371d10453SEric Joyner rowsize = 0xFF; 14471d10453SEric Joyner 14571d10453SEric Joyner hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize); 14671d10453SEric Joyner } 14771d10453SEric Joyner 14871d10453SEric Joyner /** 14971d10453SEric Joyner * rd32 - Read a 32bit hardware register value 15071d10453SEric Joyner * @hw: the private hardware structure 15171d10453SEric Joyner * @reg: register address to read 15271d10453SEric Joyner * 15371d10453SEric Joyner * Read the specified 32bit register value from BAR0 and return its contents. 15471d10453SEric Joyner */ 15571d10453SEric Joyner uint32_t 15671d10453SEric Joyner rd32(struct ice_hw *hw, uint32_t reg) 15771d10453SEric Joyner { 15871d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 15971d10453SEric Joyner 16071d10453SEric Joyner return bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg); 16171d10453SEric Joyner } 16271d10453SEric Joyner 16371d10453SEric Joyner /** 16471d10453SEric Joyner * rd64 - Read a 64bit hardware register value 16571d10453SEric Joyner * @hw: the private hardware structure 16671d10453SEric Joyner * @reg: register address to read 16771d10453SEric Joyner * 16871d10453SEric Joyner * Read the specified 64bit register value from BAR0 and return its contents. 16971d10453SEric Joyner * 17071d10453SEric Joyner * @pre For 32-bit builds, assumes that the 64bit register read can be 17171d10453SEric Joyner * safely broken up into two 32-bit register reads. 17271d10453SEric Joyner */ 17371d10453SEric Joyner uint64_t 17471d10453SEric Joyner rd64(struct ice_hw *hw, uint32_t reg) 17571d10453SEric Joyner { 17671d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 17771d10453SEric Joyner uint64_t data; 17871d10453SEric Joyner 17971d10453SEric Joyner #ifdef __amd64__ 18071d10453SEric Joyner data = bus_space_read_8(sc->bar0.tag, sc->bar0.handle, reg); 18171d10453SEric Joyner #else 18271d10453SEric Joyner /* 18371d10453SEric Joyner * bus_space_read_8 isn't supported on 32bit platforms, so we fall 18471d10453SEric Joyner * back to using two bus_space_read_4 calls. 18571d10453SEric Joyner */ 18671d10453SEric Joyner data = bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg); 18771d10453SEric Joyner data |= ((uint64_t)bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg + 4)) << 32; 18871d10453SEric Joyner #endif 18971d10453SEric Joyner 19071d10453SEric Joyner return data; 19171d10453SEric Joyner } 19271d10453SEric Joyner 19371d10453SEric Joyner /** 19471d10453SEric Joyner * wr32 - Write a 32bit hardware register 19571d10453SEric Joyner * @hw: the private hardware structure 19671d10453SEric Joyner * @reg: the register address to write to 19771d10453SEric Joyner * @val: the 32bit value to write 19871d10453SEric Joyner * 19971d10453SEric Joyner * Write the specified 32bit value to a register address in BAR0. 20071d10453SEric Joyner */ 20171d10453SEric Joyner void 20271d10453SEric Joyner wr32(struct ice_hw *hw, uint32_t reg, uint32_t val) 20371d10453SEric Joyner { 20471d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 20571d10453SEric Joyner 20671d10453SEric Joyner bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg, val); 20771d10453SEric Joyner } 20871d10453SEric Joyner 20971d10453SEric Joyner /** 21071d10453SEric Joyner * wr64 - Write a 64bit hardware register 21171d10453SEric Joyner * @hw: the private hardware structure 21271d10453SEric Joyner * @reg: the register address to write to 21371d10453SEric Joyner * @val: the 64bit value to write 21471d10453SEric Joyner * 21571d10453SEric Joyner * Write the specified 64bit value to a register address in BAR0. 21671d10453SEric Joyner * 21771d10453SEric Joyner * @pre For 32-bit builds, assumes that the 64bit register write can be safely 21871d10453SEric Joyner * broken up into two 32-bit register writes. 21971d10453SEric Joyner */ 22071d10453SEric Joyner void 22171d10453SEric Joyner wr64(struct ice_hw *hw, uint32_t reg, uint64_t val) 22271d10453SEric Joyner { 22371d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 22471d10453SEric Joyner 22571d10453SEric Joyner #ifdef __amd64__ 22671d10453SEric Joyner bus_space_write_8(sc->bar0.tag, sc->bar0.handle, reg, val); 22771d10453SEric Joyner #else 22871d10453SEric Joyner uint32_t lo_val, hi_val; 22971d10453SEric Joyner 23071d10453SEric Joyner /* 23171d10453SEric Joyner * bus_space_write_8 isn't supported on 32bit platforms, so we fall 23271d10453SEric Joyner * back to using two bus_space_write_4 calls. 23371d10453SEric Joyner */ 23471d10453SEric Joyner lo_val = (uint32_t)val; 23571d10453SEric Joyner hi_val = (uint32_t)(val >> 32); 23671d10453SEric Joyner bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg, lo_val); 23771d10453SEric Joyner bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg + 4, hi_val); 23871d10453SEric Joyner #endif 23971d10453SEric Joyner } 24071d10453SEric Joyner 24171d10453SEric Joyner /** 24271d10453SEric Joyner * ice_usec_delay - Delay for the specified number of microseconds 24371d10453SEric Joyner * @time: microseconds to delay 24471d10453SEric Joyner * @sleep: if true, sleep where possible 24571d10453SEric Joyner * 24671d10453SEric Joyner * If sleep is true, and if the current thread is allowed to sleep, pause so 24771d10453SEric Joyner * that another thread can execute. Otherwise, use DELAY to spin the thread 24871d10453SEric Joyner * instead. 24971d10453SEric Joyner */ 25071d10453SEric Joyner void 25171d10453SEric Joyner ice_usec_delay(uint32_t time, bool sleep) 25271d10453SEric Joyner { 25371d10453SEric Joyner if (sleep && THREAD_CAN_SLEEP()) 25471d10453SEric Joyner pause("ice_usec_delay", USEC_2_TICKS(time)); 25571d10453SEric Joyner else 25671d10453SEric Joyner DELAY(time); 25771d10453SEric Joyner } 25871d10453SEric Joyner 25971d10453SEric Joyner /** 26071d10453SEric Joyner * ice_msec_delay - Delay for the specified number of milliseconds 26171d10453SEric Joyner * @time: milliseconds to delay 26271d10453SEric Joyner * @sleep: if true, sleep where possible 26371d10453SEric Joyner * 26471d10453SEric Joyner * If sleep is true, and if the current thread is allowed to sleep, pause so 26571d10453SEric Joyner * that another thread can execute. Otherwise, use DELAY to spin the thread 26671d10453SEric Joyner * instead. 26771d10453SEric Joyner */ 26871d10453SEric Joyner void 26971d10453SEric Joyner ice_msec_delay(uint32_t time, bool sleep) 27071d10453SEric Joyner { 27171d10453SEric Joyner if (sleep && THREAD_CAN_SLEEP()) 27271d10453SEric Joyner pause("ice_msec_delay", MSEC_2_TICKS(time)); 27371d10453SEric Joyner else 27471d10453SEric Joyner DELAY(time * 1000); 27571d10453SEric Joyner } 27671d10453SEric Joyner 27771d10453SEric Joyner /** 27871d10453SEric Joyner * ice_msec_pause - pause (sleep) the thread for a time in milliseconds 27971d10453SEric Joyner * @time: milliseconds to sleep 28071d10453SEric Joyner * 28171d10453SEric Joyner * Wrapper for ice_msec_delay with sleep set to true. 28271d10453SEric Joyner */ 28371d10453SEric Joyner void 28471d10453SEric Joyner ice_msec_pause(uint32_t time) 28571d10453SEric Joyner { 28671d10453SEric Joyner ice_msec_delay(time, true); 28771d10453SEric Joyner } 28871d10453SEric Joyner 28971d10453SEric Joyner /** 29071d10453SEric Joyner * ice_msec_spin - Spin the thread for a time in milliseconds 29171d10453SEric Joyner * @time: milliseconds to delay 29271d10453SEric Joyner * 29371d10453SEric Joyner * Wrapper for ice_msec_delay with sleep sent to false. 29471d10453SEric Joyner */ 29571d10453SEric Joyner void 29671d10453SEric Joyner ice_msec_spin(uint32_t time) 29771d10453SEric Joyner { 29871d10453SEric Joyner ice_msec_delay(time, false); 29971d10453SEric Joyner } 30071d10453SEric Joyner 30171d10453SEric Joyner /******************************************************************** 30271d10453SEric Joyner * Manage DMA'able memory. 30371d10453SEric Joyner *******************************************************************/ 30471d10453SEric Joyner 30571d10453SEric Joyner /** 30671d10453SEric Joyner * ice_dmamap_cb - Callback function DMA maps 30771d10453SEric Joyner * @arg: pointer to return the segment address 30871d10453SEric Joyner * @segs: the segments array 30971d10453SEric Joyner * @nseg: number of segments in the array 31071d10453SEric Joyner * @error: error code 31171d10453SEric Joyner * 31271d10453SEric Joyner * Callback used by the bus DMA code to obtain the segment address. 31371d10453SEric Joyner */ 31471d10453SEric Joyner static void 31571d10453SEric Joyner ice_dmamap_cb(void *arg, bus_dma_segment_t * segs, int __unused nseg, int error) 31671d10453SEric Joyner { 31771d10453SEric Joyner if (error) 31871d10453SEric Joyner return; 31971d10453SEric Joyner *(bus_addr_t *) arg = segs->ds_addr; 32071d10453SEric Joyner return; 32171d10453SEric Joyner } 32271d10453SEric Joyner 32371d10453SEric Joyner /** 32471d10453SEric Joyner * ice_alloc_dma_mem - Request OS to allocate DMA memory 32571d10453SEric Joyner * @hw: private hardware structure 32671d10453SEric Joyner * @mem: structure defining the DMA memory request 32771d10453SEric Joyner * @size: the allocation size 32871d10453SEric Joyner * 32971d10453SEric Joyner * Allocates some memory for DMA use. Use the FreeBSD bus DMA interface to 33071d10453SEric Joyner * track this memory using a bus DMA tag and map. 33171d10453SEric Joyner * 33271d10453SEric Joyner * Returns a pointer to the DMA memory address. 33371d10453SEric Joyner */ 33471d10453SEric Joyner void * 33571d10453SEric Joyner ice_alloc_dma_mem(struct ice_hw *hw, struct ice_dma_mem *mem, u64 size) 33671d10453SEric Joyner { 33771d10453SEric Joyner device_t dev = ice_hw_to_dev(hw); 33871d10453SEric Joyner int err; 33971d10453SEric Joyner 34071d10453SEric Joyner err = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 34171d10453SEric Joyner 1, 0, /* alignment, boundary */ 34271d10453SEric Joyner BUS_SPACE_MAXADDR, /* lowaddr */ 34371d10453SEric Joyner BUS_SPACE_MAXADDR, /* highaddr */ 34471d10453SEric Joyner NULL, NULL, /* filtfunc, filtfuncarg */ 34571d10453SEric Joyner size, /* maxsize */ 34671d10453SEric Joyner 1, /* nsegments */ 34771d10453SEric Joyner size, /* maxsegsz */ 34871d10453SEric Joyner BUS_DMA_ALLOCNOW, /* flags */ 34971d10453SEric Joyner NULL, /* lockfunc */ 35071d10453SEric Joyner NULL, /* lockfuncarg */ 35171d10453SEric Joyner &mem->tag); 35271d10453SEric Joyner if (err != 0) { 35371d10453SEric Joyner device_printf(dev, 35471d10453SEric Joyner "ice_alloc_dma: bus_dma_tag_create failed, " 35571d10453SEric Joyner "error %s\n", ice_err_str(err)); 35671d10453SEric Joyner goto fail_0; 35771d10453SEric Joyner } 35871d10453SEric Joyner err = bus_dmamem_alloc(mem->tag, (void **)&mem->va, 35971d10453SEric Joyner BUS_DMA_NOWAIT | BUS_DMA_ZERO, &mem->map); 36071d10453SEric Joyner if (err != 0) { 36171d10453SEric Joyner device_printf(dev, 36271d10453SEric Joyner "ice_alloc_dma: bus_dmamem_alloc failed, " 36371d10453SEric Joyner "error %s\n", ice_err_str(err)); 36471d10453SEric Joyner goto fail_1; 36571d10453SEric Joyner } 36671d10453SEric Joyner err = bus_dmamap_load(mem->tag, mem->map, mem->va, 36771d10453SEric Joyner size, 36871d10453SEric Joyner ice_dmamap_cb, 36971d10453SEric Joyner &mem->pa, 37071d10453SEric Joyner BUS_DMA_NOWAIT); 37171d10453SEric Joyner if (err != 0) { 37271d10453SEric Joyner device_printf(dev, 37371d10453SEric Joyner "ice_alloc_dma: bus_dmamap_load failed, " 37471d10453SEric Joyner "error %s\n", ice_err_str(err)); 37571d10453SEric Joyner goto fail_2; 37671d10453SEric Joyner } 37771d10453SEric Joyner mem->size = size; 37871d10453SEric Joyner bus_dmamap_sync(mem->tag, mem->map, 37971d10453SEric Joyner BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 38071d10453SEric Joyner return (mem->va); 38171d10453SEric Joyner fail_2: 38271d10453SEric Joyner bus_dmamem_free(mem->tag, mem->va, mem->map); 38371d10453SEric Joyner fail_1: 38471d10453SEric Joyner bus_dma_tag_destroy(mem->tag); 38571d10453SEric Joyner fail_0: 38671d10453SEric Joyner mem->map = NULL; 38771d10453SEric Joyner mem->tag = NULL; 38871d10453SEric Joyner return (NULL); 38971d10453SEric Joyner } 39071d10453SEric Joyner 39171d10453SEric Joyner /** 39271d10453SEric Joyner * ice_free_dma_mem - Free DMA memory allocated by ice_alloc_dma_mem 39371d10453SEric Joyner * @hw: the hardware private structure 39471d10453SEric Joyner * @mem: DMA memory to free 39571d10453SEric Joyner * 39671d10453SEric Joyner * Release the bus DMA tag and map, and free the DMA memory associated with 39771d10453SEric Joyner * it. 39871d10453SEric Joyner */ 39971d10453SEric Joyner void 40071d10453SEric Joyner ice_free_dma_mem(struct ice_hw __unused *hw, struct ice_dma_mem *mem) 40171d10453SEric Joyner { 40271d10453SEric Joyner bus_dmamap_sync(mem->tag, mem->map, 40371d10453SEric Joyner BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 40471d10453SEric Joyner bus_dmamap_unload(mem->tag, mem->map); 40571d10453SEric Joyner bus_dmamem_free(mem->tag, mem->va, mem->map); 40671d10453SEric Joyner bus_dma_tag_destroy(mem->tag); 40771d10453SEric Joyner mem->map = NULL; 40871d10453SEric Joyner mem->tag = NULL; 40971d10453SEric Joyner } 410