1 /*- 2 * Copyright (c) 2017 Broadcom. All rights reserved. 3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 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 notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * 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 HOLDER 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 32 /** 33 * @file 34 * bsd specific headers common to the driver 35 */ 36 37 #ifndef _OCS_OS_H 38 #define _OCS_OS_H 39 40 /*************************************************************************** 41 * OS specific includes 42 */ 43 #include "opt_stack.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/malloc.h> 48 #include <sys/kernel.h> 49 #include <sys/module.h> 50 #include <sys/bus.h> 51 #include <sys/rman.h> 52 #include <sys/endian.h> 53 #include <sys/stddef.h> 54 #include <sys/lock.h> 55 #include <sys/mutex.h> 56 #include <sys/taskqueue.h> 57 #include <sys/bitstring.h> 58 #include <sys/stack.h> 59 60 #include <machine/atomic.h> 61 #include <machine/bus.h> 62 #include <machine/stdarg.h> 63 64 #include <dev/pci/pcivar.h> 65 66 #include <sys/sema.h> 67 #include <sys/time.h> 68 69 #include <sys/proc.h> 70 #include <sys/kthread.h> 71 #include <sys/unistd.h> 72 #include <sys/sched.h> 73 74 #include <sys/conf.h> 75 #include <sys/sysctl.h> 76 #include <sys/ioccom.h> 77 #include <sys/ctype.h> 78 79 #include <sys/linker.h> /* for debug of memory allocations */ 80 81 /* OCS_OS_MAX_ISR_TIME_MSEC - maximum time driver code should spend in an interrupt 82 * or kernel thread context without yielding 83 */ 84 #define OCS_OS_MAX_ISR_TIME_MSEC 1000 85 86 /* BSD driver specific definitions */ 87 88 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 89 90 #define OCS_MAX_LUN 512 91 #define OCS_NUM_UNSOLICITED_FRAMES 1024 92 93 #define OCS_MAX_DOMAINS 1 94 #define OCS_MAX_REMOTE_NODES 2048 95 #define OCS_MAX_TARGETS 1024 96 #define OCS_MAX_INITIATORS 1024 97 /** Reserve this number of IO for each intiator to return FULL/BUSY status */ 98 #define OCS_RSVD_INI_IO 8 99 100 #define OCS_MIN_DMA_ALIGNMENT 16 101 #define OCS_MAX_DMA_ALLOC (64*1024) /* maximum DMA allocation that is expected to reliably succeed */ 102 103 /* 104 * Macros used to size the CQ hash table. We want to round up to the next 105 * power of 2 for the hash. 106 */ 107 #define B2(x) ( (x) | ( (x) >> 1) ) 108 #define B4(x) ( B2(x) | ( B2(x) >> 2) ) 109 #define B8(x) ( B4(x) | ( B4(x) >> 4) ) 110 #define B16(x) ( B8(x) | ( B8(x) >> 8) ) 111 #define B32(x) (B16(x) | (B16(x) >>16) ) 112 #define B32_NEXT_POWER_OF_2(x) (B32((x)-1) + 1) 113 114 /* 115 * likely/unlikely - branch prediction hint 116 */ 117 #define likely(x) __builtin_expect(!!(x), 1) 118 #define unlikely(x) __builtin_expect(!!(x), 0) 119 120 /*************************************************************************** 121 * OS abstraction 122 */ 123 124 /** 125 * @brief Min/Max macros 126 * 127 */ 128 #define OCS_MAX(x, y) ((x) > (y) ? (x) : (y)) 129 #define OCS_MIN(x, y) ((x) < (y) ? (x) : (y)) 130 131 #define PRIX64 "lX" 132 #define PRIx64 "lx" 133 #define PRId64 "ld" 134 #define PRIu64 "lu" 135 136 /** 137 * Enable optional features 138 * - OCS_INCLUDE_DEBUG include low-level SLI debug support 139 */ 140 #define OCS_INCLUDE_DEBUG 141 142 /** 143 * @brief Set the Nth bit 144 * 145 * @todo move to a private file used internally? 146 */ 147 #ifndef BIT 148 #define BIT(n) (1U << (n)) 149 #endif 150 151 /*************************************************************************** 152 * Platform specific operations 153 */ 154 155 typedef struct ocs_softc ocs_t; 156 157 /** 158 * @ingroup os 159 * @typedef ocs_os_handle_t 160 * @brief OS specific handle or driver context 161 * 162 * This can be anything from a void * to some other OS specific type. The lower 163 * layers make no assumption about its value and pass it back as the first 164 * parameter to most OS functions. 165 */ 166 typedef ocs_t * ocs_os_handle_t; 167 168 /** 169 * @ingroup os 170 * @brief return the lower 32-bits of a bus address 171 * 172 * @param addr Physical or bus address to convert 173 * @return lower 32-bits of a bus address 174 * 175 * @note this may be a good cadidate for an inline or macro 176 */ 177 static inline uint32_t ocs_addr32_lo(uintptr_t addr) 178 { 179 #if defined(__LP64__) 180 return (uint32_t)(addr & 0xffffffffUL); 181 #else 182 return addr; 183 #endif 184 } 185 186 /** 187 * @ingroup os 188 * @brief return the upper 32-bits of a bus address 189 * 190 * @param addr Physical or bus address to convert 191 * @return upper 32-bits of a bus address 192 * 193 * @note this may be a good cadidate for an inline or macro 194 */ 195 static inline uint32_t ocs_addr32_hi(uintptr_t addr) 196 { 197 #if defined(__LP64__) 198 return (uint32_t)(addr >> 32); 199 #else 200 return 0; 201 #endif 202 } 203 204 /** 205 * @ingroup os 206 * @brief return the log2(val) 207 * 208 * @param val number to use (assumed to be exact power of 2) 209 * 210 * @return log base 2 of val 211 */ 212 static inline uint32_t ocs_lg2(uint32_t val) 213 { 214 #if defined(__GNUC__) 215 /* 216 * clz = "count leading zero's" 217 * 218 * Assuming val is an exact power of 2, the most significant bit 219 * will be the log base 2 of val 220 */ 221 return 31 - __builtin_clz(val); 222 #else 223 #error You need to provide a non-GCC version of this function 224 #endif 225 } 226 227 /** 228 * @ingroup os 229 * @brief optimization barrier 230 * 231 * Optimization barrier. Prevents compiler re-ordering 232 * instructions across barrier. 233 * 234 * @return none 235 */ 236 #define ocs_barrier() __asm __volatile("" : : : "memory"); 237 238 /** 239 * @ingroup os 240 * @brief convert a big endian 32 bit value to the host's native format 241 * 242 * @param val 32 bit big endian value 243 * 244 * @return value converted to the host's native endianness 245 */ 246 #define ocs_be32toh(val) be32toh(val) 247 248 /** 249 * @ingroup os 250 * @brief convert a 32 bit value from the host's native format to big endian 251 * 252 * @param val 32 bit native endian value 253 * 254 * @return value converted to big endian 255 */ 256 #define ocs_htobe32(val) htobe32(val) 257 258 /** 259 * @ingroup os 260 * @brief convert a 16 bit value from the host's native format to big endian 261 * 262 * @param v 16 bit native endian value 263 * 264 * @return value converted to big endian 265 */ 266 #define ocs_htobe16(v) htobe16(v) 267 #define ocs_be16toh(v) be16toh(v) 268 269 #define ocs_htobe64(v) htobe64(v) 270 #define ocs_be64toh(v) be64toh(v) 271 272 /** 273 * @ingroup os 274 * @brief Delay execution by the given number of micro-seconds 275 * 276 * @param usec number of micro-seconds to "busy-wait" 277 * 278 * @note The value of usec may be greater than 1,000,000 279 */ 280 #define ocs_udelay(usec) DELAY(usec) 281 282 /** 283 * @ingroup os 284 * @brief Delay execution by the given number of milli-seconds 285 * 286 * @param msec number of milli-seconds to "busy-wait" 287 * 288 * @note The value of usec may be greater than 1,000,000 289 */ 290 #define ocs_msleep(msec) ocs_udelay((msec)*1000) 291 292 /** 293 * @ingroup os 294 * @brief Get time of day in msec 295 * 296 * @return time of day in msec 297 */ 298 static inline time_t 299 ocs_msectime(void) 300 { 301 struct timeval tv; 302 303 getmicrotime(&tv); 304 return (tv.tv_sec*1000) + (tv.tv_usec / 1000); 305 } 306 307 /** 308 * @ingroup os 309 * @brief Copy length number of bytes from the source to destination address 310 * 311 * @param d pointer to the destination memory 312 * @param s pointer to the source memory 313 * @param l number of bytes to copy 314 * 315 * @return original value of dst pointer 316 */ 317 #define ocs_memcpy(d, s, l) memcpy(d, s, l) 318 319 #define ocs_strlen(s) strlen(s) 320 #define ocs_strcpy(d,s) strcpy(d, s) 321 #define ocs_strncpy(d,s, n) strncpy(d, s, n) 322 #define ocs_strcat(d, s) strcat(d, s) 323 #define ocs_strtoul(s,ep,b) strtoul(s,ep,b) 324 #define ocs_strtoull(s,ep,b) ((uint64_t)strtouq(s,ep,b)) 325 #define ocs_atoi(s) strtol(s, 0, 0) 326 #define ocs_strcmp(d,s) strcmp(d,s) 327 #define ocs_strcasecmp(d,s) strcasecmp(d,s) 328 #define ocs_strncmp(d,s,n) strncmp(d,s,n) 329 #define ocs_strstr(h,n) strstr(h,n) 330 #define ocs_strsep(h, n) strsep(h, n) 331 #define ocs_strchr(s,c) strchr(s,c) 332 #define ocs_copy_from_user(dst, src, n) copyin(src, dst, n) 333 #define ocs_copy_to_user(dst, src, n) copyout(src, dst, n) 334 #define ocs_snprintf(buf, n, fmt, ...) snprintf(buf, n, fmt, ##__VA_ARGS__) 335 #define ocs_vsnprintf(buf, n, fmt, ap) vsnprintf((char*)buf, n, fmt, ap) 336 #define ocs_sscanf(buf,fmt, ...) sscanf(buf, fmt, ##__VA_ARGS__) 337 #define ocs_printf printf 338 #define ocs_isspace(c) isspace(c) 339 #define ocs_isdigit(c) isdigit(c) 340 #define ocs_isxdigit(c) isxdigit(c) 341 342 extern uint64_t ocs_get_tsc(void); 343 extern void *ocs_ioctl_preprocess(ocs_os_handle_t os, void *arg, size_t size); 344 extern int32_t ocs_ioctl_postprocess(ocs_os_handle_t os, void *arg, void *kern_ptr, size_t size); 345 extern void ocs_ioctl_free(ocs_os_handle_t os, void *kern_ptr, size_t size); 346 extern char *ocs_strdup(const char *s); 347 348 /** 349 * @ingroup os 350 * @brief Set the value of each byte in memory 351 * 352 * @param b pointer to the memory 353 * @param c value used to set memory 354 * @param l number of bytes to set 355 * 356 * @return original value of mem pointer 357 */ 358 #define ocs_memset(b, c, l) memset(b, c, l) 359 360 #define LOG_CRIT 0 361 #define LOG_ERR 1 362 #define LOG_WARN 2 363 #define LOG_INFO 3 364 #define LOG_TEST 4 365 #define LOG_DEBUG 5 366 367 extern int loglevel; 368 369 extern void _ocs_log(ocs_t *ocs, const char *func, int line, const char *fmt, ...); 370 371 #define ocs_log_crit(os, fmt, ...) ocs_log(os, LOG_CRIT, fmt, ##__VA_ARGS__); 372 #define ocs_log_err(os, fmt, ...) ocs_log(os, LOG_ERR, fmt, ##__VA_ARGS__); 373 #define ocs_log_warn(os, fmt, ...) ocs_log(os, LOG_WARN, fmt, ##__VA_ARGS__); 374 #define ocs_log_info(os, fmt, ...) ocs_log(os, LOG_INFO, fmt, ##__VA_ARGS__); 375 #define ocs_log_test(os, fmt, ...) ocs_log(os, LOG_TEST, fmt, ##__VA_ARGS__); 376 #define ocs_log_debug(os, fmt, ...) ocs_log(os, LOG_DEBUG, fmt, ##__VA_ARGS__); 377 378 #define ocs_log(os, level, fmt, ...) \ 379 do { \ 380 if (level <= loglevel) { \ 381 _ocs_log(os, __func__, __LINE__, fmt, ##__VA_ARGS__); \ 382 } \ 383 } while (0) 384 385 static inline uint32_t ocs_roundup(uint32_t x, uint32_t y) 386 { 387 return (((x + y - 1) / y) * y); 388 } 389 390 static inline uint32_t ocs_rounddown(uint32_t x, uint32_t y) 391 { 392 return ((x / y) * y); 393 } 394 395 /*************************************************************************** 396 * Memory allocation interfaces 397 */ 398 399 #define OCS_M_ZERO M_ZERO 400 #define OCS_M_NOWAIT M_NOWAIT 401 402 /** 403 * @ingroup os 404 * @brief Allocate host memory 405 * 406 * @param os OS handle 407 * @param size number of bytes to allocate 408 * @param flags additional options 409 * 410 * Flags include 411 * - OCS_M_ZERO zero memory after allocating 412 * - OCS_M_NOWAIT do not block/sleep waiting for an allocation request 413 * 414 * @return pointer to allocated memory, NULL otherwise 415 */ 416 extern void *ocs_malloc(ocs_os_handle_t os, size_t size, int32_t flags); 417 418 /** 419 * @ingroup os 420 * @brief Free host memory 421 * 422 * @param os OS handle 423 * @param addr pointer to memory 424 * @param size bytes to free 425 */ 426 extern void ocs_free(ocs_os_handle_t os, void *addr, size_t size); 427 428 /** 429 * @ingroup os 430 * @brief generic DMA memory descriptor for driver allocations 431 * 432 * Memory regions ultimately used by the hardware are described using 433 * this structure. All implementations must include the structure members 434 * defined in the first section, and they may also add their own structure 435 * members in the second section. 436 * 437 * Note that each region described by ocs_dma_s is assumed to be physically 438 * contiguous. 439 */ 440 typedef struct ocs_dma_s { 441 /* 442 * OCS layer requires the following members 443 */ 444 void *virt; /**< virtual address of the memory used by the CPU */ 445 void *alloc; /**< originally allocated virtual address used to restore virt if modified */ 446 uintptr_t phys; /**< physical or bus address of the memory used by the hardware */ 447 size_t size; /**< size in bytes of the memory */ 448 /* 449 * Implementation specific fields allowed here 450 */ 451 size_t len; /**< application specific length */ 452 bus_dma_tag_t tag; 453 bus_dmamap_t map; 454 } ocs_dma_t; 455 456 /** 457 * @ingroup os 458 * @brief Returns maximum supported DMA allocation size 459 * 460 * @param os OS specific handle or driver context 461 * @param align alignment requirement for DMA allocation 462 * 463 * Return maximum supported DMA allocation size, given alignment 464 * requirement. 465 * 466 * @return maximum supported DMA allocation size 467 */ 468 static inline uint32_t ocs_max_dma_alloc(ocs_os_handle_t os, size_t align) 469 { 470 return ~((uint32_t)0); /* no max */ 471 } 472 473 /** 474 * @ingroup os 475 * @brief Allocate a DMA capable block of memory 476 * 477 * @param os OS specific handle or driver context 478 * @param dma DMA descriptor containing results of memory allocation 479 * @param size Size in bytes of desired allocation 480 * @param align Alignment in bytes of the requested allocation 481 * 482 * @return 0 on success, non-zero otherwise 483 */ 484 extern int32_t ocs_dma_alloc(ocs_os_handle_t, ocs_dma_t *, size_t, size_t); 485 486 /** 487 * @ingroup os 488 * @brief Free a DMA capable block of memory 489 * 490 * @param os OS specific handle or driver context 491 * @param dma DMA descriptor for memory to be freed 492 * 493 * @return 0 if memory is de-allocated, non-zero otherwise 494 */ 495 extern int32_t ocs_dma_free(ocs_os_handle_t, ocs_dma_t *); 496 extern int32_t ocs_dma_copy_in(ocs_dma_t *dma, void *buffer, uint32_t buffer_length); 497 extern int32_t ocs_dma_copy_out(ocs_dma_t *dma, void *buffer, uint32_t buffer_length); 498 499 static inline int32_t ocs_dma_valid(ocs_dma_t *dma) 500 { 501 return (dma->size != 0); 502 } 503 504 /** 505 * @ingroup os 506 * @brief Synchronize the DMA buffer memory 507 * 508 * Ensures memory coherency between the CPU and device 509 * 510 * @param dma DMA descriptor of memory to synchronize 511 * @param flags Describes direction of synchronization 512 * - OCS_DMASYNC_PREREAD sync needed before hardware updates host memory 513 * - OCS_DMASYNC_PREWRITE sync needed after CPU updates host memory but before hardware can access 514 * - OCS_DMASYNC_POSTREAD sync needed after hardware updates host memory but before CPU can access 515 * - OCS_DMASYNC_POSTWRITE sync needed after hardware updates host memory 516 */ 517 extern void ocs_dma_sync(ocs_dma_t *, uint32_t); 518 519 #define OCS_DMASYNC_PREWRITE BUS_DMASYNC_PREWRITE 520 #define OCS_DMASYNC_POSTREAD BUS_DMASYNC_POSTREAD 521 522 /*************************************************************************** 523 * Locking 524 */ 525 526 /** 527 * @ingroup os 528 * @typedef ocs_lock_t 529 * @brief Define the type used implement locking 530 */ 531 #define MAX_LOCK_DESC_LEN 64 532 typedef struct ocs_lock_s { 533 struct mtx lock; 534 char name[MAX_LOCK_DESC_LEN]; 535 } ocs_lock_t; 536 537 /** 538 * @ingroup os 539 * @brief Initialize a lock 540 * 541 * @param lock lock to initialize 542 * @param name string identifier for the lock 543 */ 544 extern void ocs_lock_init(void *os, ocs_lock_t *lock, const char *name, ...); 545 546 /** 547 * @ingroup os 548 * @brief Free a previously allocated lock 549 * 550 * @param lock lock to free 551 */ 552 static inline void 553 ocs_lock_free(ocs_lock_t *lock) 554 { 555 556 if (mtx_initialized(&(lock)->lock)) { 557 mtx_assert(&(lock)->lock, MA_NOTOWNED); 558 mtx_destroy(&(lock)->lock); 559 } else { 560 panic("XXX trying to free with un-initialized mtx!?!?\n"); 561 } 562 } 563 564 /** 565 * @ingroup os 566 * @brief Acquire a lock 567 * 568 * @param lock lock to obtain 569 */ 570 static inline void 571 ocs_lock(ocs_lock_t *lock) 572 { 573 574 if (mtx_initialized(&(lock)->lock)) { 575 mtx_assert(&(lock)->lock, MA_NOTOWNED); 576 mtx_lock(&(lock)->lock); 577 } else { 578 panic("XXX trying to lock with un-initialized mtx!?!?\n"); 579 } 580 } 581 582 /** 583 * @ingroup os 584 * @brief Release a lock 585 * 586 * @param lock lock to release 587 */ 588 static inline void 589 ocs_unlock(ocs_lock_t *lock) 590 { 591 592 if (mtx_initialized(&(lock)->lock)) { 593 mtx_assert(&(lock)->lock, MA_OWNED | MA_NOTRECURSED); 594 mtx_unlock(&(lock)->lock); 595 } else { 596 panic("XXX trying to unlock with un-initialized mtx!?!?\n"); 597 } 598 } 599 600 /** 601 * @ingroup os 602 * @typedef ocs_lock_t 603 * @brief Define the type used implement recursive locking 604 */ 605 typedef struct ocs_lock_s ocs_rlock_t; 606 607 /** 608 * @ingroup os 609 * @brief Initialize a recursive lock 610 * 611 * @param ocs pointer to ocs structure 612 * @param lock lock to initialize 613 * @param name string identifier for the lock 614 */ 615 static inline void 616 ocs_rlock_init(ocs_t *ocs, ocs_rlock_t *lock, const char *name) 617 { 618 ocs_strncpy(lock->name, name, MAX_LOCK_DESC_LEN); 619 mtx_init(&(lock)->lock, lock->name, NULL, MTX_DEF | MTX_RECURSE | MTX_DUPOK); 620 } 621 622 /** 623 * @ingroup os 624 * @brief Free a previously allocated recursive lock 625 * 626 * @param lock lock to free 627 */ 628 static inline void 629 ocs_rlock_free(ocs_rlock_t *lock) 630 { 631 if (mtx_initialized(&(lock)->lock)) { 632 mtx_destroy(&(lock)->lock); 633 } else { 634 panic("XXX trying to free with un-initialized mtx!?!?\n"); 635 } 636 } 637 638 /** 639 * @brief try to acquire a recursive lock 640 * 641 * Attempt to acquire a recursive lock, return TRUE if successful 642 * 643 * @param lock pointer to recursive lock 644 * 645 * @return TRUE if lock was acquired, FALSE if not 646 */ 647 static inline int32_t 648 ocs_rlock_try(ocs_rlock_t *lock) 649 { 650 int rc = mtx_trylock(&(lock)->lock); 651 652 return rc != 0; 653 } 654 655 /** 656 * @ingroup os 657 * @brief Acquire a recursive lock 658 * 659 * @param lock lock to obtain 660 */ 661 static inline void 662 ocs_rlock_acquire(ocs_rlock_t *lock) 663 { 664 if (mtx_initialized(&(lock)->lock)) { 665 mtx_lock(&(lock)->lock); 666 } else { 667 panic("XXX trying to lock with un-initialized mtx!?!?\n"); 668 } 669 } 670 671 /** 672 * @ingroup os 673 * @brief Release a recursive lock 674 * 675 * @param lock lock to release 676 */ 677 static inline void 678 ocs_rlock_release(ocs_rlock_t *lock) 679 { 680 if (mtx_initialized(&(lock)->lock)) { 681 mtx_assert(&(lock)->lock, MA_OWNED); 682 mtx_unlock(&(lock)->lock); 683 } else { 684 panic("XXX trying to unlock with un-initialized mtx!?!?\n"); 685 } 686 } 687 688 /** 689 * @brief counting semaphore 690 * 691 * Declaration of the counting semaphore object 692 * 693 */ 694 typedef struct { 695 char name[32]; 696 struct sema sem; /**< OS counting semaphore structure */ 697 } ocs_sem_t; 698 699 #define OCS_SEM_FOREVER (-1) 700 #define OCS_SEM_TRY (0) 701 702 /** 703 * @brief Initialize a counting semaphore 704 * 705 * The semaphore is initiatlized to the value 706 * 707 * @param sem pointer to semaphore 708 * @param val initial value 709 * @param name label for the semaphore 710 * 711 * @return returns 0 for success, a negative error code value for failure. 712 */ 713 714 extern int ocs_sem_init(ocs_sem_t *sem, int val, const char *name, ...) __attribute__((format(printf, 3, 4))); 715 716 /** 717 * @brief execute a P (decrement) operation 718 * 719 * A P (decrement and block if negative) operation is performed on the semaphore. 720 * 721 * If timeout_usec is zero, the semaphore attempts one time and returns 0 if acquired. 722 * If timeout_usec is greater than zero, then the call will block until the semaphore 723 * is acquired, or a timeout occurred. If timeout_usec is less than zero, then 724 * the call will block until the semaphore is acquired. 725 * 726 * @param sem pointer to semaphore 727 * @param timeout_usec timeout in microseconds 728 * 729 * @return returns 0 for success, negative value if the semaphore was not acquired. 730 */ 731 732 static inline int 733 ocs_sem_p(ocs_sem_t *sem, int timeout_usec) 734 { 735 int32_t rc = 0; 736 737 if (timeout_usec == 0) { 738 rc = sema_trywait(&sem->sem); 739 if (rc == 0) { 740 rc = -1; 741 } 742 } else if (timeout_usec > 0) { 743 struct timeval tv; 744 uint32_t ticks; 745 746 tv.tv_sec = timeout_usec / 1000000; 747 tv.tv_usec = timeout_usec % 1000000; 748 ticks = tvtohz(&tv); 749 if (ticks == 0) { 750 ticks ++; 751 } 752 rc = sema_timedwait(&sem->sem, ticks); 753 if (rc != 0) { 754 rc = -1; 755 } 756 } else { 757 sema_wait(&sem->sem); 758 } 759 if (rc) 760 rc = -1; 761 762 return rc; 763 } 764 765 /** 766 * @brief perform a V (increment) operation on a counting semaphore 767 * 768 * The semaphore is incremented, unblocking one thread that is waiting on the 769 * sempahore 770 * 771 * @param sem pointer to the semaphore 772 * 773 * @return none 774 */ 775 776 static inline void 777 ocs_sem_v(ocs_sem_t *sem) 778 { 779 sema_post(&sem->sem); 780 } 781 782 /*************************************************************************** 783 * Bitmap 784 */ 785 786 /** 787 * @ingroup os 788 * @typedef ocs_bitmap_t 789 * @brief Define the type used implement bit-maps 790 */ 791 typedef bitstr_t ocs_bitmap_t; 792 793 /** 794 * @ingroup os 795 * @brief Allocate a bitmap 796 * 797 * @param n_bits Minimum number of entries in the bit-map 798 * 799 * @return pointer to the bit-map or NULL on error 800 */ 801 extern ocs_bitmap_t *ocs_bitmap_alloc(uint32_t n_bits); 802 803 /** 804 * @ingroup os 805 * @brief Free a bit-map 806 * 807 * @param bitmap Bit-map to free 808 */ 809 extern void ocs_bitmap_free(ocs_bitmap_t *bitmap); 810 811 /** 812 * @ingroup os 813 * @brief Find next unset bit and set it 814 * 815 * @param bitmap bit map to search 816 * @param n_bits number of bits in map 817 * 818 * @return bit position or -1 if map is full 819 */ 820 extern int32_t ocs_bitmap_find(ocs_bitmap_t *bitmap, uint32_t n_bits); 821 822 /** 823 * @ingroup os 824 * @brief search for next (un)set bit 825 * 826 * @param bitmap bit map to search 827 * @param set search for a set or unset bit 828 * @param n_bits number of bits in map 829 * 830 * @return bit position or -1 831 */ 832 extern int32_t ocs_bitmap_search(ocs_bitmap_t *bitmap, uint8_t set, uint32_t n_bits); 833 834 /** 835 * @ingroup os 836 * @brief clear the specified bit 837 * 838 * @param bitmap pointer to bit map 839 * @param bit bit number to clear 840 */ 841 extern void ocs_bitmap_clear(ocs_bitmap_t *bitmap, uint32_t bit); 842 843 extern int32_t ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len); 844 845 /*************************************************************************** 846 * Timer Routines 847 * 848 * Functions for setting, querying and canceling timers. 849 */ 850 typedef struct { 851 struct callout callout; 852 struct mtx lock; 853 854 void (*func)(void *); 855 void *data; 856 } ocs_timer_t; 857 858 /** 859 * @ingroup os 860 * @brief Initialize and set a timer 861 * 862 * @param os OS handle 863 * @param timer pointer to the structure allocated for this timer 864 * @param func the function to call when the timer expires 865 * @param data Data to pass to the provided timer function when the timer 866 * expires. 867 * @param timeout_ms the timeout in milliseconds 868 */ 869 extern int32_t ocs_setup_timer(ocs_os_handle_t os, ocs_timer_t *timer, void(*func)(void *arg), 870 void *data, uint32_t timeout_ms); 871 872 /** 873 * @ingroup os 874 * @brief Modify a timer's expiration 875 * 876 * @param timer pointer to the structure allocated for this timer 877 * @param timeout_ms the timeout in milliseconds 878 */ 879 extern int32_t ocs_mod_timer(ocs_timer_t *timer, uint32_t timeout_ms); 880 881 /** 882 * @ingroup os 883 * @brief Queries to see if a timer is pending. 884 * 885 * @param timer pointer to the structure allocated for this timer 886 * 887 * @return non-zero if the timer is pending 888 */ 889 extern int32_t ocs_timer_pending(ocs_timer_t *timer); 890 891 /** 892 * @ingroup os 893 * @brief Remove a pending timer 894 * 895 * @param timer pointer to the structure allocated for this timer 896 * expires. 897 */ 898 extern int32_t ocs_del_timer(ocs_timer_t *timer); 899 900 /*************************************************************************** 901 * Atomics 902 * 903 */ 904 905 typedef uint32_t ocs_atomic_t; 906 907 /** 908 * @ingroup os 909 * @brief initialize an atomic 910 * 911 * @param a pointer to the atomic object 912 * @param v initial value 913 * 914 * @return none 915 */ 916 #define ocs_atomic_init(a, v) ocs_atomic_set(a, v) 917 918 /** 919 * @ingroup os 920 * @brief adds an integer to an atomic value 921 * 922 * @param a pointer to the atomic object 923 * @param v value to increment 924 * 925 * @return the value of the atomic before incrementing. 926 */ 927 #define ocs_atomic_add_return(a, v) atomic_fetchadd_32(a, v) 928 929 /** 930 * @ingroup os 931 * @brief subtracts an integer to an atomic value 932 * 933 * @param a pointer to the atomic object 934 * @param v value to increment 935 * 936 * @return the value of the atomic before subtracting. 937 */ 938 #define ocs_atomic_sub_return(a, v) atomic_fetchadd_32(a, (-(v))) 939 940 /** 941 * @ingroup os 942 * @brief returns the current value of an atomic object 943 * 944 * @param a pointer to the atomic object 945 * 946 * @return the value of the atomic. 947 */ 948 #define ocs_atomic_read(a) atomic_load_acq_32(a) 949 950 /** 951 * @ingroup os 952 * @brief sets the current value of an atomic object 953 * 954 * @param a pointer to the atomic object 955 */ 956 #define ocs_atomic_set(a, v) atomic_store_rel_32(a, v) 957 958 /** 959 * @ingroup os 960 * @brief Sets atomic to 0, returns previous value 961 * 962 * @param a pointer to the atomic object 963 * 964 * @return the value of the atomic before the operation. 965 */ 966 #define ocs_atomic_read_and_clear atomic_readandclear_32(a) 967 968 /** 969 * @brief OCS thread structure 970 * 971 */ 972 973 typedef struct ocs_thread_s ocs_thread_t; 974 975 typedef int32_t (*ocs_thread_fctn)(ocs_thread_t *mythread); 976 977 struct ocs_thread_s { 978 struct thread *tcb; /*<< thread control block */ 979 ocs_thread_fctn fctn; /*<< thread function */ 980 char *name; /*<< name of thread */ 981 void *arg; /*<< pointer to thread argument */ 982 ocs_atomic_t terminate; /*<< terminate request */ 983 int32_t retval; /*<< return value */ 984 uint32_t cpu_affinity; /*<< cpu affinity */ 985 }; 986 #define OCS_THREAD_DEFAULT_STACK_SIZE_PAGES 8 987 988 /** 989 * @brief OCS thread start options 990 * 991 */ 992 993 typedef enum { 994 OCS_THREAD_RUN, /*<< run immediately */ 995 OCS_THREAD_CREATE, /*<< create and wait for start request */ 996 } ocs_thread_start_e; 997 998 extern int32_t ocs_thread_create(ocs_os_handle_t os, ocs_thread_t *thread, ocs_thread_fctn fctn, 999 const char *name, void *arg, ocs_thread_start_e start_option); 1000 extern int32_t ocs_thread_start(ocs_thread_t *thread); 1001 extern void *ocs_thread_get_arg(ocs_thread_t *mythread); 1002 extern int32_t ocs_thread_terminate(ocs_thread_t *thread); 1003 extern int32_t ocs_thread_terminate_requested(ocs_thread_t *thread); 1004 extern int32_t ocs_thread_get_retval(ocs_thread_t *thread); 1005 extern void ocs_thread_yield(ocs_thread_t *thread); 1006 extern ocs_thread_t *ocs_thread_self(void); 1007 extern int32_t ocs_thread_setcpu(ocs_thread_t *thread, uint32_t cpu); 1008 extern int32_t ocs_thread_getcpu(void); 1009 1010 /*************************************************************************** 1011 * PCI 1012 * 1013 * Several functions below refer to a "register set". This is one or 1014 * more PCI BARs that constitute a PCI address. For example, if a MMIO 1015 * region is described using both BAR[0] and BAR[1], the combination of 1016 * BARs defines register set 0. 1017 */ 1018 1019 /** 1020 * @brief tracks mapped PCI memory regions 1021 */ 1022 typedef struct ocs_pci_reg_s { 1023 uint32_t rid; 1024 struct resource *res; 1025 bus_space_tag_t btag; 1026 bus_space_handle_t bhandle; 1027 } ocs_pci_reg_t; 1028 1029 #define PCI_MAX_BAR 6 1030 #define PCI_64BIT_BAR0 0 1031 1032 #define PCI_VENDOR_EMULEX 0x10df /* Emulex */ 1033 1034 #define PCI_PRODUCT_EMULEX_OCE16001 0xe200 /* OneCore 16Gb FC (lancer) */ 1035 #define PCI_PRODUCT_EMULEX_OCE16002 0xe200 /* OneCore 16Gb FC (lancer) */ 1036 #define PCI_PRODUCT_EMULEX_LPE31004 0xe300 /* LightPulse 16Gb x 4 FC (lancer-g6) */ 1037 #define PCI_PRODUCT_EMULEX_LPE32002 0xe300 /* LightPulse 32Gb x 2 FC (lancer-g6) */ 1038 #define PCI_PRODUCT_EMULEX_LANCER_G7 0xf400 /* LightPulse 32Gb x 4 FC (lancer-g7) */ 1039 1040 #define PCI_PRODUCT_EMULEX_OCE1600_VF 0xe208 1041 #define PCI_PRODUCT_EMULEX_OCE50102 0xe260 /* OneCore FCoE (lancer) */ 1042 #define PCI_PRODUCT_EMULEX_OCE50102_VF 0xe268 1043 1044 /** 1045 * @ingroup os 1046 * @brief Get the PCI bus, device, and function values 1047 * 1048 * @param ocs OS specific handle or driver context 1049 * @param bus Pointer to location to store the bus number. 1050 * @param dev Pointer to location to store the device number. 1051 * @param func Pointer to location to store the function number. 1052 * 1053 */ 1054 extern void 1055 ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func); 1056 1057 extern ocs_t *ocs_get_instance(uint32_t index); 1058 extern uint32_t ocs_instance(void *os); 1059 1060 /** 1061 * @ingroup os 1062 * @brief Read a 32 bit value from the specified configuration register 1063 * 1064 * @param os OS specific handle or driver context 1065 * @param reg register offset 1066 * 1067 * @return The 32 bit value 1068 */ 1069 extern uint32_t ocs_config_read32(ocs_os_handle_t os, uint32_t reg); 1070 1071 /** 1072 * @ingroup os 1073 * @brief Read a 16 bit value from the specified configuration 1074 * register 1075 * 1076 * @param os OS specific handle or driver context 1077 * @param reg register offset 1078 * 1079 * @return The 16 bit value 1080 */ 1081 extern uint16_t ocs_config_read16(ocs_os_handle_t os, uint32_t reg); 1082 1083 /** 1084 * @ingroup os 1085 * @brief Read a 8 bit value from the specified configuration 1086 * register 1087 * 1088 * @param os OS specific handle or driver context 1089 * @param reg register offset 1090 * 1091 * @return The 8 bit value 1092 */ 1093 extern uint8_t ocs_config_read8(ocs_os_handle_t os, uint32_t reg); 1094 1095 /** 1096 * @ingroup os 1097 * @brief Write a 8 bit value to the specified configuration 1098 * register 1099 * 1100 * @param os OS specific handle or driver context 1101 * @param reg register offset 1102 * @param val value to write 1103 * 1104 * @return None 1105 */ 1106 extern void ocs_config_write8(ocs_os_handle_t os, uint32_t reg, uint8_t val); 1107 1108 /** 1109 * @ingroup os 1110 * @brief Write a 16 bit value to the specified configuration 1111 * register 1112 * 1113 * @param os OS specific handle or driver context 1114 * @param reg register offset 1115 * @param val value to write 1116 * 1117 * @return None 1118 */ 1119 extern void ocs_config_write16(ocs_os_handle_t os, uint32_t reg, uint16_t val); 1120 1121 /** 1122 * @ingroup os 1123 * @brief Write a 32 bit value to the specified configuration 1124 * register 1125 * 1126 * @param os OS specific handle or driver context 1127 * @param reg register offset 1128 * @param val value to write 1129 * 1130 * @return None 1131 */ 1132 extern void ocs_config_write32(ocs_os_handle_t os, uint32_t reg, uint32_t val); 1133 1134 /** 1135 * @ingroup os 1136 * @brief Read a PCI register 1137 * 1138 * @param os OS specific handle or driver context 1139 * @param rset Which "register set" to use 1140 * @param off Register offset 1141 * 1142 * @return 32 bit conents of the register 1143 */ 1144 extern uint32_t ocs_reg_read32(ocs_os_handle_t os, uint32_t rset, uint32_t off); 1145 1146 /** 1147 * @ingroup os 1148 * @brief Read a PCI register 1149 * 1150 * @param os OS specific handle or driver context 1151 * @param rset Which "register set" to use 1152 * @param off Register offset 1153 * 1154 * @return 16 bit conents of the register 1155 */ 1156 extern uint16_t ocs_reg_read16(ocs_os_handle_t os, uint32_t rset, uint32_t off); 1157 1158 /** 1159 * @ingroup os 1160 * @brief Read a PCI register 1161 * 1162 * @param os OS specific handle or driver context 1163 * @param rset Which "register set" to use 1164 * @param off Register offset 1165 * 1166 * @return 8 bit conents of the register 1167 */ 1168 extern uint8_t ocs_reg_read8(ocs_os_handle_t os, uint32_t rset, uint32_t off); 1169 1170 /** 1171 * @ingroup os 1172 * @brief Write a PCI register 1173 * 1174 * @param os OS specific handle or driver context 1175 * @param rset Which "register set" to use 1176 * @param off Register offset 1177 * @param val 32-bit value to write 1178 */ 1179 extern void ocs_reg_write32(ocs_os_handle_t os, uint32_t rset, uint32_t off, uint32_t val); 1180 1181 /** 1182 * @ingroup os 1183 * @brief Write a PCI register 1184 * 1185 * @param os OS specific handle or driver context 1186 * @param rset Which "register set" to use 1187 * @param off Register offset 1188 * @param val 16-bit value to write 1189 */ 1190 extern void ocs_reg_write16(ocs_os_handle_t os, uint32_t rset, uint32_t off, uint16_t val); 1191 1192 /** 1193 * @ingroup os 1194 * @brief Write a PCI register 1195 * 1196 * @param os OS specific handle or driver context 1197 * @param rset Which "register set" to use 1198 * @param off Register offset 1199 * @param val 8-bit value to write 1200 */ 1201 extern void ocs_reg_write8(ocs_os_handle_t os, uint32_t rset, uint32_t off, uint8_t val); 1202 1203 /** 1204 * @ingroup os 1205 * @brief Disable interrupts 1206 * 1207 * @param os OS specific handle or driver context 1208 */ 1209 extern void ocs_intr_disable(ocs_os_handle_t os); 1210 1211 /** 1212 * @ingroup os 1213 * @brief Enable interrupts 1214 * 1215 * @param os OS specific handle or driver context 1216 */ 1217 extern void ocs_intr_enable(ocs_os_handle_t os); 1218 1219 /** 1220 * @ingroup os 1221 * @brief Return model string 1222 * 1223 * @param os OS specific handle or driver context 1224 */ 1225 extern const char *ocs_pci_model(uint16_t vendor, uint16_t device); 1226 1227 extern void ocs_print_stack(void); 1228 1229 extern void ocs_abort(void) __attribute__((noreturn)); 1230 1231 /*************************************************************************** 1232 * Reference counting 1233 * 1234 */ 1235 1236 /** 1237 * @ingroup os 1238 * @brief reference counter object 1239 */ 1240 typedef void (*ocs_ref_release_t)(void *arg); 1241 typedef struct ocs_ref_s { 1242 ocs_ref_release_t release; /* release function to call */ 1243 void *arg; 1244 uint32_t count; /* ref count; no need to be atomic if we have a lock */ 1245 } ocs_ref_t; 1246 1247 /** 1248 * @ingroup os 1249 * @brief initialize given reference object 1250 * 1251 * @param ref Pointer to reference object 1252 * @param release Function to be called when count is 0. 1253 * @param arg Argument to be passed to release function. 1254 */ 1255 static inline void 1256 ocs_ref_init(ocs_ref_t *ref, ocs_ref_release_t release, void *arg) 1257 { 1258 ref->release = release; 1259 ref->arg = arg; 1260 ocs_atomic_init(&ref->count, 1); 1261 } 1262 1263 /** 1264 * @ingroup os 1265 * @brief Return reference count value 1266 * 1267 * @param ref Pointer to reference object 1268 * 1269 * @return Count value of given reference object 1270 */ 1271 static inline uint32_t 1272 ocs_ref_read_count(ocs_ref_t *ref) 1273 { 1274 return ocs_atomic_read(&ref->count); 1275 } 1276 1277 /** 1278 * @ingroup os 1279 * @brief Set count on given reference object to a value. 1280 * 1281 * @param ref Pointer to reference object 1282 * @param i Set count to this value 1283 */ 1284 static inline void 1285 ocs_ref_set(ocs_ref_t *ref, int i) 1286 { 1287 ocs_atomic_set(&ref->count, i); 1288 } 1289 1290 /** 1291 * @ingroup os 1292 * @brief Take a reference on given object. 1293 * 1294 * @par Description 1295 * This function takes a reference on an object. 1296 * 1297 * Note: this function should only be used if the caller can 1298 * guarantee that the reference count is >= 1 and will stay >= 1 1299 * for the duration of this call (i.e. won't go to zero). If it 1300 * can't (the refcount may go to zero during this call), 1301 * ocs_ref_get_unless_zero() should be used instead. 1302 * 1303 * @param ref Pointer to reference object 1304 * 1305 */ 1306 static inline void 1307 ocs_ref_get(ocs_ref_t *ref) 1308 { 1309 ocs_atomic_add_return(&ref->count, 1); 1310 } 1311 1312 /** 1313 * @ingroup os 1314 * @brief Take a reference on given object if count is not zero. 1315 * 1316 * @par Description 1317 * This function takes a reference on an object if and only if 1318 * the given reference object is "active" or valid. 1319 * 1320 * @param ref Pointer to reference object 1321 * 1322 * @return non-zero if "get" succeeded; Return zero if ref count 1323 * is zero. 1324 */ 1325 static inline uint32_t 1326 ocs_ref_get_unless_zero(ocs_ref_t *ref) 1327 { 1328 uint32_t rc = 0; 1329 rc = ocs_atomic_read(&ref->count); 1330 if (rc != 0) { 1331 ocs_atomic_add_return(&ref->count, 1); 1332 } 1333 return rc; 1334 } 1335 1336 /** 1337 * @ingroup os 1338 * @brief Decrement reference on given object 1339 * 1340 * @par Description 1341 * This function decrements the reference count on the given 1342 * reference object. If the reference count becomes zero, the 1343 * "release" function (set during "init" time) is called. 1344 * 1345 * @param ref Pointer to reference object 1346 * 1347 * @return non-zero if release function was called; zero 1348 * otherwise. 1349 */ 1350 static inline uint32_t 1351 ocs_ref_put(ocs_ref_t *ref) 1352 { 1353 uint32_t rc = 0; 1354 if (ocs_atomic_sub_return(&ref->count, 1) == 1) { 1355 ref->release(ref->arg); 1356 rc = 1; 1357 } 1358 return rc; 1359 } 1360 1361 /** 1362 * @ingroup os 1363 * @brief Get the OS system ticks 1364 * 1365 * @return number of ticks that have occurred since the system 1366 * booted. 1367 */ 1368 static inline uint64_t 1369 ocs_get_os_ticks(void) 1370 { 1371 return ticks; 1372 } 1373 1374 /** 1375 * @ingroup os 1376 * @brief Get the OS system tick frequency 1377 * 1378 * @return frequency of system ticks. 1379 */ 1380 static inline uint32_t 1381 ocs_get_os_tick_freq(void) 1382 { 1383 return hz; 1384 } 1385 1386 /***************************************************************************** 1387 * 1388 * CPU topology API 1389 */ 1390 1391 typedef struct { 1392 uint32_t num_cpus; /* Number of CPU cores */ 1393 uint8_t hyper; /* TRUE if threaded CPUs */ 1394 } ocs_cpuinfo_t; 1395 1396 extern int32_t ocs_get_cpuinfo(ocs_cpuinfo_t *cpuinfo); 1397 extern uint32_t ocs_get_num_cpus(void); 1398 1399 #include "ocs_list.h" 1400 #include "ocs_utils.h" 1401 #include "ocs_mgmt.h" 1402 #include "ocs_common.h" 1403 1404 #endif /* !_OCS_OS_H */ 1405