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

populate.c (8527B)


      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:        populate.c
      8  * Purpose:     Stacking related functions
      9  *              Populate CPUDB based on board hardware
     10  */
     11 
     12 #include <sal/core/alloc.h>
     13 
     14 #include <bcm/error.h>
     15 #include <bcm/types.h>
     16 #include <bcm/port.h>
     17 #include <bcm/stack.h>
     18 #include <board/board.h>
     19 #if defined(INCLUDE_LIB_CPUDB)
     20 #include <appl/cpudb/cpudb.h>
     21 #endif
     22 
     23 #include <board/stack.h>
     24 #include <board_int/support.h>
     25 
     26 #if defined(INCLUDE_LIB_CPUDB)
     27 
     28 /* TRUE if sp_id is valid for cpudb entry */
     29 #define CPUDB_VALID_SP_ID(entry, sp_id) \
     30     (entry != NULL && (sp_id) >= 0 && (sp_id) < entry->base.num_stk_ports)
     31 
     32 /* Last stack port */
     33 #define CPUDB_STK_PORT_LAST (CPUDB_STK_PORTS_MAX - 1)
     34 
     35 /*
     36  * Function:
     37  *     _cpudb_stk_port_next_id_get
     38  * Purpose:
     39  *     Get the next valid stack port ID for the entry
     40  * Parameters:
     41  *     entry - (INOUT) CPUDB entry
     42  *     sp_id - (OUT)   stack port ID
     43  * Returns:
     44  *     BCM_E_NONE - success
     45  *     BCM_E_XXX  - failed
     46  */
     47 STATIC int
     48 _cpudb_stk_port_next_id_get(cpudb_entry_t *entry, int *sp_id)
     49 {
     50     int rv = BCM_E_FAIL;
     51 
     52     if (entry->base.num_stk_ports < CPUDB_STK_PORT_LAST) {
     53         if (sp_id) {
     54             *sp_id = entry->base.num_stk_ports++;
     55             rv = BCM_E_NONE;
     56         } else {
     57             rv = BCM_E_PARAM;
     58         }
     59     }
     60 
     61     return rv;
     62 }
     63 
     64 /*
     65  * Function:
     66  *     _cpudb_stk_gport_add
     67  * Purpose:
     68  *     Add given DEVPORT as the given stack port ID in CPUDB entry
     69  * Parameters:
     70  *     entry - (INOUT) CPUDB entry
     71  *     sp_id - (OUT)   stack port ID
     72  *     gport - (IN)    stack port
     73  * Returns:
     74  *     BCM_E_NONE - success
     75  *     BCM_E_XXX  - failed
     76  */
     77 STATIC int
     78 _cpudb_stk_gport_add(cpudb_entry_t *entry, int sp_id, bcm_gport_t gport)
     79 {
     80     int rv = BCM_E_FAIL;
     81 
     82     if (CPUDB_VALID_SP_ID(entry, sp_id)) {
     83         entry->base.stk_ports[sp_id].unit = BCM_GPORT_DEVPORT_DEVID_GET(gport);
     84         entry->base.stk_ports[sp_id].port = BCM_GPORT_DEVPORT_PORT_GET(gport);
     85         rv = BCM_E_NONE;
     86     }
     87 
     88     return rv;
     89 }
     90 
     91 
     92 /*
     93  * Function:
     94  *     _cpudb_stk_port_flags_set
     95  * Purpose:
     96  *     Set parameters for indicated stack port id
     97  * Parameters:
     98  *     entry  - (INOUT) CPUDB entry
     99  *     sp_id  - (OUT)   stack port ID
    100  *     flags  - (IN)    stack port flags
    101  * Returns:
    102  *     BCM_E_NONE - success
    103  *     BCM_E_XXX  - failed
    104  */
    105 STATIC int
    106 _cpudb_stk_port_flags_set(cpudb_entry_t *entry, int sp_id, uint32 flags)
    107 {
    108     int rv = BCM_E_FAIL;
    109 
    110     if (CPUDB_VALID_SP_ID(entry, sp_id)) {
    111         cpudb_stk_port_t *sp;
    112 
    113         sp = &entry->sp_info[sp_id];
    114         sp->flags = flags;
    115         rv = BCM_E_NONE;
    116     }
    117 
    118     return rv;
    119 }
    120 
    121 /*
    122  * Function:
    123  *     _board_probe_board_id
    124  * Purpose:
    125  *     Set the board ID based on a board attribute.
    126  * Parameters:
    127  *     driver - (IN)    board driver
    128  *     db_ref - (INOUT) CPUDB to set
    129  * Returns:
    130  *     BCM_E_NONE - success
    131  *     BCM_E_XXX  - failed
    132  * Note: This is only intended as a fallback for generic drivers.
    133  */
    134 
    135 STATIC int
    136 _board_probe_board_id(board_driver_t *driver, cpudb_ref_t db_ref)
    137 {
    138     int rv;
    139     int board_attr_id;
    140 
    141     rv = board_attribute_get("cpudb_id", &board_attr_id);
    142     if (BCM_SUCCESS(rv)) {
    143         db_ref->local_entry->base.board_id = (CPUDB_BOARD_ID) board_attr_id;
    144     }
    145 
    146     return rv;
    147 }
    148 
    149 /*
    150  * Function:
    151  *     _external_stack
    152  * Purpose:
    153  *     Return information if a connection is an external
    154  *     stack port.
    155  * Parameters:
    156  *      connection - (IN)  connection to check
    157  *      gport      - (OUT) external stack port
    158  *      now_higig  - (OUT) true if external stack port is stacking
    159  * Returns:
    160  *     BCM_E_NONE - success
    161  *     BCM_E_XXX  - failed
    162  */
    163 STATIC int
    164 _external_stack(board_connection_t *connection,
    165                bcm_gport_t *gport, int *now_higig)
    166 {
    167     int ext, encap;
    168     int rv = BCM_E_FAIL;
    169 
    170     ext = (connection->to == BCM_GPORT_TYPE_NONE);
    171     if (ext) {
    172 
    173         *gport = connection->from;
    174 
    175         rv = board_connection_gport_stackable(connection->from);
    176 
    177         if (BCM_SUCCESS(rv)) {
    178             rv = bcm_port_encap_get
    179                 (BCM_GPORT_DEVPORT_DEVID_GET(connection->from),
    180                  connection->from,
    181                  &encap);
    182             if (BCM_SUCCESS(rv)) {
    183                 if ((encap & BCM_PORT_ENCAP_HIGIG) ||
    184                     (encap & BCM_PORT_ENCAP_HIGIG2)) {
    185                     *now_higig = TRUE;
    186                 }
    187             }
    188         }
    189     }
    190 
    191     return rv;
    192 }
    193 
    194 /*
    195  * Function:
    196  *     _add_sp
    197  * Purpose:
    198  *     Add a connection to CPUDB if it is an external stack port
    199  * Parameters:
    200  *     connection - (IN)    connection to check
    201  *     entry      - (INOUT) CPUDB entry
    202  * Returns:
    203  *     BCM_E_NONE - success
    204  *     BCM_E_XXX  - failed
    205  */
    206 STATIC int
    207 _add_sp(board_connection_t *connection, cpudb_entry_t *entry)
    208 {
    209     bcm_gport_t gport;
    210     int sp_id;
    211     int now_higig = FALSE;
    212     int rv = BCM_E_NONE;
    213 
    214     if (BCM_SUCCESS(_external_stack(connection, &gport, &now_higig))) {
    215         rv = _cpudb_stk_port_next_id_get(entry, &sp_id);
    216         if (BCM_SUCCESS(rv)) {
    217             rv = _cpudb_stk_gport_add(entry, sp_id, gport);
    218             if (BCM_SUCCESS(rv)) {
    219                 if (!now_higig) {
    220                     rv = _cpudb_stk_port_flags_set(entry, sp_id,
    221                                                    CPUDB_SPF_ETHERNET);
    222                 }
    223             }
    224         }
    225     }
    226 
    227     return rv;
    228 }
    229 
    230 /*
    231  * Function:
    232  *     board_cpudb_get
    233  * Purpose:
    234  *     Populate a CPUDB appropriate for the board driver
    235  * Parameters:
    236  *     driver - (IN)    current board driver
    237  *     db_ref - (INOUT) CPUDB to populate
    238  * Returns:
    239  *     BCM_E_NONE - success
    240  *     BCM_E_XXX  - failed
    241  */
    242 int
    243 board_cpudb_get(board_driver_t *driver, cpudb_ref_t db_ref)
    244 {
    245     int i;
    246     int rv;
    247     int unit;
    248     cpudb_entry_t *entry;
    249     bcm_port_config_t port_info;
    250     int num_modids;
    251     int port;
    252     int cpu_unit;
    253     int cpu_port;
    254     int first_cpu_port;
    255 
    256     entry = db_ref->local_entry;
    257 
    258     /* Set fields */
    259     entry->base.master_pri = 0;
    260     entry->base.slot_id = -1;
    261 
    262     entry->tx_unit = -1;
    263     entry->tx_port = -1;
    264     entry->dest_mod = -1;
    265     entry->dest_port = -1;
    266     entry->topo_idx = -1;
    267     entry->base.num_units = board_num_devices();
    268     entry->base.num_stk_ports = 0;
    269 
    270     rv = BCM_E_FAIL;
    271 
    272     for (i=0; i<driver->num_connection; i++) {
    273         rv = _add_sp(&driver->connection[i], entry);
    274         if (BCM_FAILURE(rv)) {
    275             goto fail;
    276         }
    277     }
    278 
    279     /* modids */
    280 
    281     cpu_unit = -1;
    282     cpu_port = -1;
    283     first_cpu_port = -1;
    284 
    285     for (unit=0; unit < entry->base.num_units; unit++) {
    286         num_modids = 0;
    287         rv = bcm_stk_modid_count(unit, &num_modids);
    288         if (BCM_FAILURE(rv)) {
    289             goto fail;
    290         }
    291         entry->mod_ids[unit] = -1;
    292 
    293         /* -1 for single modid, -2 for dual modid (even) */
    294         entry->base.pref_mod_id[unit] = -num_modids;
    295         entry->base.mod_ids_req[unit] = num_modids;
    296 
    297         /* Select CPU port
    298 
    299         Use the first CPU port of a device that is assignable a modid.
    300         If no such device is found, use the CPU port of the first device.
    301 
    302         */
    303 
    304         if (cpu_port < 0) {
    305 
    306             if (unit > 0 && num_modids == 0) {
    307                 /* More than one unit, but this units appears to be a fabric */
    308                 continue;
    309             }
    310 
    311             /* Collect device info */
    312             rv = bcm_port_config_get(unit, &port_info);
    313 
    314             if (BCM_FAILURE(rv)) {
    315                 goto fail;
    316             }
    317 
    318             BCM_PBMP_ITER(port_info.cpu, port) {
    319                 break;
    320             }
    321             if (num_modids > 0) {
    322                 cpu_unit = unit;
    323                 cpu_port = port;
    324             } else if (unit == 0) {
    325                 first_cpu_port = port;
    326             }
    327         }
    328     }
    329 
    330     /* If there still isn't a CPU port, just assign it to the first unit */
    331     if (cpu_unit == -1) {
    332         cpu_unit = 0;
    333         cpu_port = first_cpu_port;
    334     }
    335 
    336     entry->base.dest_unit = cpu_unit;
    337     entry->base.dest_port = cpu_port;
    338 
    339     if (entry->base.dest_unit < 0 || entry->base.dest_port < 0) {
    340         /* No point in having a CPUDB entry without a CPU */
    341         rv = BCM_E_CONFIG;
    342         goto fail;
    343     }
    344 
    345     /* board id */
    346     if (entry->base.num_units == 1) {
    347         (void)(_board_probe_board_id(driver, db_ref));
    348     }
    349 
    350     rv = BCM_E_NONE;
    351 
    352  fail:
    353 
    354     return rv;
    355 }
    356 
    357 #else
    358 int board_cpudb_get;
    359 #endif