xref: /freebsd/sys/dev/ice/ice_osdep.c (revision 71d10453)
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