1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2023, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Intel Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /*$FreeBSD$*/ 32 33 /** 34 * @file ice_osdep.c 35 * @brief Functions used to implement OS compatibility layer 36 * 37 * Contains functions used by ice_osdep.h to implement the OS compatibility 38 * layer used by some of the hardware files. Specifically, it is for the bits 39 * of OS compatibility which don't make sense as macros or inline functions. 40 */ 41 42 #include "ice_common.h" 43 #include "ice_iflib.h" 44 #include <machine/stdarg.h> 45 #include <sys/time.h> 46 47 /** 48 * @var M_ICE_OSDEP 49 * @brief OS compatibility layer allocation type 50 * 51 * malloc(9) allocation type used by the OS compatibility layer for 52 * distinguishing allocations by this layer from those of the rest of the 53 * driver. 54 */ 55 MALLOC_DEFINE(M_ICE_OSDEP, "ice-osdep", "Intel(R) 100Gb Network Driver osdep allocations"); 56 57 /** 58 * @var ice_lock_count 59 * @brief Global count of # of ice_lock mutexes initialized 60 * 61 * A global count of the total number of times that ice_init_lock has been 62 * called. This is used to generate unique lock names for each ice_lock, to 63 * aid in witness lock checking. 64 */ 65 u16 ice_lock_count = 0; 66 67 static void ice_dmamap_cb(void *arg, bus_dma_segment_t * segs, int __unused nseg, int error); 68 69 /** 70 * ice_hw_to_dev - Given a hw private struct, find the associated device_t 71 * @hw: the hardware private structure 72 * 73 * Given a hw structure pointer, lookup the softc and extract the device 74 * pointer. Assumes that hw is embedded within the ice_softc, instead of being 75 * allocated separately, so that __containerof math will work. 76 * 77 * This can't be defined in ice_osdep.h as it depends on the complete 78 * definition of struct ice_softc. That can't be easily included in 79 * ice_osdep.h without creating circular header dependencies. 80 */ 81 device_t 82 ice_hw_to_dev(struct ice_hw *hw) { 83 struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 84 85 return sc->dev; 86 } 87 88 /** 89 * ice_debug - Log a debug message if the type is enabled 90 * @hw: device private hardware structure 91 * @mask: the debug message type 92 * @fmt: printf format specifier 93 * 94 * Check if hw->debug_mask has enabled the given message type. If so, log the 95 * message to the console using vprintf. Mimic the output of device_printf by 96 * using device_print_prettyname(). 97 */ 98 void 99 ice_debug(struct ice_hw *hw, uint64_t mask, char *fmt, ...) 100 { 101 device_t dev = ice_hw_to_dev(hw); 102 va_list args; 103 104 if (!(mask & hw->debug_mask)) 105 return; 106 107 device_print_prettyname(dev); 108 va_start(args, fmt); 109 vprintf(fmt, args); 110 va_end(args); 111 } 112 113 /** 114 * ice_debug_array - Format and print an array of values to the console 115 * @hw: private hardware structure 116 * @mask: the debug message type 117 * @rowsize: preferred number of rows to use 118 * @groupsize: preferred size in bytes to print each chunk 119 * @buf: the array buffer to print 120 * @len: size of the array buffer 121 * 122 * Format the given array as a series of uint8_t values with hexadecimal 123 * notation and log the contents to the console log. 124 * 125 * TODO: Currently only supports a group size of 1, due to the way hexdump is 126 * implemented. 127 */ 128 void 129 ice_debug_array(struct ice_hw *hw, uint64_t mask, uint32_t rowsize, 130 uint32_t __unused groupsize, uint8_t *buf, size_t len) 131 { 132 device_t dev = ice_hw_to_dev(hw); 133 char prettyname[20]; 134 135 if (!(mask & hw->debug_mask)) 136 return; 137 138 /* Format the device header to a string */ 139 snprintf(prettyname, sizeof(prettyname), "%s: ", device_get_nameunit(dev)); 140 141 /* Make sure the row-size isn't too large */ 142 if (rowsize > 0xFF) 143 rowsize = 0xFF; 144 145 hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize); 146 } 147 148 /** 149 * ice_info_fwlog - Format and print an array of values to the console 150 * @hw: private hardware structure 151 * @rowsize: preferred number of rows to use 152 * @groupsize: preferred size in bytes to print each chunk 153 * @buf: the array buffer to print 154 * @len: size of the array buffer 155 * 156 * Format the given array as a series of uint8_t values with hexadecimal 157 * notation and log the contents to the console log. This variation is 158 * specific to firmware logging. 159 * 160 * TODO: Currently only supports a group size of 1, due to the way hexdump is 161 * implemented. 162 */ 163 void 164 ice_info_fwlog(struct ice_hw *hw, uint32_t rowsize, uint32_t __unused groupsize, 165 uint8_t *buf, size_t len) 166 { 167 device_t dev = ice_hw_to_dev(hw); 168 char prettyname[20]; 169 170 if (!ice_fwlog_supported(hw)) 171 return; 172 173 /* Format the device header to a string */ 174 snprintf(prettyname, sizeof(prettyname), "%s: FWLOG: ", 175 device_get_nameunit(dev)); 176 177 /* Make sure the row-size isn't too large */ 178 if (rowsize > 0xFF) 179 rowsize = 0xFF; 180 181 hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize); 182 } 183 184 /** 185 * rd32 - Read a 32bit hardware register value 186 * @hw: the private hardware structure 187 * @reg: register address to read 188 * 189 * Read the specified 32bit register value from BAR0 and return its contents. 190 */ 191 uint32_t 192 rd32(struct ice_hw *hw, uint32_t reg) 193 { 194 struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 195 196 return bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg); 197 } 198 199 /** 200 * rd64 - Read a 64bit hardware register value 201 * @hw: the private hardware structure 202 * @reg: register address to read 203 * 204 * Read the specified 64bit register value from BAR0 and return its contents. 205 * 206 * @pre For 32-bit builds, assumes that the 64bit register read can be 207 * safely broken up into two 32-bit register reads. 208 */ 209 uint64_t 210 rd64(struct ice_hw *hw, uint32_t reg) 211 { 212 struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 213 uint64_t data; 214 215 #ifdef __amd64__ 216 data = bus_space_read_8(sc->bar0.tag, sc->bar0.handle, reg); 217 #else 218 /* 219 * bus_space_read_8 isn't supported on 32bit platforms, so we fall 220 * back to using two bus_space_read_4 calls. 221 */ 222 data = bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg); 223 data |= ((uint64_t)bus_space_read_4(sc->bar0.tag, sc->bar0.handle, reg + 4)) << 32; 224 #endif 225 226 return data; 227 } 228 229 /** 230 * wr32 - Write a 32bit hardware register 231 * @hw: the private hardware structure 232 * @reg: the register address to write to 233 * @val: the 32bit value to write 234 * 235 * Write the specified 32bit value to a register address in BAR0. 236 */ 237 void 238 wr32(struct ice_hw *hw, uint32_t reg, uint32_t val) 239 { 240 struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 241 242 bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg, val); 243 } 244 245 /** 246 * wr64 - Write a 64bit hardware register 247 * @hw: the private hardware structure 248 * @reg: the register address to write to 249 * @val: the 64bit value to write 250 * 251 * Write the specified 64bit value to a register address in BAR0. 252 * 253 * @pre For 32-bit builds, assumes that the 64bit register write can be safely 254 * broken up into two 32-bit register writes. 255 */ 256 void 257 wr64(struct ice_hw *hw, uint32_t reg, uint64_t val) 258 { 259 struct ice_softc *sc = __containerof(hw, struct ice_softc, hw); 260 261 #ifdef __amd64__ 262 bus_space_write_8(sc->bar0.tag, sc->bar0.handle, reg, val); 263 #else 264 uint32_t lo_val, hi_val; 265 266 /* 267 * bus_space_write_8 isn't supported on 32bit platforms, so we fall 268 * back to using two bus_space_write_4 calls. 269 */ 270 lo_val = (uint32_t)val; 271 hi_val = (uint32_t)(val >> 32); 272 bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg, lo_val); 273 bus_space_write_4(sc->bar0.tag, sc->bar0.handle, reg + 4, hi_val); 274 #endif 275 } 276 277 /** 278 * ice_usec_delay - Delay for the specified number of microseconds 279 * @time: microseconds to delay 280 * @sleep: if true, sleep where possible 281 * 282 * If sleep is true, and if the current thread is allowed to sleep, pause so 283 * that another thread can execute. Otherwise, use DELAY to spin the thread 284 * instead. 285 */ 286 void 287 ice_usec_delay(uint32_t time, bool sleep) 288 { 289 if (sleep && THREAD_CAN_SLEEP()) 290 pause("ice_usec_delay", USEC_2_TICKS(time)); 291 else 292 DELAY(time); 293 } 294 295 /** 296 * ice_msec_delay - Delay for the specified number of milliseconds 297 * @time: milliseconds to delay 298 * @sleep: if true, sleep where possible 299 * 300 * If sleep is true, and if the current thread is allowed to sleep, pause so 301 * that another thread can execute. Otherwise, use DELAY to spin the thread 302 * instead. 303 */ 304 void 305 ice_msec_delay(uint32_t time, bool sleep) 306 { 307 if (sleep && THREAD_CAN_SLEEP()) 308 pause("ice_msec_delay", MSEC_2_TICKS(time)); 309 else 310 DELAY(time * 1000); 311 } 312 313 /** 314 * ice_msec_pause - pause (sleep) the thread for a time in milliseconds 315 * @time: milliseconds to sleep 316 * 317 * Wrapper for ice_msec_delay with sleep set to true. 318 */ 319 void 320 ice_msec_pause(uint32_t time) 321 { 322 ice_msec_delay(time, true); 323 } 324 325 /** 326 * ice_msec_spin - Spin the thread for a time in milliseconds 327 * @time: milliseconds to delay 328 * 329 * Wrapper for ice_msec_delay with sleep sent to false. 330 */ 331 void 332 ice_msec_spin(uint32_t time) 333 { 334 ice_msec_delay(time, false); 335 } 336 337 /******************************************************************** 338 * Manage DMA'able memory. 339 *******************************************************************/ 340 341 /** 342 * ice_dmamap_cb - Callback function DMA maps 343 * @arg: pointer to return the segment address 344 * @segs: the segments array 345 * @nseg: number of segments in the array 346 * @error: error code 347 * 348 * Callback used by the bus DMA code to obtain the segment address. 349 */ 350 static void 351 ice_dmamap_cb(void *arg, bus_dma_segment_t * segs, int __unused nseg, int error) 352 { 353 if (error) 354 return; 355 *(bus_addr_t *) arg = segs->ds_addr; 356 return; 357 } 358 359 /** 360 * ice_alloc_dma_mem - Request OS to allocate DMA memory 361 * @hw: private hardware structure 362 * @mem: structure defining the DMA memory request 363 * @size: the allocation size 364 * 365 * Allocates some memory for DMA use. Use the FreeBSD bus DMA interface to 366 * track this memory using a bus DMA tag and map. 367 * 368 * Returns a pointer to the DMA memory address. 369 */ 370 void * 371 ice_alloc_dma_mem(struct ice_hw *hw, struct ice_dma_mem *mem, u64 size) 372 { 373 device_t dev = ice_hw_to_dev(hw); 374 int err; 375 376 err = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 377 1, 0, /* alignment, boundary */ 378 BUS_SPACE_MAXADDR, /* lowaddr */ 379 BUS_SPACE_MAXADDR, /* highaddr */ 380 NULL, NULL, /* filtfunc, filtfuncarg */ 381 size, /* maxsize */ 382 1, /* nsegments */ 383 size, /* maxsegsz */ 384 BUS_DMA_ALLOCNOW, /* flags */ 385 NULL, /* lockfunc */ 386 NULL, /* lockfuncarg */ 387 &mem->tag); 388 if (err != 0) { 389 device_printf(dev, 390 "ice_alloc_dma: bus_dma_tag_create failed, " 391 "error %s\n", ice_err_str(err)); 392 goto fail_0; 393 } 394 err = bus_dmamem_alloc(mem->tag, (void **)&mem->va, 395 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &mem->map); 396 if (err != 0) { 397 device_printf(dev, 398 "ice_alloc_dma: bus_dmamem_alloc failed, " 399 "error %s\n", ice_err_str(err)); 400 goto fail_1; 401 } 402 err = bus_dmamap_load(mem->tag, mem->map, mem->va, 403 size, 404 ice_dmamap_cb, 405 &mem->pa, 406 BUS_DMA_NOWAIT); 407 if (err != 0) { 408 device_printf(dev, 409 "ice_alloc_dma: bus_dmamap_load failed, " 410 "error %s\n", ice_err_str(err)); 411 goto fail_2; 412 } 413 mem->size = size; 414 bus_dmamap_sync(mem->tag, mem->map, 415 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 416 return (mem->va); 417 fail_2: 418 bus_dmamem_free(mem->tag, mem->va, mem->map); 419 fail_1: 420 bus_dma_tag_destroy(mem->tag); 421 fail_0: 422 mem->map = NULL; 423 mem->tag = NULL; 424 return (NULL); 425 } 426 427 /** 428 * ice_free_dma_mem - Free DMA memory allocated by ice_alloc_dma_mem 429 * @hw: the hardware private structure 430 * @mem: DMA memory to free 431 * 432 * Release the bus DMA tag and map, and free the DMA memory associated with 433 * it. 434 */ 435 void 436 ice_free_dma_mem(struct ice_hw __unused *hw, struct ice_dma_mem *mem) 437 { 438 bus_dmamap_sync(mem->tag, mem->map, 439 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 440 bus_dmamap_unload(mem->tag, mem->map); 441 bus_dmamem_free(mem->tag, mem->va, mem->map); 442 bus_dma_tag_destroy(mem->tag); 443 mem->map = NULL; 444 mem->tag = NULL; 445 } 446