openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

connection.c (15706B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        connection.c
      8  * Purpose:     Board connection functions
      9  */
     10 
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <sal/core/alloc.h>
     15 #include <sal/core/libc.h>
     16 #include <bcm/init.h>
     17 #include <bcm/error.h>
     18 #include <bcm/types.h>
     19 #include <bcm/port.h>
     20 #include <bcm/trunk.h>
     21 #include <bcm/stack.h>
     22 #include <board/board.h>
     23 #include <board/manager.h>
     24 #include <board_int/support.h>
     25 
     26 
     27 /*
     28  * Function:
     29  *     board_connection_gport_stackable
     30  * Purpose:
     31  *     Return true if the port is capable of being some sort of Higig
     32  *     port.
     33  * Parameters:
     34  *     gport - (IN) stack port
     35  * Returns:
     36  *     TRUE - port is stackable
     37  *     BCM_E_NONE - port is not stackable
     38  *     BCM_E_XXX - failure
     39  * Notes:
     40  *  Not all Higig modes are usable for stacking purposes.
     41  *
     42  *  This API is currently broken. See PR 36640 -
     43  *  bcm_port_ability_local_get only gets current encap of port
     44  */
     45 int
     46 board_connection_gport_stackable(bcm_gport_t gport)
     47 {
     48     bcm_port_ability_t ability;
     49     int unit;
     50     int rv = BCM_E_NONE;
     51 
     52     unit = BCM_GPORT_DEVPORT_DEVID_GET(gport);
     53 
     54     rv = bcm_port_ability_local_get(unit, gport, &ability);
     55     if (BCM_SUCCESS(rv)) {
     56         
     57         if ((ability.encap & BCM_PA_ENCAP_HIGIG) ||
     58             (ability.encap & BCM_PA_ENCAP_HIGIG2)) {
     59                 rv = TRUE;
     60         }
     61     }
     62 
     63     return rv;
     64 }
     65 
     66 /*
     67  * Function:
     68  *     board_connection_gport_stacking
     69  * Purpose:
     70  *     Return TRUE if the stack port is currently in a stacking mode
     71  * Parameters:
     72  *     gport - (IN) stack port
     73  * Returns:
     74  *     TRUE - port is in a stacking mode
     75  *     BCM_E_NONE - port is not in a stacking mode
     76  *     BCM_E_XXX - failure
     77  */
     78 int
     79 board_connection_gport_stacking(bcm_gport_t gport)
     80 {
     81     int mode;
     82     int unit;
     83     int rv = BCM_E_NONE;
     84 
     85     unit = BCM_GPORT_DEVPORT_DEVID_GET(gport);
     86 
     87     rv = bcm_port_encap_get(unit, gport, &mode);
     88     if (BCM_SUCCESS(rv)) {
     89         if ((mode == BCM_PORT_ENCAP_HIGIG) ||
     90             (mode == BCM_PORT_ENCAP_HIGIG2) ||
     91             (mode == BCM_PORT_ENCAP_HIGIG2_LITE)) {
     92                 rv = TRUE;
     93         }
     94     }
     95 
     96     return rv;
     97 }
     98 
     99 /*
    100  * Function:
    101  *     board_connections_discover
    102  * Purpose:
    103  *     Discovers internal connectivity between devices on a board.
    104  *     Discovery algorithm is guaranteed to disrupt traffic,
    105  *     and may be slow for large numbers of devices or internal ports.
    106  *
    107  *     This function is provided for debugging and initial board
    108  *     implementation, and is not intended for production use.
    109  * Parameters:
    110  *     max_num    - (IN)  maximum number of entries in connection array
    111  *     connection - (OUT) array of board_connection_t
    112  *     actual     - (OUT) actual number of valid entries in connection array
    113  * Returns:
    114  *     BCM_E_NONE - success
    115  *     BCM_E_XXX  - failed
    116  */
    117 int
    118 board_connections_discover(int max_num,
    119                            board_connection_t *connection,
    120                            int *actual)
    121 {
    122     int u;
    123     int unit = -1;
    124     int num_units;
    125     int count = 0;
    126     int rv = BCM_E_NONE;
    127     bcm_port_config_t port_info;
    128     bcm_port_t port;
    129     bcm_port_t gport;
    130 
    131     for ( num_units=u=0; u<bcm_unit_max(); u++ ) {
    132         if (bcm_unit_local(u)) {
    133             if (unit < 0) {
    134                 unit = u;
    135                 num_units++;
    136             } else {
    137                 
    138                 return BCM_E_CONFIG;
    139             }
    140         }
    141     }
    142 
    143     if (unit >= 0) {
    144         BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &port_info));
    145         BCM_PBMP_ITER(port_info.port, port) {
    146             gport = BCM_GPORT_DEVPORT(unit, port);
    147             rv = board_connection_gport_stackable(gport);
    148             if (BCM_SUCCESS(rv) && rv > 0) {
    149                 if (count < max_num) {
    150                     connection[count].from = BCM_GPORT_DEVPORT(unit,port);
    151                     connection[count].to   = BCM_GPORT_TYPE_NONE;
    152                 }
    153                 count++;
    154             } else if (BCM_FAILURE(rv)) {
    155                 return rv;
    156             }
    157         }
    158     }
    159 
    160     if (max_num == 0) {
    161         if (actual) {
    162             *actual = count;
    163         } else {
    164             rv = BCM_E_PARAM;
    165         }
    166     } else {
    167         if (actual) {
    168             *actual = count;
    169         }
    170     }
    171 
    172     return rv;
    173 }
    174 
    175 /*
    176  * Function:
    177  *     board_connections_alloc
    178  * Purpose:
    179  *     Allocate a worst case sized connection list for the current board.
    180  * Parameters:
    181  *     driver     - (IN)  current board driver
    182  *     connection - (OUT) allocated connection array
    183  *     actual     - (OUT) size of connection array
    184  * Returns:
    185  *     BCM_E_NONE - success
    186  *     BCM_E_XXX - failed
    187  */
    188 int
    189 board_connections_alloc(board_driver_t *driver,
    190                         board_connection_t **connection,
    191                         int *actual)
    192 {
    193     int count;
    194     int rv = BCM_E_MEMORY;
    195     board_connection_t *conn;
    196 
    197     if (driver == NULL || connection == NULL || actual == NULL) {
    198         return BCM_E_PARAM;
    199     }
    200 
    201     count = board_num_devices() * BCM_PBMP_PORT_MAX;
    202     conn = sal_alloc(count * sizeof(*conn), driver->name);
    203     if (conn) {
    204         sal_memset(conn, 0, count * sizeof(*conn));
    205         *connection = conn;
    206         *actual = count;
    207         rv = BCM_E_NONE;
    208     }
    209 
    210     return rv;
    211 }
    212 
    213 /*
    214  * Function:
    215  *     board_connection_stack_ports
    216  * Purpose:
    217  *     Returns all stack ports on all devices, without regard to internal
    218  *     connectivity.
    219  * Parameters:
    220  *     max_num    - (IN)    maximum size of connection list
    221  *     connection - (INOUT) connection list
    222  *     actual     - (OUT)   actual size of connection list
    223  * Returns:
    224  *     BCM_E_NONE - success
    225  *     BCM_E_XXX - failed
    226  */
    227 int
    228 board_connection_stack_ports(int max_num,
    229                              board_connection_t *connection,
    230                              int *actual)
    231 {
    232     int unit;
    233     int count;
    234     int rv = BCM_E_NONE;
    235     bcm_port_config_t port_info;
    236     bcm_port_t port;
    237     bcm_port_t gport;
    238 
    239     count = 0;
    240     for ( unit=0; unit<bcm_unit_max(); unit++ ) {
    241         if (bcm_unit_local(unit)) {
    242             BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &port_info));
    243             BCM_PBMP_ITER(port_info.port, port) {
    244                 gport = BCM_GPORT_DEVPORT(unit, port);
    245                 rv = board_connection_gport_stackable(gport);
    246                 if (BCM_SUCCESS(rv) && rv > 0) {
    247                     if (count < max_num) {
    248                         connection[count].from = BCM_GPORT_DEVPORT(unit,port);
    249                         connection[count].to   = BCM_GPORT_TYPE_NONE;
    250                     }
    251                     count++;
    252                 } else if (BCM_FAILURE(rv)) {
    253                     return rv;
    254                 }
    255             }
    256         }
    257     }
    258 
    259     if (actual) {
    260         *actual = count;
    261     }
    262 
    263     return rv;
    264 }
    265 
    266 #define INT_STK_FLAGS (BCM_STK_ENABLE | BCM_STK_DUPLEX | BCM_STK_INTERNAL)
    267 
    268 /* Traverse  */
    269 
    270 /*
    271  * Function:
    272  *     board_connection_connected_stack_port_traverse
    273  * Purpose:
    274  *     Tranverses all connected stack ports in the list, ignoring
    275  *     external ports, and non-stack ports.
    276  * Parameters:
    277  *      count      - (IN) length of connection list
    278  *      connection - (IN) connection list
    279  *      func       - (IN) callback function
    280  *      user_data  - (IN) user data passed to callback
    281  * Returns:
    282  *     BCM_E_NONE - success
    283  *     BCM_E_XXX - failed
    284  */
    285 int
    286 board_connection_connected_stack_port_traverse(int count,
    287                                                board_connection_t *connection,
    288                                                board_connection_sp_cb_t func,
    289                                                void *user_data)
    290 {
    291     int i;
    292     int rv = BCM_E_NONE;
    293 
    294     for (i=0; i<count; i++) {
    295 
    296         /* both have to be GPORTs */
    297         if (connection[i].from == BCM_GPORT_TYPE_NONE ||
    298             connection[i].to   == BCM_GPORT_TYPE_NONE) {
    299             continue;
    300         }
    301 
    302         /* both have to be stacking */
    303         rv = board_connection_gport_stacking(connection[i].from);
    304 
    305         if (BCM_FAILURE(rv)) {
    306             break;
    307         } else  if (rv != TRUE) {
    308             continue;
    309         }
    310 
    311         rv = board_connection_gport_stacking(connection[i].to);
    312 
    313         if (BCM_FAILURE(rv)) {
    314             break;
    315         } else  if (rv != TRUE) {
    316             continue;
    317         }
    318 
    319         /* Call the callback for each port */
    320         rv = func(&connection[i], user_data);
    321 
    322         if (BCM_FAILURE(rv)) {
    323             break;
    324         }
    325 
    326     }
    327 
    328     return rv;
    329 }
    330 
    331 /*
    332  * Function:
    333  *
    334  * Purpose:
    335  *     Mark the port as an internal stack port if the stack port
    336  *     is not yet enabled.
    337  * Parameters:
    338  *     gport - (IN) stack port
    339  * Returns:
    340  *     BCM_E_NONE - success
    341  *     BCM_E_XXX - failed
    342  */
    343 STATIC int
    344 _internal_stack_port_set(bcm_gport_t gport)
    345 {
    346     int unit;
    347     uint32 flags;
    348 
    349     unit = BCM_GPORT_DEVPORT_DEVID_GET(gport);
    350     BCM_IF_ERROR_RETURN(bcm_stk_port_get(unit, gport, &flags));
    351     if (!(flags & BCM_STK_ENABLE)) {
    352         /* add as a stack port */
    353         BCM_IF_ERROR_RETURN(bcm_stk_port_set(unit, gport, INT_STK_FLAGS));
    354         /* allow all modids */
    355         BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, gport,
    356                                                       -1, TRUE));
    357     }
    358 
    359     return BCM_E_NONE;
    360 }
    361 
    362 /*
    363  * Function:
    364  *     _internal_stack_connection_set
    365  * Purpose:
    366  *     Set the connection as internal stack ports
    367  * Parameters:
    368  *     conn      - (IN) internal stack port connection
    369  *     user_data - (IN) callback user data
    370  * Returns:
    371  *     BCM_E_NONE - success
    372  *     BCM_E_XXX - failed
    373  */
    374 STATIC int
    375 _internal_stack_connection_set(board_connection_t *conn, void *user_data)
    376 {
    377     COMPILER_REFERENCE(user_data);
    378     BCM_IF_ERROR_RETURN(_internal_stack_port_set(conn->from));
    379     BCM_IF_ERROR_RETURN(_internal_stack_port_set(conn->to));
    380 
    381     return BCM_E_NONE;
    382 }
    383 
    384 /*
    385  * Function:
    386  *     board_connection_add_internal_stack_ports
    387  * Purpose:
    388  *     Add all connection pairs in list as internal stack ports
    389  * Parameters:
    390  *     count      - (IN) length of connection list
    391  *     connection - (IN) connection list
    392  * Returns:
    393  *     BCM_E_NONE - success
    394  *     BCM_E_XXX - failed
    395  */
    396 int
    397 board_connection_add_internal_stack_ports(int count,
    398                                           board_connection_t *connection)
    399 {
    400     return
    401         board_connection_connected_stack_port_traverse
    402            (count, connection, _internal_stack_connection_set, NULL);
    403 }
    404 
    405 /*
    406  * Function:
    407  *     _board_connection_info
    408  * Purpose:
    409  *     Tree Programmer 'info' function.
    410  *     Local interdevice programming
    411  *     Sets modid/trunk info for given unit
    412  * Parameters:
    413  *     unit      - (IN)  current unit
    414  *     modid     - (OUT) modid for this unit
    415  *     ti        - (OUT) trunk info for this unit
    416  *     user_data - (IN)  user data registered
    417  * Returns:
    418  *     BCM_E_NONE - success
    419  *     BCM_E_XXX - failed
    420  */
    421 STATIC int
    422 _board_connection_info(int unit, int *modid, bcm_trunk_chip_info_t *ti,
    423                        void *user_data)
    424 {
    425     int rv;
    426 
    427     rv = bcm_trunk_chip_info_get(unit, ti);
    428     if (BCM_SUCCESS(rv)) {
    429         rv = bcm_stk_my_modid_get(unit, modid);
    430         if (BCM_FAILURE(rv) && (rv == BCM_E_UNAVAIL)) {
    431             /* Assume that this is a fabric */
    432             *modid = -1;
    433             rv = BCM_E_NONE;
    434         }
    435     }
    436 
    437     return rv;
    438 }
    439 
    440 /*
    441  * Function:
    442  *     _board_connection_trunk
    443  * Purpose:
    444  *     Tree Programmer 'edge' function.
    445  *     Program trunk if needed.
    446  * Parameters:
    447  *     unit      - (IN)  current unit
    448  *     ti        - (IN)  trunk info for this unit
    449  *     ta        - (OUT) trunk add info for this unit
    450  *     user_data - (IN)  user data registered
    451  * Returns:
    452  *     BCM_E_NONE - success
    453  *     BCM_E_XXX - failed
    454  */
    455 STATIC int
    456 _board_connection_trunk(int unit, bcm_trunk_chip_info_t *ti,
    457                         bcm_trunk_add_info_t *ta, void *user_data)
    458 {
    459     int rv, tid;
    460     int i;
    461     bcm_trunk_member_t *member_array = NULL;
    462     bcm_trunk_info_t tinfo;
    463 
    464     if (ta->num_ports < 2) {
    465         /* Nothing to do */
    466         return BCM_E_NONE;
    467     }
    468 
    469     tid = ti->trunk_fabric_id_max;
    470     if (tid >= ti->trunk_fabric_id_min) {
    471         ta->psc = -1; /* Default hash algorithm */
    472         ta->dlf_index = -1;
    473         ta->mc_index = -1;
    474         ta->ipmc_index = -1;
    475         rv = bcm_trunk_create(unit, BCM_TRUNK_FLAG_WITH_ID, &tid);
    476         if (BCM_SUCCESS(rv)) {
    477             LOG_VERBOSE(BSL_LS_BOARD_COMMON,
    478                         (BSL_META_U(unit,
    479                         "Board trunk u:%d tid:%d\n"),
    480                          unit, tid));
    481             member_array = sal_alloc(ta->num_ports * sizeof(bcm_trunk_member_t),
    482                     "trunk member array");
    483             if (NULL == member_array) {
    484                 return BCM_E_MEMORY;
    485             }
    486             for (i = 0; i < ta->num_ports; i++) {
    487                 bcm_trunk_member_t_init(&member_array[i]);
    488                 if (BCM_GPORT_IS_SET(ta->tp[i])) {
    489                     member_array[i].gport = ta->tp[i];
    490                 } else {
    491                     BCM_GPORT_LOCAL_SET(member_array[i].gport, ta->tp[i]);
    492                 } 
    493             }
    494             bcm_trunk_info_t_init(&tinfo);
    495             tinfo.flags = ta->flags;
    496             tinfo.psc = ta->psc;
    497             tinfo.dlf_index = ta->dlf_index;
    498             tinfo.mc_index = ta->mc_index;
    499             tinfo.ipmc_index = ta->ipmc_index;
    500             rv = bcm_trunk_set(unit, tid, &tinfo, ta->num_ports, member_array);
    501             if (BCM_SUCCESS(rv)) {
    502                 ti->trunk_fabric_id_max--;
    503             }
    504             sal_free(member_array);
    505         }
    506     } else {
    507         /* No more trunks */
    508         rv = BCM_E_FULL;
    509     }
    510 
    511     return rv;
    512 }
    513 
    514 /*
    515  * Function:
    516  *     _board_connection_modmap
    517  * Purpose:
    518  *     Tree Programmer 'vertex' function.
    519  *     Programs device modmap
    520  * Parameters:
    521  *     unit      - (IN) current unit
    522  *     modid     - (IN) modid for this unit
    523  *     port      - (IN) egressing stack port on this vertex
    524  *     user_data - (IN) user data registered
    525  * Returns:
    526  */
    527 
    528 STATIC int
    529 _board_connection_modmap(int unit, int modid, bcm_gport_t port,
    530                          void *user_data)
    531 {
    532     int rv = BCM_E_NONE;
    533 
    534     if (modid >= 0) {
    535         LOG_VERBOSE(BSL_LS_BOARD_COMMON,
    536                     (BSL_META_U(unit,
    537                     "Board modmap mod=%d u:%d,%d\n"),
    538                      modid, unit, port));
    539         rv = bcm_stk_modport_set(unit, modid, port);
    540     }
    541 
    542     return rv;
    543 }
    544 
    545 
    546 /*
    547  * Function:
    548  *     board_connection_setup
    549  * Purpose:
    550  *     Sets up a board in a standard Ethernet switch configuration
    551  *     according to the board driver connection
    552  *     array. board_modid_set() must be called prior to calling this
    553  *     function.
    554  *
    555  *     Multiple Higig links between devices will be trunked, and module
    556  *     mapping configured for multiple devices.
    557  *
    558  * Parameters:
    559  *     none
    560  * Returns:
    561  *     BCM_E_NONE - success
    562  *     BCM_E_XXX  - failed
    563  */
    564 int
    565 board_connection_setup(void)
    566 {
    567     int rv;
    568     board_driver_t *driver;
    569     board_tree_driver_t tree_driver;
    570 
    571     driver = board_driver();
    572 
    573     if (!driver) {
    574         rv = BCM_E_INIT;
    575     } else if (driver->num_connection > 0) {
    576         tree_driver.num_connection = driver->num_connection;
    577         tree_driver.connection = driver->connection;
    578         tree_driver.user_data = NULL;
    579         tree_driver.info = _board_connection_info;
    580         tree_driver.edge = _board_connection_trunk;
    581         tree_driver.vertex = _board_connection_modmap;
    582         rv = board_tree_connect(&tree_driver);
    583     } else {
    584         /* No connections, nothing to set up */
    585         rv = BCM_E_NONE;
    586     }
    587 
    588     return rv;
    589 }