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/smartpqi/smartpqi_tag.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 2016-2021 Microchip Technology, Inc. and/or its subsidiaries.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  */
   25 
   26 /* $FreeBSD$ */
   27 
   28 #include "smartpqi_includes.h"
   29 
   30 #ifndef LOCKFREE_STACK
   31 
   32 /*
   33  * Function used to release the tag from taglist.
   34  */
   35 void
   36 pqisrc_put_tag(pqi_taglist_t *taglist, uint32_t elem)
   37 {
   38 
   39         OS_ACQUIRE_SPINLOCK(&(taglist->lock));
   40         DBG_FUNC("IN\n");
   41 
   42         ASSERT(taglist->num_elem < taglist->max_elem);
   43 
   44         if (taglist->num_elem < taglist->max_elem) {
   45                 taglist->elem_array[taglist->tail] = elem;
   46                 taglist->num_elem++;
   47                 taglist->tail = (taglist->tail + 1) % taglist->max_elem;
   48         }
   49 
   50         OS_RELEASE_SPINLOCK(&taglist->lock);
   51 
   52         DBG_FUNC("OUT\n");
   53 }
   54 
   55 /*
   56  * Function used to get an unoccupied tag from the tag list.
   57  */
   58 uint32_t
   59 pqisrc_get_tag(pqi_taglist_t *taglist)
   60 {
   61         uint32_t elem = INVALID_ELEM;
   62 
   63 /*      DBG_FUNC("IN\n");*/
   64 
   65         OS_ACQUIRE_SPINLOCK(&taglist->lock);
   66 
   67         ASSERT(taglist->num_elem > 0);
   68 
   69         if (taglist->num_elem > 0) {
   70                 elem = taglist->elem_array[taglist->head];
   71                 taglist->num_elem--;
   72                 taglist->head = (taglist->head + 1) % taglist->max_elem;
   73         }
   74 
   75         OS_RELEASE_SPINLOCK(&taglist->lock);
   76 
   77 /*      DBG_FUNC("OUT got %d\n", elem);*/
   78         return elem;
   79 }
   80 
   81 /*
   82  * Initialize circular queue implementation of tag list.
   83  */
   84 int
   85 pqisrc_init_taglist(pqisrc_softstate_t *softs, pqi_taglist_t *taglist,
   86                                 uint32_t max_elem)
   87 {
   88         int ret = PQI_STATUS_SUCCESS;
   89         int i = 0;
   90 
   91         DBG_FUNC("IN\n");
   92 
   93         taglist->max_elem = max_elem;
   94         taglist->num_elem = 0;
   95         taglist->head = 0;
   96         taglist->tail = 0;
   97         taglist->elem_array = os_mem_alloc(softs,
   98                         (max_elem * sizeof(uint32_t)));
   99         if (!(taglist->elem_array)) {
  100                 DBG_FUNC("Unable to allocate memory for taglist\n");
  101                 ret = PQI_STATUS_FAILURE;
  102                 goto err_out;
  103         }
  104 
  105         os_strlcpy(taglist->lockname, "tag_lock",  LOCKNAME_SIZE);
  106         ret = os_init_spinlock(softs, &taglist->lock, taglist->lockname);
  107         if(ret){
  108                 DBG_ERR("tag lock initialization failed\n");
  109                 taglist->lockcreated=false;
  110                 goto err_lock;
  111         }
  112         taglist->lockcreated = true;
  113 
  114         /* indices 1 to max_elem are considered as valid tags */
  115         for (i=1; i <= max_elem; i++) {
  116                 softs->rcb[i].tag = INVALID_ELEM;
  117                 pqisrc_put_tag(taglist, i);
  118         }
  119 
  120         DBG_FUNC("OUT\n");
  121         return ret;
  122 
  123 err_lock:
  124         os_mem_free(softs, (char *)taglist->elem_array,
  125                 (taglist->max_elem * sizeof(uint32_t)));
  126         taglist->elem_array = NULL;
  127 err_out:
  128         DBG_FUNC("OUT failed\n");
  129         return ret;
  130 }
  131 
  132 /*
  133  * Destroy circular queue implementation of tag list.
  134  */
  135 void
  136 pqisrc_destroy_taglist(pqisrc_softstate_t *softs, pqi_taglist_t *taglist)
  137 {
  138         DBG_FUNC("IN\n");
  139         os_mem_free(softs, (char *)taglist->elem_array,
  140                 (taglist->max_elem * sizeof(uint32_t)));
  141         taglist->elem_array = NULL;
  142 
  143         if(taglist->lockcreated==true){
  144                 os_uninit_spinlock(&taglist->lock);
  145                 taglist->lockcreated = false;
  146         }
  147 
  148         DBG_FUNC("OUT\n");
  149 }
  150 
  151 #else    /* LOCKFREE_STACK */
  152 
  153 /*
  154  * Initialize circular queue implementation of tag list.
  155  */
  156 int
  157 pqisrc_init_taglist(pqisrc_softstate_t *softs, lockless_stack_t *stack,
  158                                 uint32_t max_elem)
  159 {
  160         int ret = PQI_STATUS_SUCCESS;
  161         int index = 0;
  162 
  163         DBG_FUNC("IN\n");
  164 
  165         /* indices 1 to max_elem are considered as valid tags */
  166         stack->max_elem = max_elem + 1;
  167         stack->head.data = 0;
  168         DBG_INFO("Stack head address :%p\n",&stack->head);
  169 
  170         /*Allocate memory for stack*/
  171         stack->next_index_array = (uint32_t*)os_mem_alloc(softs,
  172                 (stack->max_elem * sizeof(uint32_t)));
  173         if (!(stack->next_index_array)) {
  174                 DBG_ERR("Unable to allocate memory for stack\n");
  175                 ret = PQI_STATUS_FAILURE;
  176                 goto err_out;
  177         }
  178 
  179         /* push all the entries to the stack */
  180         for (index = 1; index < stack->max_elem ; index++) {
  181                 softs->rcb[index].tag = INVALID_ELEM;
  182                 pqisrc_put_tag(stack, index);
  183         }
  184 
  185         DBG_FUNC("OUT\n");
  186         return ret;
  187 err_out:
  188         DBG_FUNC("Failed OUT\n");
  189         return ret;
  190 }
  191 
  192 /*
  193  * Destroy circular queue implementation of tag list.
  194  */
  195 void
  196 pqisrc_destroy_taglist(pqisrc_softstate_t *softs, lockless_stack_t *stack)
  197 {
  198         DBG_FUNC("IN\n");
  199 
  200         /* de-allocate stack memory */
  201         if (stack->next_index_array) {
  202                 os_mem_free(softs,(char*)stack->next_index_array,
  203                         (stack->max_elem * sizeof(uint32_t)));
  204                 stack->next_index_array = NULL;
  205         }
  206 
  207         DBG_FUNC("OUT\n");
  208 }
  209 
  210 /*
  211  * Function used to release the tag from taglist.
  212  */
  213 void
  214 pqisrc_put_tag(lockless_stack_t *stack, uint32_t index)
  215 {
  216    union head_list cur_head, new_head;
  217 
  218         DBG_FUNC("IN\n");
  219         DBG_INFO("push tag :%d\n",index);
  220 
  221         if (index >= stack->max_elem) {
  222                 ASSERT(false);
  223                 DBG_INFO("Pushed Invalid index\n"); /* stack full */
  224                 return;
  225         }
  226 
  227         if (stack->next_index_array[index] != 0) {
  228                 ASSERT(false);
  229                 DBG_INFO("Index already present as tag in the stack\n");
  230                 return;
  231         }
  232 
  233         do {
  234                 cur_head = stack->head;
  235                 /* increment seq_no */
  236                 new_head.top.seq_no = cur_head.top.seq_no + 1;
  237                 /* update the index at the top of the stack with the new index */
  238                 new_head.top.index = index;
  239                 /* Create a link to the previous index */
  240                 stack->next_index_array[index] = cur_head.top.index;
  241         }while(!os_atomic64_cas(&stack->head.data,cur_head.data,new_head.data));
  242         stack->num_elem++;
  243         DBG_FUNC("OUT\n");
  244         return;
  245 }
  246 
  247 /*
  248  * Function used to get an unoccupied tag from the tag list.
  249  */
  250 uint32_t
  251 pqisrc_get_tag(lockless_stack_t *stack)
  252 {
  253         union head_list cur_head, new_head;
  254 
  255         DBG_FUNC("IN\n");
  256         do {
  257                 cur_head = stack->head;
  258                 if (cur_head.top.index == 0)    /* stack empty */
  259                         return INVALID_ELEM;
  260                 /* increment seq_no field */
  261                 new_head.top.seq_no = cur_head.top.seq_no + 1;
  262                 /* update the index at the top of the stack with the next index */
  263                 new_head.top.index = stack->next_index_array[cur_head.top.index];
  264         }while(!os_atomic64_cas(&stack->head.data,cur_head.data,new_head.data));
  265         stack->next_index_array[cur_head.top.index] = 0;
  266         stack->num_elem--;
  267 
  268         DBG_INFO("pop tag: %d\n",cur_head.top.index);
  269         DBG_FUNC("OUT\n");
  270         return cur_head.top.index; /*tag*/
  271 }
  272 #endif /* LOCKFREE_STACK */

Cache object: 878d06e30fcf365248d8050c46615793


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