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