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.c

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  * Implementation of common BSD OS abstraction functions
   37  */
   38 
   39 #include "ocs.h"
   40 
   41 static MALLOC_DEFINE(M_OCS, "OCS", "OneCore Storage data");
   42 
   43 #include <dev/pci/pcireg.h>
   44 #include <dev/pci/pcivar.h>
   45 
   46 #include <machine/bus.h>
   47 
   48 callout_func_t  __ocs_callout;
   49 
   50 uint32_t
   51 ocs_config_read32(ocs_os_handle_t os, uint32_t reg)
   52 {
   53         return pci_read_config(os->dev, reg, 4);
   54 }
   55 
   56 uint16_t
   57 ocs_config_read16(ocs_os_handle_t os, uint32_t reg)
   58 {
   59         return pci_read_config(os->dev, reg, 2);
   60 }
   61 
   62 uint8_t
   63 ocs_config_read8(ocs_os_handle_t os, uint32_t reg)
   64 {
   65         return pci_read_config(os->dev, reg, 1);
   66 }
   67 
   68 void
   69 ocs_config_write8(ocs_os_handle_t os, uint32_t reg, uint8_t val)
   70 {
   71         return pci_write_config(os->dev, reg, val, 1);
   72 }
   73 
   74 void
   75 ocs_config_write16(ocs_os_handle_t os, uint32_t reg, uint16_t val)
   76 {
   77         return pci_write_config(os->dev, reg, val, 2);
   78 }
   79 
   80 void
   81 ocs_config_write32(ocs_os_handle_t os, uint32_t reg, uint32_t val)
   82 {
   83         return pci_write_config(os->dev, reg, val, 4);
   84 }
   85 
   86 /**
   87  * @ingroup os
   88  * @brief Read a 32bit PCI register
   89  *
   90  * The SLI documentation uses the term "register set" to describe one or more
   91  * PCI BARs which form a logical address. For example, a 64-bit address uses
   92  * two BARs, and thus constitute a register set.
   93  *
   94  * @param ocs Pointer to the driver's context
   95  * @param rset Register Set to use
   96  * @param off Offset from the base address of the Register Set
   97  *
   98  * @return register value
   99  */
  100 uint32_t
  101 ocs_reg_read32(ocs_t *ocs, uint32_t rset, uint32_t off)
  102 {
  103         ocs_pci_reg_t           *reg = NULL;
  104 
  105         reg = &ocs->reg[rset];
  106 
  107         return bus_space_read_4(reg->btag, reg->bhandle, off);
  108 }
  109 
  110 /**
  111  * @ingroup os
  112  * @brief Read a 16bit PCI register
  113  *
  114  * The SLI documentation uses the term "register set" to describe one or more
  115  * PCI BARs which form a logical address. For example, a 64-bit address uses
  116  * two BARs, and thus constitute a register set.
  117  *
  118  * @param ocs Pointer to the driver's context
  119  * @param rset Register Set to use
  120  * @param off Offset from the base address of the Register Set
  121  *
  122  * @return register value
  123  */
  124 uint16_t
  125 ocs_reg_read16(ocs_t *ocs, uint32_t rset, uint32_t off)
  126 {
  127         ocs_pci_reg_t           *reg = NULL;
  128 
  129         reg = &ocs->reg[rset];
  130 
  131         return bus_space_read_2(reg->btag, reg->bhandle, off);
  132 }
  133 
  134 /**
  135  * @ingroup os
  136  * @brief Read a 8bit PCI register
  137  *
  138  * The SLI documentation uses the term "register set" to describe one or more
  139  * PCI BARs which form a logical address. For example, a 64-bit address uses
  140  * two BARs, and thus constitute a register set.
  141  *
  142  * @param ocs Pointer to the driver's context
  143  * @param rset Register Set to use
  144  * @param off Offset from the base address of the Register Set
  145  *
  146  * @return register value
  147  */
  148 uint8_t
  149 ocs_reg_read8(ocs_t *ocs, uint32_t rset, uint32_t off)
  150 {
  151         ocs_pci_reg_t           *reg = NULL;
  152 
  153         reg = &ocs->reg[rset];
  154 
  155         return bus_space_read_1(reg->btag, reg->bhandle, off);
  156 }
  157 
  158 /**
  159  * @ingroup os
  160  * @brief Write a 32bit PCI register
  161  *
  162  * The SLI documentation uses the term "register set" to describe one or more
  163  * PCI BARs which form a logical address. For example, a 64-bit address uses
  164  * two BARs, and thus constitute a register set.
  165  *
  166  * @param ocs Pointer to the driver's context
  167  * @param rset Register Set to use
  168  * @param off Offset from the base address of the Register Set
  169  * @param val Value to write
  170  *
  171  * @return none
  172  */
  173 void
  174 ocs_reg_write32(ocs_t *ocs, uint32_t rset, uint32_t off, uint32_t val)
  175 {
  176         ocs_pci_reg_t           *reg = NULL;
  177 
  178         reg = &ocs->reg[rset];
  179 
  180         return bus_space_write_4(reg->btag, reg->bhandle, off, val);
  181 }
  182 
  183 /**
  184  * @ingroup os
  185  * @brief Write a 16-bit PCI register
  186  *
  187  * The SLI documentation uses the term "register set" to describe one or more
  188  * PCI BARs which form a logical address. For example, a 64-bit address uses
  189  * two BARs, and thus constitute a register set.
  190  *
  191  * @param ocs Pointer to the driver's context
  192  * @param rset Register Set to use
  193  * @param off Offset from the base address of the Register Set
  194  * @param val Value to write
  195  *
  196  * @return none
  197  */
  198 void
  199 ocs_reg_write16(ocs_t *ocs, uint32_t rset, uint32_t off, uint16_t val)
  200 {
  201         ocs_pci_reg_t           *reg = NULL;
  202 
  203         reg = &ocs->reg[rset];
  204 
  205         return bus_space_write_2(reg->btag, reg->bhandle, off, val);
  206 }
  207 
  208 /**
  209  * @ingroup os
  210  * @brief Write a 8-bit PCI register
  211  *
  212  * The SLI documentation uses the term "register set" to describe one or more
  213  * PCI BARs which form a logical address. For example, a 64-bit address uses
  214  * two BARs, and thus constitute a register set.
  215  *
  216  * @param ocs Pointer to the driver's context
  217  * @param rset Register Set to use
  218  * @param off Offset from the base address of the Register Set
  219  * @param val Value to write
  220  *
  221  * @return none
  222  */
  223 void
  224 ocs_reg_write8(ocs_t *ocs, uint32_t rset, uint32_t off, uint8_t val)
  225 {
  226         ocs_pci_reg_t           *reg = NULL;
  227 
  228         reg = &ocs->reg[rset];
  229 
  230         return bus_space_write_1(reg->btag, reg->bhandle, off, val);
  231 }
  232 
  233 /**
  234  * @ingroup os
  235  * @brief Allocate host memory
  236  *
  237  * @param os OS handle
  238  * @param size number of bytes to allocate
  239  * @param flags additional options
  240  *
  241  * @return pointer to allocated memory, NULL otherwise
  242  */
  243 void *
  244 ocs_malloc(ocs_os_handle_t os, size_t size, int32_t flags)
  245 {
  246         if ((flags & OCS_M_NOWAIT) == 0) {
  247                 flags |= M_WAITOK;
  248         }
  249 
  250 #ifndef OCS_DEBUG_MEMORY
  251         return malloc(size, M_OCS, flags);
  252 #else
  253         char nameb[80];
  254         long offset = 0;
  255         void *addr = malloc(size, M_OCS, flags);
  256 
  257         linker_ddb_search_symbol_name(__builtin_return_address(1), nameb, sizeof(nameb), &offset);
  258         printf("A: %p %ld @ %s+%#lx\n", addr, size, nameb, offset);
  259 
  260         return addr;
  261 #endif
  262 }
  263 
  264 /**
  265  * @ingroup os
  266  * @brief Free host memory
  267  *
  268  * @param os OS handle
  269  * @param addr pointer to memory
  270  * @param size bytes to free
  271  *
  272  * @note size ignored in BSD
  273  */
  274 void
  275 ocs_free(ocs_os_handle_t os, void *addr, size_t size)
  276 {
  277 #ifndef OCS_DEBUG_MEMORY
  278         free(addr, M_OCS);
  279 #else
  280         printf("F: %p %ld\n", addr, size);
  281         free(addr, M_OCS);
  282 #endif
  283 }
  284 
  285 /**
  286  * @brief Callback function provided to bus_dmamap_load
  287  *
  288  * Function loads the physical / bus address into the DMA descriptor. The caller
  289  * can detect a mapping failure if a descriptor's phys element is zero.
  290  *
  291  * @param arg Argument provided to bus_dmamap_load is a ocs_dma_t
  292  * @param seg Array of DMA segment(s), each describing segment's address and length
  293  * @param nseg Number of elements in array
  294  * @param error Indicates success (0) or failure of mapping
  295  */
  296 static void
  297 ocs_dma_load(void *arg, bus_dma_segment_t *seg, int nseg, int error)
  298 {
  299         ocs_dma_t       *dma = arg;
  300 
  301         if (error) {
  302                 printf("%s: error=%d\n", __func__, error);
  303                 dma->phys = 0;
  304         } else {
  305                 dma->phys = seg->ds_addr;
  306         }
  307 }
  308 
  309 /**
  310  * @ingroup os
  311  * @brief Free a DMA capable block of memory
  312  *
  313  * @param os Device abstraction
  314  * @param dma DMA descriptor for memory to be freed
  315  *
  316  * @return 0 if memory is de-allocated, -1 otherwise
  317  */
  318 int32_t
  319 ocs_dma_free(ocs_os_handle_t os, ocs_dma_t *dma)
  320 {
  321         struct ocs_softc        *ocs = os;
  322 
  323         if (!dma) {
  324                 device_printf(ocs->dev, "%s: bad parameter(s) dma=%p\n", __func__, dma);
  325                 return -1;
  326         }
  327 
  328         if (dma->size == 0) {
  329                 return 0;
  330         }
  331 
  332         if (dma->map) {
  333                 bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_POSTREAD |
  334                                 BUS_DMASYNC_POSTWRITE);
  335                 bus_dmamap_unload(dma->tag, dma->map);
  336         }
  337 
  338         if (dma->virt) {
  339                 bus_dmamem_free(dma->tag, dma->virt, dma->map);
  340                 bus_dmamap_destroy(dma->tag, dma->map);
  341         }
  342         bus_dma_tag_destroy(dma->tag);
  343 
  344         bzero(dma, sizeof(ocs_dma_t));
  345 
  346         return 0;
  347 }
  348 
  349 /**
  350  * @ingroup os
  351  * @brief Allocate a DMA capable block of memory
  352  *
  353  * @param os Device abstraction
  354  * @param dma DMA descriptor containing results of memory allocation
  355  * @param size Size in bytes of desired allocation
  356  * @param align Alignment in bytes
  357  *
  358  * @return 0 on success, ENOMEM otherwise
  359  */
  360 int32_t
  361 ocs_dma_alloc(ocs_os_handle_t os, ocs_dma_t *dma, size_t size, size_t align)
  362 {
  363         struct ocs_softc        *ocs = os;
  364 
  365         if (!dma || !size) {
  366                 device_printf(ocs->dev, "%s bad parameter(s) dma=%p size=%zd\n",
  367                                 __func__, dma, size);
  368                 return ENOMEM;
  369         }
  370 
  371         bzero(dma, sizeof(ocs_dma_t));
  372 
  373         /* create a "tag" that describes the desired memory allocation */
  374         if (bus_dma_tag_create(ocs->dmat, align, 0, BUS_SPACE_MAXADDR,
  375                                 BUS_SPACE_MAXADDR, NULL, NULL,
  376                                 size, 1, size, 0, NULL, NULL, &dma->tag)) {
  377                 device_printf(ocs->dev, "DMA tag allocation failed\n");
  378                 return ENOMEM;
  379         }
  380 
  381         dma->size = size;
  382 
  383         /* allocate the memory */
  384         if (bus_dmamem_alloc(dma->tag, &dma->virt, BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
  385                                 &dma->map)) {
  386                 device_printf(ocs->dev, "DMA memory allocation failed s=%zd a=%zd\n", size, align);
  387                 ocs_dma_free(ocs, dma);
  388                 return ENOMEM;
  389         }
  390 
  391         dma->alloc = dma->virt;
  392 
  393         /* map virtual address to device visible address */
  394         if (bus_dmamap_load(dma->tag, dma->map, dma->virt, dma->size, ocs_dma_load,
  395                                 dma, 0)) {
  396                 device_printf(ocs->dev, "DMA memory load failed\n");
  397                 ocs_dma_free(ocs, dma);
  398                 return ENOMEM;
  399         }
  400 
  401         /* if the DMA map load callback fails, it sets the physical address to zero */
  402         if (0 == dma->phys) {
  403                 device_printf(ocs->dev, "ocs_dma_load failed\n");
  404                 ocs_dma_free(ocs, dma);
  405                 return ENOMEM;
  406         }
  407 
  408         return 0;
  409 }
  410 
  411 /**
  412  * @ingroup os
  413  * @brief Synchronize the DMA buffer memory
  414  *
  415  * Ensures memory coherency between the CPU and device
  416  *
  417  * @param dma DMA descriptor of memory to synchronize
  418  * @param flags Describes direction of synchronization
  419  *   See BUS_DMA(9) for details
  420  *   - BUS_DMASYNC_PREWRITE
  421  *   - BUS_DMASYNC_POSTREAD
  422  */
  423 void
  424 ocs_dma_sync(ocs_dma_t *dma, uint32_t flags)
  425 {
  426         bus_dmamap_sync(dma->tag, dma->map, flags);
  427 }
  428 
  429 int32_t
  430 ocs_dma_copy_in(ocs_dma_t *dma, void *buffer, uint32_t buffer_length)
  431 {
  432         if (!dma)
  433                 return -1;
  434         if (!buffer)
  435                 return -1;
  436         if (buffer_length == 0)
  437                 return 0;
  438         if (buffer_length > dma->size)
  439                 buffer_length = dma->size;
  440         ocs_memcpy(dma->virt, buffer, buffer_length);
  441         dma->len = buffer_length;
  442         return buffer_length;
  443 }
  444 
  445 int32_t
  446 ocs_dma_copy_out(ocs_dma_t *dma, void *buffer, uint32_t buffer_length)
  447 {
  448         if (!dma)
  449                 return -1;
  450         if (!buffer)
  451                 return -1;
  452         if (buffer_length == 0)
  453                 return 0;
  454         if (buffer_length > dma->len)
  455                 buffer_length = dma->len;
  456         ocs_memcpy(buffer, dma->virt, buffer_length);
  457         return buffer_length;
  458 }
  459 
  460 /**
  461  * @ingroup os
  462  * @brief Initialize a lock
  463  *
  464  * @param lock lock to initialize
  465  * @param name string identifier for the lock
  466  */
  467 void
  468 ocs_lock_init(void *os, ocs_lock_t *lock, const char *name, ...)
  469 {
  470         va_list ap;
  471 
  472         va_start(ap, name);
  473         ocs_vsnprintf(lock->name, MAX_LOCK_DESC_LEN, name, ap);
  474         va_end(ap);
  475 
  476         mtx_init(&lock->lock, lock->name, NULL, MTX_DEF);
  477 }
  478 
  479 /**
  480  * @brief Allocate a bit map
  481  *
  482  * For BSD, this is a simple character string
  483  *
  484  * @param n_bits number of bits in bit map
  485  *
  486  * @return pointer to the bit map, NULL on error
  487  */
  488 ocs_bitmap_t *
  489 ocs_bitmap_alloc(uint32_t n_bits)
  490 {
  491 
  492         return malloc(bitstr_size(n_bits), M_OCS, M_ZERO | M_NOWAIT);
  493 }
  494 
  495 /**
  496  * @brief Free a bit map
  497  *
  498  * @param bitmap pointer to previously allocated bit map
  499  */
  500 void
  501 ocs_bitmap_free(ocs_bitmap_t *bitmap)
  502 {
  503 
  504         free(bitmap, M_OCS);
  505 }
  506 
  507 /**
  508  * @brief find next unset bit and set it
  509  *
  510  * @param bitmap bit map to search
  511  * @param n_bits number of bits in map
  512  *
  513  * @return bit position or -1 if map is full
  514  */
  515 int32_t
  516 ocs_bitmap_find(ocs_bitmap_t *bitmap, uint32_t n_bits)
  517 {
  518         int32_t         position = -1;
  519 
  520         bit_ffc(bitmap, n_bits, &position);
  521 
  522         if (-1 != position) {
  523                 bit_set(bitmap, position);
  524         }
  525 
  526         return position;
  527 }
  528 
  529 /**
  530  * @brief search for next (un)set bit
  531  *
  532  * @param bitmap bit map to search
  533  * @param set search for a set or unset bit
  534  * @param n_bits number of bits in map
  535  *
  536  * @return bit position or -1
  537  */
  538 int32_t
  539 ocs_bitmap_search(ocs_bitmap_t *bitmap, uint8_t set, uint32_t n_bits)
  540 {
  541         int32_t         position;
  542 
  543         if (!bitmap) {
  544                 return -1;
  545         }
  546 
  547         if (set) {
  548                 bit_ffs(bitmap, n_bits, &position);
  549         } else {
  550                 bit_ffc(bitmap, n_bits, &position);
  551         }
  552 
  553         return position;
  554 }
  555 
  556 /**
  557  * @brief clear the specified bit
  558  *
  559  * @param bitmap pointer to bit map
  560  * @param bit bit number to clear
  561  */
  562 void
  563 ocs_bitmap_clear(ocs_bitmap_t *bitmap, uint32_t bit)
  564 {
  565         bit_clear(bitmap, bit);
  566 }
  567 
  568 void _ocs_log(ocs_t *ocs, const char *func_name, int line, const char *fmt, ...)
  569 {
  570         va_list ap;
  571         char buf[256];
  572         char *p = buf;
  573 
  574         va_start(ap, fmt);
  575 
  576         /* TODO: Add Current PID info here. */
  577 
  578         p += snprintf(p, sizeof(buf) - (p - buf), "%s: ", DRV_NAME);
  579         p += snprintf(p, sizeof(buf) - (p - buf), "%s:", func_name);
  580         p += snprintf(p, sizeof(buf) - (p - buf), "%i:", line);
  581         p += snprintf(p, sizeof(buf) - (p - buf), "%s:", (ocs != NULL) ? device_get_nameunit(ocs->dev) : "");
  582         p += vsnprintf(p, sizeof(buf) - (p - buf), fmt, ap);
  583 
  584         va_end(ap);
  585 
  586         printf("%s", buf);
  587 }
  588 
  589 /**
  590  * @brief Common thread call function
  591  *
  592  * This is the common function called whenever a thread instantiated by ocs_thread_create() is started.
  593  * It captures the return value from the actual thread function and stashes it in the thread object, to
  594  * be later retrieved by ocs_thread_get_retval(), and calls kthread_exit(), the proscribed method to terminate
  595  * a thread.
  596  *
  597  * @param arg a pointer to the thread object
  598  *
  599  * @return none
  600  */
  601 
  602 static void
  603 ocs_thread_call_fctn(void *arg)
  604 {
  605         ocs_thread_t *thread = arg;
  606         thread->retval = (*thread->fctn)(thread->arg);
  607         ocs_free(NULL, thread->name, ocs_strlen(thread->name+1));
  608         kthread_exit();
  609 }
  610 
  611 /**
  612  * @brief Create a kernel thread
  613  *
  614  * Creates a kernel thread and optionally starts it.   If the thread is not immediately
  615  * started, ocs_thread_start() should be called at some later point.
  616  *
  617  * @param os OS handle
  618  * @param thread pointer to thread object
  619  * @param fctn function for thread to be begin executing
  620  * @param name text name to identify thread
  621  * @param arg application specific argument passed to thread function
  622  * @param start start option, OCS_THREAD_RUN will start the thread immediately,
  623  *                      OCS_THREAD_CREATE will create but not start the thread
  624  *
  625  * @return returns 0 for success, a negative error code value for failure.
  626  */
  627 
  628 int32_t
  629 ocs_thread_create(ocs_os_handle_t os, ocs_thread_t *thread, ocs_thread_fctn fctn, const char *name, void *arg, ocs_thread_start_e start)
  630 {
  631         int32_t rc = 0;
  632 
  633         ocs_memset(thread, 0, sizeof(*thread));
  634 
  635         thread->fctn = fctn;
  636         thread->name = ocs_strdup(name);
  637         if (thread->name == NULL) {
  638                 thread->name = "unknown";
  639         }
  640         thread->arg = arg;
  641 
  642         ocs_atomic_set(&thread->terminate, 0);
  643 
  644         rc = kthread_add(ocs_thread_call_fctn, thread, NULL, &thread->tcb, (start == OCS_THREAD_CREATE) ? RFSTOPPED : 0,
  645                 OCS_THREAD_DEFAULT_STACK_SIZE_PAGES, "%s", name);
  646 
  647         return rc;
  648 }
  649 
  650 /**
  651  * @brief Start a thread
  652  *
  653  * Starts a thread that was created with OCS_THREAD_CREATE rather than OCS_THREAD_RUN
  654  *
  655  * @param thread pointer to thread object
  656  *
  657  * @return returns 0 for success, a negative error code value for failure.
  658  */
  659 
  660 int32_t ocs_thread_start(ocs_thread_t *thread)
  661 {
  662 
  663         thread_lock(thread->tcb);
  664         sched_add(thread->tcb, SRQ_BORING);
  665         return 0;
  666 }
  667 
  668 /**
  669  * @brief return thread argument
  670  *
  671  * Returns a pointer to the thread's application specific argument
  672  *
  673  * @param mythread pointer to the thread object
  674  *
  675  * @return pointer to application specific argument
  676  */
  677 
  678 void *ocs_thread_get_arg(ocs_thread_t *mythread)
  679 {
  680         return mythread->arg;
  681 }
  682 
  683 /**
  684  * @brief Request thread stop
  685  *
  686  * A stop request is made to the thread.  This is a voluntary call, the thread needs
  687  * to periodically query its terminate request using ocs_thread_terminate_requested()
  688  *
  689  * @param thread pointer to thread object
  690  *
  691  * @return returns 0 for success, a negative error code value for failure.
  692  */
  693 
  694 int32_t
  695 ocs_thread_terminate(ocs_thread_t *thread)
  696 {
  697         ocs_atomic_set(&thread->terminate, 1);
  698         return 0;
  699 }
  700 
  701 /**
  702  * @brief See if a terminate request has been made
  703  *
  704  * Check to see if a stop request has been made to the current thread.  This
  705  * function would be used by a thread to see if it should terminate.
  706  *
  707  * @return returns non-zero if a stop has been requested
  708  */
  709 
  710 int32_t ocs_thread_terminate_requested(ocs_thread_t *thread)
  711 {
  712         return ocs_atomic_read(&thread->terminate);
  713 }
  714 
  715 /**
  716  * @brief Retrieve threads return value
  717  *
  718  * After a thread has terminated, it's return value may be retrieved with this function.
  719  *
  720  * @param thread pointer to thread object
  721  *
  722  * @return return value from thread function
  723  */
  724 
  725 int32_t
  726 ocs_thread_get_retval(ocs_thread_t *thread)
  727 {
  728         return thread->retval;
  729 }
  730 
  731 /**
  732  * @brief Request that the currently running thread yield
  733  *
  734  * The currently running thread yields to the scheduler
  735  *
  736  * @param thread pointer to thread (ignored)
  737  *
  738  * @return none
  739  */
  740 
  741 void
  742 ocs_thread_yield(ocs_thread_t *thread) {
  743         pause("thread yield", 1);
  744 }
  745 
  746 ocs_thread_t *
  747 ocs_thread_self(void)
  748 {
  749         ocs_printf(">>> %s not implemented\n", __func__);
  750         ocs_abort();
  751 }
  752 
  753 int32_t
  754 ocs_thread_setcpu(ocs_thread_t *thread, uint32_t cpu)
  755 {
  756         ocs_printf(">>> %s not implemented\n", __func__);
  757         return -1;
  758 }
  759 
  760 int32_t
  761 ocs_thread_getcpu(void)
  762 {
  763         return curcpu;
  764 }
  765 
  766 int
  767 ocs_sem_init(ocs_sem_t *sem, int val, const char *name, ...)
  768 {
  769         va_list ap;
  770 
  771         va_start(ap, name);
  772         ocs_vsnprintf(sem->name, sizeof(sem->name), name, ap);
  773         va_end(ap);
  774 
  775         sema_init(&sem->sem, val, sem->name);
  776         return 0;
  777 }
  778 
  779 /**
  780  * @ingroup os
  781  * @brief  Copy user arguments in to kernel space for an ioctl
  782  * @par Description
  783  * This function is called at the beginning of an ioctl function
  784  * to copy the ioctl argument from user space to kernel space.
  785  *
  786  * BSD handles this for us - arg is already in kernel space,
  787  * so we just return it.
  788  *
  789  * @param os OS handle
  790  * @param arg The argument passed to the ioctl function
  791  * @param size The size of the structure pointed to by arg
  792  *
  793  * @return A pointer to a kernel space copy of the argument on
  794  *      success; NULL on failure
  795  */
  796 void *ocs_ioctl_preprocess(ocs_os_handle_t os, void *arg, size_t size)
  797 {
  798          return arg;
  799 }
  800 
  801 /**
  802  * @ingroup os
  803  * @brief  Copy results of an ioctl back to user space
  804  * @par Description
  805  * This function is called at the end of ioctl processing to
  806  * copy the argument back to user space.
  807  *
  808  * BSD handles this for us.
  809  *
  810  * @param os OS handle
  811  * @param arg The argument passed to the ioctl function
  812  * @param kern_ptr A pointer to the kernel space copy of the
  813  *                 argument
  814  * @param size The size of the structure pointed to by arg.
  815  *
  816  * @return Returns 0.
  817  */
  818 int32_t ocs_ioctl_postprocess(ocs_os_handle_t os, void *arg, void *kern_ptr, size_t size)
  819 {
  820         return 0;
  821 }
  822 
  823 /**
  824  * @ingroup os
  825  * @brief  Free memory allocated by ocs_ioctl_preprocess
  826  * @par Description
  827  * This function is called in the event of an error in ioctl
  828  * processing.  For operating environments where ocs_ioctlpreprocess
  829  * allocates memory, this call frees the memory without copying
  830  * results back to user space.
  831  *
  832  * For BSD, because no memory was allocated in ocs_ioctl_preprocess,
  833  * nothing needs to be done here.
  834  *
  835  * @param os OS handle
  836  * @param kern_ptr A pointer to the kernel space copy of the
  837  *                 argument
  838  * @param size The size of the structure pointed to by arg.
  839  *
  840  * @return Returns nothing.
  841  */
  842 void ocs_ioctl_free(ocs_os_handle_t os, void *kern_ptr, size_t size)
  843 {
  844         return;
  845 }
  846 
  847 void ocs_intr_disable(ocs_os_handle_t os)
  848 {
  849 }
  850 
  851 void ocs_intr_enable(ocs_os_handle_t os)
  852 {
  853 }
  854 
  855 void ocs_print_stack(void)
  856 {
  857 #if defined(STACK)
  858         struct stack st;
  859 
  860         stack_zero(&st);
  861         stack_save(&st);
  862         stack_print(&st);
  863 #endif
  864 }
  865 
  866 void ocs_abort(void)
  867 {
  868         panic(">>> abort/panic\n");
  869 }
  870 
  871 const char *
  872 ocs_pci_model(uint16_t vendor, uint16_t device)
  873 {
  874         switch (device) {
  875         case PCI_PRODUCT_EMULEX_OCE16002:       return "OCE16002";
  876         case PCI_PRODUCT_EMULEX_OCE1600_VF:     return "OCE1600_VF";
  877         case PCI_PRODUCT_EMULEX_OCE50102:       return "OCE50102";
  878         case PCI_PRODUCT_EMULEX_OCE50102_VF:    return "OCE50102_VR";
  879         default:
  880                 break;
  881         }
  882 
  883         return "unknown";
  884 }
  885 
  886 int32_t
  887 ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func)
  888 {
  889         *bus = pci_get_bus(ocs->dev);
  890         *dev = pci_get_slot(ocs->dev);
  891         *func= pci_get_function(ocs->dev);
  892         return 0;
  893 }
  894 
  895 /**
  896  * @brief return CPU information
  897  *
  898  * This function populates the ocs_cpuinfo_t buffer with CPU information
  899  *
  900  * @param cpuinfo pointer to ocs_cpuinfo_t buffer
  901  *
  902  * @return returns 0 for success, a negative error code value for failure.
  903  */
  904 extern int mp_ncpus;
  905 int32_t
  906 ocs_get_cpuinfo(ocs_cpuinfo_t *cpuinfo)
  907 {
  908         cpuinfo->num_cpus = mp_ncpus;
  909         return 0;
  910 }
  911 
  912 uint32_t
  913 ocs_get_num_cpus(void)
  914 {
  915         static ocs_cpuinfo_t cpuinfo;
  916 
  917         if (cpuinfo.num_cpus == 0) {
  918                 ocs_get_cpuinfo(&cpuinfo);
  919         }
  920         return cpuinfo.num_cpus;
  921 }
  922 
  923 void
  924 __ocs_callout(void *t)
  925 {
  926         ocs_timer_t *timer = t;
  927 
  928         if (callout_pending(&timer->callout)) {
  929                 /* Callout was reset */
  930                 return;
  931         }
  932 
  933         if (!callout_active(&timer->callout)) {
  934                 /* Callout was stopped */
  935                 return;
  936         }
  937 
  938         callout_deactivate(&timer->callout);
  939 
  940         if (timer->func) {
  941                 timer->func(timer->data);
  942         }
  943 }
  944 
  945 int32_t
  946 ocs_setup_timer(ocs_os_handle_t os, ocs_timer_t *timer, void(*func)(void *arg), void *data, uint32_t timeout_ms)
  947 {
  948         struct  timeval tv;
  949         int     hz;
  950 
  951         if (timer == NULL) {
  952                 ocs_log_err(NULL, "bad parameter\n");
  953                 return -1;
  954         }
  955 
  956         if (!mtx_initialized(&timer->lock)) {
  957                 mtx_init(&timer->lock, "ocs_timer", NULL, MTX_DEF);
  958         }
  959 
  960         callout_init_mtx(&timer->callout, &timer->lock, 0);
  961 
  962         timer->func = func;
  963         timer->data = data;
  964 
  965         tv.tv_sec  = timeout_ms / 1000;
  966         tv.tv_usec = (timeout_ms % 1000) * 1000;
  967 
  968         hz = tvtohz(&tv);
  969         if (hz < 0)
  970                 hz = INT32_MAX;
  971         if (hz == 0)
  972                 hz = 1;
  973 
  974         mtx_lock(&timer->lock);
  975                 callout_reset(&timer->callout, hz, __ocs_callout, timer);
  976         mtx_unlock(&timer->lock);
  977 
  978         return 0;
  979 }
  980 
  981 int32_t
  982 ocs_mod_timer(ocs_timer_t *timer, uint32_t timeout_ms)
  983 {
  984         struct  timeval tv;
  985         int     hz;
  986 
  987         if (timer == NULL) {
  988                 ocs_log_err(NULL, "bad parameter\n");
  989                 return -1;
  990         }
  991 
  992         tv.tv_sec  = timeout_ms / 1000;
  993         tv.tv_usec = (timeout_ms % 1000) * 1000;
  994 
  995         hz = tvtohz(&tv);
  996         if (hz < 0)
  997                 hz = INT32_MAX;
  998         if (hz == 0)
  999                 hz = 1;
 1000 
 1001         mtx_lock(&timer->lock);
 1002                 callout_reset(&timer->callout, hz, __ocs_callout, timer);
 1003         mtx_unlock(&timer->lock);
 1004 
 1005         return 0;
 1006 }
 1007 
 1008 int32_t
 1009 ocs_timer_pending(ocs_timer_t *timer)
 1010 {
 1011         return callout_active(&timer->callout);
 1012 }
 1013 
 1014 int32_t
 1015 ocs_del_timer(ocs_timer_t *timer)
 1016 {
 1017 
 1018         mtx_lock(&timer->lock);
 1019                 callout_stop(&timer->callout);
 1020         mtx_unlock(&timer->lock);
 1021 
 1022         return 0;
 1023 }
 1024 
 1025 char *
 1026 ocs_strdup(const char *s)
 1027 {
 1028         uint32_t l = strlen(s);
 1029         char *d;
 1030 
 1031         d = ocs_malloc(NULL, l+1, OCS_M_NOWAIT);
 1032         if (d != NULL) {
 1033                 ocs_strcpy(d, s);
 1034         }
 1035         return d;
 1036 }
 1037 
 1038 void
 1039 _ocs_assert(const char *cond, const char *filename, int linenum)
 1040 {
 1041         const char *fn = strrchr(__FILE__, '/');
 1042 
 1043         ocs_log_err(NULL, "%s(%d) assertion (%s) failed\n", (fn ? fn + 1 : filename), linenum, cond);
 1044         ocs_print_stack();
 1045         ocs_save_ddump_all(OCS_DDUMP_FLAGS_WQES|OCS_DDUMP_FLAGS_CQES|OCS_DDUMP_FLAGS_MQES, -1, TRUE);
 1046 }

Cache object: 01584218bb1567658e3a732f658f0939


[ 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.