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