The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ocs_fc/ocs_os.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 4052fab323a0eb5e2c2bba3c1dc78a3e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.