xref: /freebsd/sys/dev/ice/ice_osdep.c (revision 015f8cc5)
171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2015f8cc5SEric 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
ice_hw_to_dev(struct ice_hw * hw)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
ice_debug(struct ice_hw * hw,uint64_t mask,char * fmt,...)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
ice_debug_array(struct ice_hw * hw,uint64_t mask,uint32_t rowsize,uint32_t __unused groupsize,uint8_t * buf,size_t len)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
ice_info_fwlog(struct ice_hw * hw,uint32_t rowsize,uint32_t __unused groupsize,uint8_t * buf,size_t len)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
rd32(struct ice_hw * hw,uint32_t reg)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
rd64(struct ice_hw * hw,uint32_t reg)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
wr32(struct ice_hw * hw,uint32_t reg,uint32_t val)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
wr64(struct ice_hw * hw,uint32_t reg,uint64_t val)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
ice_usec_delay(uint32_t time,bool sleep)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
ice_msec_delay(uint32_t time,bool sleep)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
ice_msec_pause(uint32_t time)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
ice_msec_spin(uint32_t time)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
ice_dmamap_cb(void * arg,bus_dma_segment_t * segs,int __unused nseg,int error)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 *
ice_alloc_dma_mem(struct ice_hw * hw,struct ice_dma_mem * mem,u64 size)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
ice_free_dma_mem(struct ice_hw __unused * hw,struct ice_dma_mem * mem)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