171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2*015f8cc5SEric Joyner /* Copyright (c) 2024, 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 3271d10453SEric Joyner /** 3371d10453SEric Joyner * @file ice_osdep.c 3471d10453SEric Joyner * @brief Functions used to implement OS compatibility layer 3571d10453SEric Joyner * 3671d10453SEric Joyner * Contains functions used by ice_osdep.h to implement the OS compatibility 3771d10453SEric Joyner * layer used by some of the hardware files. Specifically, it is for the bits 3871d10453SEric Joyner * of OS compatibility which don't make sense as macros or inline functions. 3971d10453SEric Joyner */ 4071d10453SEric Joyner 4171d10453SEric Joyner #include "ice_common.h" 4271d10453SEric Joyner #include "ice_iflib.h" 4371d10453SEric Joyner #include <machine/stdarg.h> 4471d10453SEric Joyner #include <sys/time.h> 4571d10453SEric Joyner 4671d10453SEric Joyner /** 4771d10453SEric Joyner * @var M_ICE_OSDEP 4871d10453SEric Joyner * @brief OS compatibility layer allocation type 4971d10453SEric Joyner * 5071d10453SEric Joyner * malloc(9) allocation type used by the OS compatibility layer for 5171d10453SEric Joyner * distinguishing allocations by this layer from those of the rest of the 5271d10453SEric Joyner * driver. 5371d10453SEric Joyner */ 5471d10453SEric Joyner MALLOC_DEFINE(M_ICE_OSDEP, "ice-osdep", "Intel(R) 100Gb Network Driver osdep allocations"); 5571d10453SEric Joyner 5671d10453SEric Joyner /** 5771d10453SEric Joyner * @var ice_lock_count 5871d10453SEric Joyner * @brief Global count of # of ice_lock mutexes initialized 5971d10453SEric Joyner * 6071d10453SEric Joyner * A global count of the total number of times that ice_init_lock has been 6171d10453SEric Joyner * called. This is used to generate unique lock names for each ice_lock, to 6271d10453SEric Joyner * aid in witness lock checking. 6371d10453SEric Joyner */ 6471d10453SEric Joyner u16 ice_lock_count = 0; 6571d10453SEric Joyner 6671d10453SEric Joyner static void ice_dmamap_cb(void *arg, bus_dma_segment_t * segs, int __unused nseg, int error); 6771d10453SEric Joyner 6871d10453SEric Joyner /** 6971d10453SEric Joyner * ice_hw_to_dev - Given a hw private struct, find the associated device_t 7071d10453SEric Joyner * @hw: the hardware private structure 7171d10453SEric Joyner * 7271d10453SEric Joyner * Given a hw structure pointer, lookup the softc and extract the device 7371d10453SEric Joyner * pointer. Assumes that hw is embedded within the ice_softc, instead of being 7471d10453SEric Joyner * allocated separately, so that __containerof math will work. 7571d10453SEric Joyner * 7671d10453SEric Joyner * This can't be defined in ice_osdep.h as it depends on the complete 7771d10453SEric Joyner * definition of struct ice_softc. That can't be easily included in 7871d10453SEric Joyner * ice_osdep.h without creating circular header dependencies. 7971d10453SEric Joyner */ 8071d10453SEric Joyner device_t 8171d10453SEric Joyner ice_hw_to_dev(struct ice_hw *hw) { 8271d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 8371d10453SEric Joyner 8471d10453SEric Joyner return sc->dev; 8571d10453SEric Joyner } 8671d10453SEric Joyner 8771d10453SEric Joyner /** 8871d10453SEric Joyner * ice_debug - Log a debug message if the type is enabled 8971d10453SEric Joyner * @hw: device private hardware structure 9071d10453SEric Joyner * @mask: the debug message type 9171d10453SEric Joyner * @fmt: printf format specifier 9271d10453SEric Joyner * 9371d10453SEric Joyner * Check if hw->debug_mask has enabled the given message type. If so, log the 9471d10453SEric Joyner * message to the console using vprintf. Mimic the output of device_printf by 9571d10453SEric Joyner * using device_print_prettyname(). 9671d10453SEric Joyner */ 9771d10453SEric Joyner void 9871d10453SEric Joyner ice_debug(struct ice_hw *hw, uint64_t mask, char *fmt, ...) 9971d10453SEric Joyner { 10071d10453SEric Joyner device_t dev = ice_hw_to_dev(hw); 10171d10453SEric Joyner va_list args; 10271d10453SEric Joyner 10371d10453SEric Joyner if (!(mask & hw->debug_mask)) 10471d10453SEric Joyner return; 10571d10453SEric Joyner 10671d10453SEric Joyner device_print_prettyname(dev); 10771d10453SEric Joyner va_start(args, fmt); 10871d10453SEric Joyner vprintf(fmt, args); 10971d10453SEric Joyner va_end(args); 11071d10453SEric Joyner } 11171d10453SEric Joyner 11271d10453SEric Joyner /** 11371d10453SEric Joyner * ice_debug_array - Format and print an array of values to the console 11471d10453SEric Joyner * @hw: private hardware structure 11571d10453SEric Joyner * @mask: the debug message type 11671d10453SEric Joyner * @rowsize: preferred number of rows to use 11771d10453SEric Joyner * @groupsize: preferred size in bytes to print each chunk 11871d10453SEric Joyner * @buf: the array buffer to print 11971d10453SEric Joyner * @len: size of the array buffer 12071d10453SEric Joyner * 12171d10453SEric Joyner * Format the given array as a series of uint8_t values with hexadecimal 12271d10453SEric Joyner * notation and log the contents to the console log. 12371d10453SEric Joyner * 12471d10453SEric Joyner * TODO: Currently only supports a group size of 1, due to the way hexdump is 12571d10453SEric Joyner * implemented. 12671d10453SEric Joyner */ 12771d10453SEric Joyner void 12871d10453SEric Joyner ice_debug_array(struct ice_hw *hw, uint64_t mask, uint32_t rowsize, 12971d10453SEric Joyner uint32_t __unused groupsize, uint8_t *buf, size_t len) 13071d10453SEric Joyner { 13171d10453SEric Joyner device_t dev = ice_hw_to_dev(hw); 13271d10453SEric Joyner char prettyname[20]; 13371d10453SEric Joyner 13471d10453SEric Joyner if (!(mask & hw->debug_mask)) 13571d10453SEric Joyner return; 13671d10453SEric Joyner 13771d10453SEric Joyner /* Format the device header to a string */ 13871d10453SEric Joyner snprintf(prettyname, sizeof(prettyname), "%s: ", device_get_nameunit(dev)); 13971d10453SEric Joyner 14071d10453SEric Joyner /* Make sure the row-size isn't too large */ 14171d10453SEric Joyner if (rowsize > 0xFF) 14271d10453SEric Joyner rowsize = 0xFF; 14371d10453SEric Joyner 14471d10453SEric Joyner hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize); 14571d10453SEric Joyner } 14671d10453SEric Joyner 14771d10453SEric Joyner /** 14856429daeSEric Joyner * ice_info_fwlog - Format and print an array of values to the console 14956429daeSEric Joyner * @hw: private hardware structure 15056429daeSEric Joyner * @rowsize: preferred number of rows to use 15156429daeSEric Joyner * @groupsize: preferred size in bytes to print each chunk 15256429daeSEric Joyner * @buf: the array buffer to print 15356429daeSEric Joyner * @len: size of the array buffer 15456429daeSEric Joyner * 15556429daeSEric Joyner * Format the given array as a series of uint8_t values with hexadecimal 15656429daeSEric Joyner * notation and log the contents to the console log. This variation is 15756429daeSEric Joyner * specific to firmware logging. 15856429daeSEric Joyner * 15956429daeSEric Joyner * TODO: Currently only supports a group size of 1, due to the way hexdump is 16056429daeSEric Joyner * implemented. 16156429daeSEric Joyner */ 16256429daeSEric Joyner void 16356429daeSEric Joyner ice_info_fwlog(struct ice_hw *hw, uint32_t rowsize, uint32_t __unused groupsize, 16456429daeSEric Joyner uint8_t *buf, size_t len) 16556429daeSEric Joyner { 16656429daeSEric Joyner device_t dev = ice_hw_to_dev(hw); 16756429daeSEric Joyner char prettyname[20]; 16856429daeSEric Joyner 16956429daeSEric Joyner if (!ice_fwlog_supported(hw)) 17056429daeSEric Joyner return; 17156429daeSEric Joyner 17256429daeSEric Joyner /* Format the device header to a string */ 17356429daeSEric Joyner snprintf(prettyname, sizeof(prettyname), "%s: FWLOG: ", 17456429daeSEric Joyner device_get_nameunit(dev)); 17556429daeSEric Joyner 17656429daeSEric Joyner /* Make sure the row-size isn't too large */ 17756429daeSEric Joyner if (rowsize > 0xFF) 17856429daeSEric Joyner rowsize = 0xFF; 17956429daeSEric Joyner 18056429daeSEric Joyner hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize); 18156429daeSEric Joyner } 18256429daeSEric Joyner 18356429daeSEric Joyner /** 18471d10453SEric Joyner * rd32 - Read a 32bit hardware register value 18571d10453SEric Joyner * @hw: the private hardware structure 18671d10453SEric Joyner * @reg: register address to read 18771d10453SEric Joyner * 18871d10453SEric Joyner * Read the specified 32bit register value from BAR0 and return its contents. 18971d10453SEric Joyner */ 19071d10453SEric Joyner uint32_t 19171d10453SEric Joyner rd32(struct ice_hw *hw, uint32_t reg) 19271d10453SEric Joyner { 19371d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 19471d10453SEric Joyner 19571d10453SEric Joyner return bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg); 19671d10453SEric Joyner } 19771d10453SEric Joyner 19871d10453SEric Joyner /** 19971d10453SEric Joyner * rd64 - Read a 64bit hardware register value 20071d10453SEric Joyner * @hw: the private hardware structure 20171d10453SEric Joyner * @reg: register address to read 20271d10453SEric Joyner * 20371d10453SEric Joyner * Read the specified 64bit register value from BAR0 and return its contents. 20471d10453SEric Joyner * 20571d10453SEric Joyner * @pre For 32-bit builds, assumes that the 64bit register read can be 20671d10453SEric Joyner * safely broken up into two 32-bit register reads. 20771d10453SEric Joyner */ 20871d10453SEric Joyner uint64_t 20971d10453SEric Joyner rd64(struct ice_hw *hw, uint32_t reg) 21071d10453SEric Joyner { 21171d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 21271d10453SEric Joyner uint64_t data; 21371d10453SEric Joyner 21471d10453SEric Joyner #ifdef __amd64__ 21571d10453SEric Joyner data = bus_space_read_8(sc->bar0.tag, sc->bar0.handle, reg); 21671d10453SEric Joyner #else 21771d10453SEric Joyner /* 21871d10453SEric Joyner * bus_space_read_8 isn't supported on 32bit platforms, so we fall 21971d10453SEric Joyner * back to using two bus_space_read_4 calls. 22071d10453SEric Joyner */ 22171d10453SEric Joyner data = bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg); 22271d10453SEric Joyner data |= ((uint64_t)bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg + 4)) << 32; 22371d10453SEric Joyner #endif 22471d10453SEric Joyner 22571d10453SEric Joyner return data; 22671d10453SEric Joyner } 22771d10453SEric Joyner 22871d10453SEric Joyner /** 22971d10453SEric Joyner * wr32 - Write a 32bit hardware register 23071d10453SEric Joyner * @hw: the private hardware structure 23171d10453SEric Joyner * @reg: the register address to write to 23271d10453SEric Joyner * @val: the 32bit value to write 23371d10453SEric Joyner * 23471d10453SEric Joyner * Write the specified 32bit value to a register address in BAR0. 23571d10453SEric Joyner */ 23671d10453SEric Joyner void 23771d10453SEric Joyner wr32(struct ice_hw *hw, uint32_t reg, uint32_t val) 23871d10453SEric Joyner { 23971d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 24071d10453SEric Joyner 24171d10453SEric Joyner bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg, val); 24271d10453SEric Joyner } 24371d10453SEric Joyner 24471d10453SEric Joyner /** 24571d10453SEric Joyner * wr64 - Write a 64bit hardware register 24671d10453SEric Joyner * @hw: the private hardware structure 24771d10453SEric Joyner * @reg: the register address to write to 24871d10453SEric Joyner * @val: the 64bit value to write 24971d10453SEric Joyner * 25071d10453SEric Joyner * Write the specified 64bit value to a register address in BAR0. 25171d10453SEric Joyner * 25271d10453SEric Joyner * @pre For 32-bit builds, assumes that the 64bit register write can be safely 25371d10453SEric Joyner * broken up into two 32-bit register writes. 25471d10453SEric Joyner */ 25571d10453SEric Joyner void 25671d10453SEric Joyner wr64(struct ice_hw *hw, uint32_t reg, uint64_t val) 25771d10453SEric Joyner { 25871d10453SEric Joyner struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 25971d10453SEric Joyner 26071d10453SEric Joyner #ifdef __amd64__ 26171d10453SEric Joyner bus_space_write_8(sc->bar0.tag, sc->bar0.handle, reg, val); 26271d10453SEric Joyner #else 26371d10453SEric Joyner uint32_t lo_val, hi_val; 26471d10453SEric Joyner 26571d10453SEric Joyner /* 26671d10453SEric Joyner * bus_space_write_8 isn't supported on 32bit platforms, so we fall 26771d10453SEric Joyner * back to using two bus_space_write_4 calls. 26871d10453SEric Joyner */ 26971d10453SEric Joyner lo_val = (uint32_t)val; 27071d10453SEric Joyner hi_val = (uint32_t)(val >> 32); 27171d10453SEric Joyner bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg, lo_val); 27271d10453SEric Joyner bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg + 4, hi_val); 27371d10453SEric Joyner #endif 27471d10453SEric Joyner } 27571d10453SEric Joyner 27671d10453SEric Joyner /** 27771d10453SEric Joyner * ice_usec_delay - Delay for the specified number of microseconds 27871d10453SEric Joyner * @time: microseconds to delay 27971d10453SEric Joyner * @sleep: if true, sleep where possible 28071d10453SEric Joyner * 28171d10453SEric Joyner * If sleep is true, and if the current thread is allowed to sleep, pause so 28271d10453SEric Joyner * that another thread can execute. Otherwise, use DELAY to spin the thread 28371d10453SEric Joyner * instead. 28471d10453SEric Joyner */ 28571d10453SEric Joyner void 28671d10453SEric Joyner ice_usec_delay(uint32_t time, bool sleep) 28771d10453SEric Joyner { 28871d10453SEric Joyner if (sleep && THREAD_CAN_SLEEP()) 28971d10453SEric Joyner pause("ice_usec_delay", USEC_2_TICKS(time)); 29071d10453SEric Joyner else 29171d10453SEric Joyner DELAY(time); 29271d10453SEric Joyner } 29371d10453SEric Joyner 29471d10453SEric Joyner /** 29571d10453SEric Joyner * ice_msec_delay - Delay for the specified number of milliseconds 29671d10453SEric Joyner * @time: milliseconds to delay 29771d10453SEric Joyner * @sleep: if true, sleep where possible 29871d10453SEric Joyner * 29971d10453SEric Joyner * If sleep is true, and if the current thread is allowed to sleep, pause so 30071d10453SEric Joyner * that another thread can execute. Otherwise, use DELAY to spin the thread 30171d10453SEric Joyner * instead. 30271d10453SEric Joyner */ 30371d10453SEric Joyner void 30471d10453SEric Joyner ice_msec_delay(uint32_t time, bool sleep) 30571d10453SEric Joyner { 30671d10453SEric Joyner if (sleep && THREAD_CAN_SLEEP()) 30771d10453SEric Joyner pause("ice_msec_delay", MSEC_2_TICKS(time)); 30871d10453SEric Joyner else 30971d10453SEric Joyner DELAY(time * 1000); 31071d10453SEric Joyner } 31171d10453SEric Joyner 31271d10453SEric Joyner /** 31371d10453SEric Joyner * ice_msec_pause - pause (sleep) the thread for a time in milliseconds 31471d10453SEric Joyner * @time: milliseconds to sleep 31571d10453SEric Joyner * 31671d10453SEric Joyner * Wrapper for ice_msec_delay with sleep set to true. 31771d10453SEric Joyner */ 31871d10453SEric Joyner void 31971d10453SEric Joyner ice_msec_pause(uint32_t time) 32071d10453SEric Joyner { 32171d10453SEric Joyner ice_msec_delay(time, true); 32271d10453SEric Joyner } 32371d10453SEric Joyner 32471d10453SEric Joyner /** 32571d10453SEric Joyner * ice_msec_spin - Spin the thread for a time in milliseconds 32671d10453SEric Joyner * @time: milliseconds to delay 32771d10453SEric Joyner * 32871d10453SEric Joyner * Wrapper for ice_msec_delay with sleep sent to false. 32971d10453SEric Joyner */ 33071d10453SEric Joyner void 33171d10453SEric Joyner ice_msec_spin(uint32_t time) 33271d10453SEric Joyner { 33371d10453SEric Joyner ice_msec_delay(time, false); 33471d10453SEric Joyner } 33571d10453SEric Joyner 33671d10453SEric Joyner /******************************************************************** 33771d10453SEric Joyner * Manage DMA'able memory. 33871d10453SEric Joyner *******************************************************************/ 33971d10453SEric Joyner 34071d10453SEric Joyner /** 34171d10453SEric Joyner * ice_dmamap_cb - Callback function DMA maps 34271d10453SEric Joyner * @arg: pointer to return the segment address 34371d10453SEric Joyner * @segs: the segments array 34471d10453SEric Joyner * @nseg: number of segments in the array 34571d10453SEric Joyner * @error: error code 34671d10453SEric Joyner * 34771d10453SEric Joyner * Callback used by the bus DMA code to obtain the segment address. 34871d10453SEric Joyner */ 34971d10453SEric Joyner static void 35071d10453SEric Joyner ice_dmamap_cb(void *arg, bus_dma_segment_t * segs, int __unused nseg, int error) 35171d10453SEric Joyner { 35271d10453SEric Joyner if (error) 35371d10453SEric Joyner return; 35471d10453SEric Joyner *(bus_addr_t *) arg = segs->ds_addr; 35571d10453SEric Joyner return; 35671d10453SEric Joyner } 35771d10453SEric Joyner 35871d10453SEric Joyner /** 35971d10453SEric Joyner * ice_alloc_dma_mem - Request OS to allocate DMA memory 36071d10453SEric Joyner * @hw: private hardware structure 36171d10453SEric Joyner * @mem: structure defining the DMA memory request 36271d10453SEric Joyner * @size: the allocation size 36371d10453SEric Joyner * 36471d10453SEric Joyner * Allocates some memory for DMA use. Use the FreeBSD bus DMA interface to 36571d10453SEric Joyner * track this memory using a bus DMA tag and map. 36671d10453SEric Joyner * 36771d10453SEric Joyner * Returns a pointer to the DMA memory address. 36871d10453SEric Joyner */ 36971d10453SEric Joyner void * 37071d10453SEric Joyner ice_alloc_dma_mem(struct ice_hw *hw, struct ice_dma_mem *mem, u64 size) 37171d10453SEric Joyner { 37271d10453SEric Joyner device_t dev = ice_hw_to_dev(hw); 37371d10453SEric Joyner int err; 37471d10453SEric Joyner 37571d10453SEric Joyner err = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 37671d10453SEric Joyner 1, 0, /* alignment, boundary */ 37771d10453SEric Joyner BUS_SPACE_MAXADDR, /* lowaddr */ 37871d10453SEric Joyner BUS_SPACE_MAXADDR, /* highaddr */ 37971d10453SEric Joyner NULL, NULL, /* filtfunc, filtfuncarg */ 38071d10453SEric Joyner size, /* maxsize */ 38171d10453SEric Joyner 1, /* nsegments */ 38271d10453SEric Joyner size, /* maxsegsz */ 38371d10453SEric Joyner BUS_DMA_ALLOCNOW, /* flags */ 38471d10453SEric Joyner NULL, /* lockfunc */ 38571d10453SEric Joyner NULL, /* lockfuncarg */ 38671d10453SEric Joyner &mem->tag); 38771d10453SEric Joyner if (err != 0) { 38871d10453SEric Joyner device_printf(dev, 38971d10453SEric Joyner "ice_alloc_dma: bus_dma_tag_create failed, " 39071d10453SEric Joyner "error %s\n", ice_err_str(err)); 39171d10453SEric Joyner goto fail_0; 39271d10453SEric Joyner } 39371d10453SEric Joyner err = bus_dmamem_alloc(mem->tag, (void **)&mem->va, 39471d10453SEric Joyner BUS_DMA_NOWAIT | BUS_DMA_ZERO, &mem->map); 39571d10453SEric Joyner if (err != 0) { 39671d10453SEric Joyner device_printf(dev, 39771d10453SEric Joyner "ice_alloc_dma: bus_dmamem_alloc failed, " 39871d10453SEric Joyner "error %s\n", ice_err_str(err)); 39971d10453SEric Joyner goto fail_1; 40071d10453SEric Joyner } 40171d10453SEric Joyner err = bus_dmamap_load(mem->tag, mem->map, mem->va, 40271d10453SEric Joyner size, 40371d10453SEric Joyner ice_dmamap_cb, 40471d10453SEric Joyner &mem->pa, 40571d10453SEric Joyner BUS_DMA_NOWAIT); 40671d10453SEric Joyner if (err != 0) { 40771d10453SEric Joyner device_printf(dev, 40871d10453SEric Joyner "ice_alloc_dma: bus_dmamap_load failed, " 40971d10453SEric Joyner "error %s\n", ice_err_str(err)); 41071d10453SEric Joyner goto fail_2; 41171d10453SEric Joyner } 41271d10453SEric Joyner mem->size = size; 41371d10453SEric Joyner bus_dmamap_sync(mem->tag, mem->map, 41471d10453SEric Joyner BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 41571d10453SEric Joyner return (mem->va); 41671d10453SEric Joyner fail_2: 41771d10453SEric Joyner bus_dmamem_free(mem->tag, mem->va, mem->map); 41871d10453SEric Joyner fail_1: 41971d10453SEric Joyner bus_dma_tag_destroy(mem->tag); 42071d10453SEric Joyner fail_0: 42171d10453SEric Joyner mem->map = NULL; 42271d10453SEric Joyner mem->tag = NULL; 42371d10453SEric Joyner return (NULL); 42471d10453SEric Joyner } 42571d10453SEric Joyner 42671d10453SEric Joyner /** 42771d10453SEric Joyner * ice_free_dma_mem - Free DMA memory allocated by ice_alloc_dma_mem 42871d10453SEric Joyner * @hw: the hardware private structure 42971d10453SEric Joyner * @mem: DMA memory to free 43071d10453SEric Joyner * 43171d10453SEric Joyner * Release the bus DMA tag and map, and free the DMA memory associated with 43271d10453SEric Joyner * it. 43371d10453SEric Joyner */ 43471d10453SEric Joyner void 43571d10453SEric Joyner ice_free_dma_mem(struct ice_hw __unused *hw, struct ice_dma_mem *mem) 43671d10453SEric Joyner { 43771d10453SEric Joyner bus_dmamap_sync(mem->tag, mem->map, 43871d10453SEric Joyner BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 43971d10453SEric Joyner bus_dmamap_unload(mem->tag, mem->map); 44071d10453SEric Joyner bus_dmamem_free(mem->tag, mem->va, mem->map); 44171d10453SEric Joyner bus_dma_tag_destroy(mem->tag); 44271d10453SEric Joyner mem->map = NULL; 44371d10453SEric Joyner mem->tag = NULL; 44471d10453SEric Joyner } 445