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/isci/scil/scic_sds_remote_node_table.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  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
    3  *
    4  * This file is provided under a dual BSD/GPLv2 license.  When using or
    5  * redistributing this file, you may do so under either license.
    6  *
    7  * GPL LICENSE SUMMARY
    8  *
    9  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   10  *
   11  * This program is free software; you can redistribute it and/or modify
   12  * it under the terms of version 2 of the GNU General Public License as
   13  * published by the Free Software Foundation.
   14  *
   15  * This program is distributed in the hope that it will be useful, but
   16  * WITHOUT ANY WARRANTY; without even the implied warranty of
   17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   18  * General Public License for more details.
   19  *
   20  * You should have received a copy of the GNU General Public License
   21  * along with this program; if not, write to the Free Software
   22  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   23  * The full GNU General Public License is included in this distribution
   24  * in the file called LICENSE.GPL.
   25  *
   26  * BSD LICENSE
   27  *
   28  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   29  * All rights reserved.
   30  *
   31  * Redistribution and use in source and binary forms, with or without
   32  * modification, are permitted provided that the following conditions
   33  * are met:
   34  *
   35  *   * Redistributions of source code must retain the above copyright
   36  *     notice, this list of conditions and the following disclaimer.
   37  *   * Redistributions in binary form must reproduce the above copyright
   38  *     notice, this list of conditions and the following disclaimer in
   39  *     the documentation and/or other materials provided with the
   40  *     distribution.
   41  *
   42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   53  */
   54 
   55 #include <sys/cdefs.h>
   56 __FBSDID("$FreeBSD$");
   57 
   58 /**
   59  * @file
   60  *
   61  * @brief This file contains the implementation of the
   62  *        SCIC_SDS_REMOTE_NODE_TABLE public, protected, and private methods.
   63  */
   64 
   65 #include <dev/isci/scil/scic_sds_remote_node_table.h>
   66 #include <dev/isci/scil/scic_sds_remote_node_context.h>
   67 
   68 /**
   69  * This routine will find the bit position in absolute bit terms of the next
   70  * available bit for selection.  The absolute bit is index * 32 + bit
   71  * position.  If there are available bits in the first U32 then it is just bit
   72  * position.
   73  *  @param[in] remote_node_table This is the remote node index table from
   74  *       which the selection will be made.
   75  * @param[in] group_table_index This is the index to the group table from
   76  *       which to search for an available selection.
   77  *
   78  * @return U32 This is the absolute bit position for an available group.
   79  */
   80 static
   81 U32 scic_sds_remote_node_table_get_group_index(
   82    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
   83    U32                        group_table_index
   84 )
   85 {
   86    U32   dword_index;
   87    U32 * group_table;
   88    U32   bit_index;
   89 
   90    group_table = remote_node_table->remote_node_groups[group_table_index];
   91 
   92    for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++)
   93    {
   94       if (group_table[dword_index] != 0)
   95       {
   96          for (bit_index = 0; bit_index < 32; bit_index++)
   97          {
   98             if ((group_table[dword_index] & (1 << bit_index)) != 0)
   99             {
  100                return (dword_index * 32) + bit_index;
  101             }
  102          }
  103       }
  104    }
  105 
  106    return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX;
  107 }
  108 
  109 /**
  110  * This method will clear the group index entry in the specified group index
  111  * table.
  112  *
  113  * @param[in out] remote_node_table This the remote node table in which to
  114  *       clear the selector.
  115  * @param[in] set_index This is the remote node selector in which the change
  116  *       will be made.
  117  * @param[in] group_index This is the bit index in the table to be modified.
  118  *
  119  * @return none
  120  */
  121 static
  122 void scic_sds_remote_node_table_clear_group_index(
  123    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  124    U32                        group_table_index,
  125    U32                        group_index
  126 )
  127 {
  128    U32   dword_index;
  129    U32   bit_index;
  130    U32 * group_table;
  131 
  132    ASSERT(group_table_index < SCU_STP_REMOTE_NODE_COUNT);
  133    ASSERT(group_index < (U32)(remote_node_table->group_array_size * 32));
  134 
  135    dword_index = group_index / 32;
  136    bit_index   = group_index % 32;
  137    group_table = remote_node_table->remote_node_groups[group_table_index];
  138 
  139    group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index);
  140 }
  141 
  142 /**
  143  * This method will set the group index bit entry in the specified group index
  144  * table.
  145  *
  146  * @param[in out] remote_node_table This the remote node table in which to set
  147  *       the selector.
  148  * @param[in] group_table_index This is the remote node selector in which the
  149  *       change will be made.
  150  * @param[in] group_index This is the bit position in the table to be
  151  *       modified.
  152  *
  153  * @return none
  154  */
  155 static
  156 void scic_sds_remote_node_table_set_group_index(
  157    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  158    U32                        group_table_index,
  159    U32                        group_index
  160 )
  161 {
  162    U32   dword_index;
  163    U32   bit_index;
  164    U32 * group_table;
  165 
  166    ASSERT(group_table_index < SCU_STP_REMOTE_NODE_COUNT);
  167    ASSERT(group_index < (U32)(remote_node_table->group_array_size * 32));
  168 
  169    dword_index = group_index / 32;
  170    bit_index   = group_index % 32;
  171    group_table = remote_node_table->remote_node_groups[group_table_index];
  172 
  173    group_table[dword_index] = group_table[dword_index] | (1 << bit_index);
  174 }
  175 
  176 /**
  177  * This method will set the remote to available in the remote node allocation
  178  * table.
  179  *
  180  * @param[in out] remote_node_table This is the remote node table in which to
  181  *       modify the remote node availability.
  182  * @param[in] remote_node_index This is the remote node index that is being
  183  *       returned to the table.
  184  *
  185  * @return none
  186  */
  187 static
  188 void scic_sds_remote_node_table_set_node_index(
  189    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  190    U32                        remote_node_index
  191 )
  192 {
  193    U32 dword_location;
  194    U32 dword_remainder;
  195    U32 slot_normalized;
  196    U32 slot_position;
  197 
  198    ASSERT(
  199         (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
  200       > (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
  201    );
  202 
  203    dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
  204    dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
  205    slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(U32);
  206    slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
  207 
  208    remote_node_table->available_remote_nodes[dword_location] |=
  209       1 << (slot_normalized + slot_position);
  210 }
  211 
  212 /**
  213  * This method clears the remote node index from the table of available remote
  214  * nodes.
  215  *
  216  * @param[in out] remote_node_table This is the remote node table from which
  217  *       to clear the available remote node bit.
  218  * @param[in] remote_node_index This is the remote node index which is to be
  219  *       cleared from the table.
  220  *
  221  * @return none
  222  */
  223 static
  224 void scic_sds_remote_node_table_clear_node_index(
  225    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  226    U32                        remote_node_index
  227 )
  228 {
  229    U32 dword_location;
  230    U32 dword_remainder;
  231    U32 slot_position;
  232    U32 slot_normalized;
  233 
  234    ASSERT(
  235         (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
  236       > (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
  237    );
  238 
  239    dword_location  = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
  240    dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
  241    slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(U32);
  242    slot_position   = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
  243 
  244    remote_node_table->available_remote_nodes[dword_location] &=
  245       ~(1 << (slot_normalized + slot_position));
  246 }
  247 
  248 /**
  249  * This method clears the entire table slot at the specified slot index.
  250  *
  251  * @param[in out] remote_node_table The remote node table from which the slot
  252  *       will be cleared.
  253  * @param[in] group_index The index for the slot that is to be cleared.
  254  *
  255  * @return none
  256  */
  257 static
  258 void scic_sds_remote_node_table_clear_group(
  259    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  260    U32                        group_index
  261 )
  262 {
  263    U32 dword_location;
  264    U32 dword_remainder;
  265    U32 dword_value;
  266 
  267    ASSERT(
  268         (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
  269       > (group_index / SCU_STP_REMOTE_NODE_COUNT)
  270    );
  271 
  272    dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
  273    dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
  274 
  275    dword_value = remote_node_table->available_remote_nodes[dword_location];
  276    dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
  277    remote_node_table->available_remote_nodes[dword_location] = dword_value;
  278 }
  279 
  280 /**
  281  * THis method sets an entire remote node group in the remote node table.
  282  *
  283  * @param[in] remote_node_table
  284  * @param[in] group_index
  285  */
  286 static
  287 void scic_sds_remote_node_table_set_group(
  288    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  289    U32                        group_index
  290 )
  291 {
  292    U32 dword_location;
  293    U32 dword_remainder;
  294    U32 dword_value;
  295 
  296    ASSERT(
  297         (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
  298       > (group_index / SCU_STP_REMOTE_NODE_COUNT)
  299    );
  300 
  301    dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
  302    dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
  303 
  304    dword_value = remote_node_table->available_remote_nodes[dword_location];
  305    dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
  306    remote_node_table->available_remote_nodes[dword_location] = dword_value;
  307 }
  308 
  309 /**
  310  * This method will return the group value for the specified group index.
  311  *
  312  * @param[in] remote_node_table This is the remote node table that for which
  313  *       the group value is to be returned.
  314  * @param[in] group_index This is the group index to use to find the group
  315  *       value.
  316  *
  317  * @return The bit values at the specified remote node group index.
  318  */
  319 static
  320 U8 scic_sds_remote_node_table_get_group_value(
  321    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  322    U32                        group_index
  323 )
  324 {
  325    U32 dword_location;
  326    U32 dword_remainder;
  327    U32 dword_value;
  328 
  329    dword_location  = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
  330    dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
  331 
  332    dword_value = remote_node_table->available_remote_nodes[dword_location];
  333    dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
  334    dword_value = dword_value >> (dword_remainder * 4);
  335 
  336    return (U8)dword_value;
  337 }
  338 
  339 /**
  340  * This method will initialize the remote node table for use.
  341  *
  342  * @param[in out] remote_node_table The remote that which is to be
  343  *       initialized.
  344  * @param[in] remote_node_entries The number of entries to put in the table.
  345  *
  346  * @return none
  347  */
  348 void scic_sds_remote_node_table_initialize(
  349    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  350    U32                        remote_node_entries
  351 )
  352 {
  353    U32 index;
  354 
  355    // Initialize the raw data we could improve the speed by only initializing
  356    // those entries that we are actually going to be used
  357    memset(
  358       remote_node_table->available_remote_nodes,
  359       0x00,
  360       sizeof(remote_node_table->available_remote_nodes)
  361    );
  362 
  363    memset(
  364       remote_node_table->remote_node_groups,
  365       0x00,
  366       sizeof(remote_node_table->remote_node_groups)
  367    );
  368 
  369    // Initialize the available remote node sets
  370    remote_node_table->available_nodes_array_size = (U16)
  371         (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD)
  372       + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0);
  373 
  374 
  375    // Initialize each full DWORD to a FULL SET of remote nodes
  376    for (index = 0; index < remote_node_entries; index++)
  377    {
  378       scic_sds_remote_node_table_set_node_index(remote_node_table, index);
  379    }
  380 
  381    remote_node_table->group_array_size = (U16)
  382         (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32))
  383       + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0);
  384 
  385    for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++)
  386    {
  387       // These are all guaranteed to be full slot values so fill them in the
  388       // available sets of 3 remote nodes
  389       scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index);
  390    }
  391 
  392    // Now fill in any remainders that we may find
  393    if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2)
  394    {
  395       scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index);
  396    }
  397    else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1)
  398    {
  399       scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index);
  400    }
  401 }
  402 
  403 /**
  404  * This method will allocate a single RNi from the remote node table.  The
  405  * table index will determine from which remote node group table to search.
  406  * This search may fail and another group node table can be specified.  The
  407  * function is designed to allow a serach of the available single remote node
  408  * group up to the triple remote node group.  If an entry is found in the
  409  * specified table the remote node is removed and the remote node groups are
  410  * updated.
  411  *
  412  * @param[in out] remote_node_table The remote node table from which to
  413  *       allocate a remote node.
  414  * @param[in] table_index The group index that is to be used for the search.
  415  *
  416  * @return The RNi value or an invalid remote node context if an RNi can not
  417  *         be found.
  418  */
  419 static
  420 U16 scic_sds_remote_node_table_allocate_single_remote_node(
  421    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  422    U32                        group_table_index
  423 )
  424 {
  425    U8  index;
  426    U8  group_value;
  427    U32 group_index;
  428    U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
  429 
  430    group_index = scic_sds_remote_node_table_get_group_index(
  431                                              remote_node_table, group_table_index);
  432 
  433    // We could not find an available slot in the table selector 0
  434    if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX)
  435    {
  436       group_value = scic_sds_remote_node_table_get_group_value(
  437                                     remote_node_table, group_index);
  438 
  439       for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++)
  440       {
  441          if (((1 << index) & group_value) != 0)
  442          {
  443             // We have selected a bit now clear it
  444             remote_node_index = (U16) (group_index * SCU_STP_REMOTE_NODE_COUNT
  445                                        + index);
  446 
  447             scic_sds_remote_node_table_clear_group_index(
  448                remote_node_table, group_table_index, group_index
  449             );
  450 
  451             scic_sds_remote_node_table_clear_node_index(
  452                remote_node_table, remote_node_index
  453             );
  454 
  455             if (group_table_index > 0)
  456             {
  457                scic_sds_remote_node_table_set_group_index(
  458                   remote_node_table, group_table_index - 1, group_index
  459                );
  460             }
  461 
  462             break;
  463          }
  464       }
  465    }
  466 
  467    return remote_node_index;
  468 }
  469 
  470 /**
  471  * This method will allocate three consecutive remote node context entries. If
  472  * there are no remaining triple entries the function will return a failure.
  473  *
  474  * @param[in] remote_node_table This is the remote node table from which to
  475  *       allocate the remote node entries.
  476  * @param[in] group_table_index THis is the group table index which must equal
  477  *       two (2) for this operation.
  478  *
  479  * @return The remote node index that represents three consecutive remote node
  480  *         entries or an invalid remote node context if none can be found.
  481  */
  482 static
  483 U16 scic_sds_remote_node_table_allocate_triple_remote_node(
  484    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  485    U32                        group_table_index
  486 )
  487 {
  488    U32 group_index;
  489    U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
  490 
  491    group_index = scic_sds_remote_node_table_get_group_index(
  492                                              remote_node_table, group_table_index);
  493 
  494    if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX)
  495    {
  496       remote_node_index = (U16) group_index * SCU_STP_REMOTE_NODE_COUNT;
  497 
  498       scic_sds_remote_node_table_clear_group_index(
  499          remote_node_table, group_table_index, group_index
  500       );
  501 
  502       scic_sds_remote_node_table_clear_group(
  503          remote_node_table, group_index
  504       );
  505    }
  506 
  507    return remote_node_index;
  508 }
  509 
  510 /**
  511  * This method will allocate a remote node that mataches the remote node count
  512  * specified by the caller.  Valid values for remote node count is
  513  * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
  514  *
  515  * @param[in] remote_node_table This is the remote node table from which the
  516  *       remote node allocation is to take place.
  517  * @param[in] remote_node_count This is ther remote node count which is one of
  518  *       SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
  519  *
  520  * @return U16 This is the remote node index that is returned or an invalid
  521  *         remote node context.
  522  */
  523 U16 scic_sds_remote_node_table_allocate_remote_node(
  524    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  525    U32                        remote_node_count
  526 )
  527 {
  528    U16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
  529 
  530    if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT)
  531    {
  532       remote_node_index =
  533          scic_sds_remote_node_table_allocate_single_remote_node(
  534                                                          remote_node_table, 0);
  535 
  536       if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
  537       {
  538          remote_node_index =
  539             scic_sds_remote_node_table_allocate_single_remote_node(
  540                                                          remote_node_table, 1);
  541       }
  542 
  543       if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
  544       {
  545          remote_node_index =
  546             scic_sds_remote_node_table_allocate_single_remote_node(
  547                                                          remote_node_table, 2);
  548       }
  549    }
  550    else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT)
  551    {
  552       remote_node_index =
  553          scic_sds_remote_node_table_allocate_triple_remote_node(
  554                                                          remote_node_table, 2);
  555    }
  556 
  557    return remote_node_index;
  558 }
  559 
  560 /**
  561  * This method will free a single remote node index back to the remote node
  562  * table.  This routine will update the remote node groups
  563  *
  564  * @param[in] remote_node_table
  565  * @param[in] remote_node_index
  566  */
  567 static
  568 void scic_sds_remote_node_table_release_single_remote_node(
  569    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  570    U16                        remote_node_index
  571 )
  572 {
  573    U32 group_index;
  574    U8  group_value;
  575 
  576    group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
  577 
  578    group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index);
  579 
  580    // Assert that we are not trying to add an entry to a slot that is already
  581    // full.
  582    ASSERT(group_value != SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE);
  583 
  584    if (group_value == 0x00)
  585    {
  586       // There are no entries in this slot so it must be added to the single
  587       // slot table.
  588       scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index);
  589    }
  590    else if ((group_value & (group_value -1)) == 0)
  591    {
  592       // There is only one entry in this slot so it must be moved from the
  593       // single slot table to the dual slot table
  594       scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index);
  595       scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index);
  596    }
  597    else
  598    {
  599       // There are two entries in the slot so it must be moved from the dual
  600       // slot table to the tripple slot table.
  601       scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index);
  602       scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index);
  603    }
  604 
  605    scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index);
  606 }
  607 
  608 /**
  609  * This method will release a group of three consecutive remote nodes back to
  610  * the free remote nodes.
  611  *
  612  * @param[in] remote_node_table This is the remote node table to which the
  613  *       remote node index is to be freed.
  614  * @param[in] remote_node_index This is the remote node index which is being
  615  *       freed.
  616  */
  617 static
  618 void scic_sds_remote_node_table_release_triple_remote_node(
  619    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  620    U16                        remote_node_index
  621 )
  622 {
  623    U32 group_index;
  624 
  625    group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
  626 
  627    scic_sds_remote_node_table_set_group_index(
  628       remote_node_table, 2, group_index
  629    );
  630 
  631    scic_sds_remote_node_table_set_group(remote_node_table, group_index);
  632 }
  633 
  634 /**
  635  * This method will release the remote node index back into the remote node
  636  * table free pool.
  637  *
  638  * @param[in] remote_node_table The remote node table to which the remote node
  639  *       index is to be freed.
  640  * @param[in] remote_node_count This is the count of consecutive remote nodes
  641  *       that are to be freed.
  642  * @param[in] remote_node_index This is the remote node index of the start of
  643  *       the number of remote nodes to be freed.
  644  */
  645 void scic_sds_remote_node_table_release_remote_node_index(
  646    SCIC_REMOTE_NODE_TABLE_T * remote_node_table,
  647    U32                        remote_node_count,
  648    U16                        remote_node_index
  649 )
  650 {
  651    if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT)
  652    {
  653       scic_sds_remote_node_table_release_single_remote_node(
  654                                        remote_node_table, remote_node_index);
  655    }
  656    else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT)
  657    {
  658       scic_sds_remote_node_table_release_triple_remote_node(
  659                                        remote_node_table, remote_node_index);
  660    }
  661 }
  662 

Cache object: f316f1095b58c3727aef0468a29ecb45


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