mpls.c (18310B)
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: vlan.c 8 * 9 * Provides: 10 * soc_internal_mpls_hash 11 * soc_internal_mpls_dual_banks 12 * soc_internal_mpls_entry_read 13 * soc_internal_mpls_entry_write 14 * soc_internal_mpls_entry_ins 15 * soc_internal_mpls_entry_del 16 * soc_internal_mpls_entry_lkup 17 * 18 * Requires: 19 */ 20 21 #include <shared/bsl.h> 22 23 #include <soc/mem.h> 24 #include <soc/hash.h> 25 #include <soc/drv.h> 26 #include <soc/l2x.h> 27 #ifdef BCM_TRIDENT2_SUPPORT 28 #include <soc/trident2.h> 29 #endif 30 #ifdef BCM_TOMAHAWK3_SUPPORT 31 #include <soc/tomahawk3.h> 32 #endif /* BCM_TOMAHAWK3_SUPPORT */ 33 34 #include "pcid.h" 35 #include "mem.h" 36 #include "cmicsim.h" 37 38 #ifdef BCM_TRIUMPH_SUPPORT 39 40 int 41 soc_internal_mpls_hash(pcid_info_t * pcid_info, 42 mpls_entry_entry_t *entry, int dual) 43 { 44 uint32 tmp_hs[SOC_MAX_MEM_WORDS]; 45 int hash_sel; 46 uint8 at, key[8]; 47 int index, bits; 48 soc_block_t blk; 49 50 LOG_VERBOSE(BSL_LS_SOC_COMMON, 51 (BSL_META("MPLS_ENTRY hash\n"))); 52 53 #ifdef BCM_TOMAHAWK3_SUPPORT 54 if (SOC_IS_TOMAHAWK3(pcid_info->unit)) { 55 soc_block_t sblk; 56 int use_lsb; 57 uint8 acc_type; 58 uint32 addr; 59 int bank; 60 static const soc_field_t fields[] = { 61 HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f 62 }; 63 64 bank = dual ? 1 : 0; 65 blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLm); 66 sblk = SOC_BLOCK2SCH(pcid_info->unit, blk); 67 addr = soc_mem_addr_get(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLm, 0, 68 blk, 0, &acc_type); 69 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp_hs); 70 use_lsb = soc_mem_field32_get(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLm, 71 tmp_hs, HASH_TABLE_TEST_MODEf); 72 hash_sel = soc_mem_field32_get(pcid_info->unit, 73 MPLS_ENTRY_HASH_CONTROLm, tmp_hs, 74 fields[bank]); 75 76 index = soc_tomahawk3_mpls_entry_hash(pcid_info->unit, bank, hash_sel, 77 use_lsb, (uint32 *)entry); 78 79 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META("index %d\n"), index)); 80 81 return index; 82 } else 83 #endif /* BCM_TOMAHAWK3_SUPPORT */ 84 { 85 soc_internal_extended_read_reg(pcid_info, blk, at, 86 soc_reg_addr_get(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLr, 87 REG_PORT_ANY, 0, SOC_REG_ADDR_OPTION_NONE, 88 &blk, &at), tmp_hs); 89 if (dual) { 90 hash_sel = soc_reg_field_get(pcid_info->unit, 91 MPLS_ENTRY_HASH_CONTROLr, 92 tmp_hs[0], HASH_SELECT_Bf); 93 } else { 94 hash_sel = soc_reg_field_get(pcid_info->unit, 95 MPLS_ENTRY_HASH_CONTROLr, tmp_hs[0], 96 HASH_SELECT_Af); 97 } 98 } 99 100 LOG_VERBOSE(BSL_LS_SOC_COMMON, 101 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 102 103 #ifdef BCM_TRIDENT2_SUPPORT 104 if (SOC_IS_TD2_TT2(pcid_info->unit)) { 105 bits = soc_td2_mpls_base_entry_to_key(pcid_info->unit, dual, entry, key); 106 index = soc_td2_mpls_hash(pcid_info->unit, hash_sel, bits, entry, key); 107 } else 108 #endif /* BCM_TRIDENT2_SUPPORT */ 109 { 110 bits = soc_tr_mpls_base_entry_to_key(pcid_info->unit, (uint32 *)entry, 111 key); 112 index = soc_tr_mpls_hash(pcid_info->unit, hash_sel, bits, 113 (uint32 *)entry, key); 114 } 115 116 LOG_VERBOSE(BSL_LS_SOC_COMMON, 117 (BSL_META("index %d\n"), index)); 118 119 return index; 120 } 121 122 void 123 soc_internal_mpls_dual_banks(pcid_info_t *pcid_info, uint8 banks, 124 int *dual, int *slot_min, int *slot_max) 125 { 126 /* Dual hash always enabled for MPLS_ENTRY */ 127 *dual = TRUE; 128 129 if (*dual) { 130 switch (banks) { 131 case 0: 132 return; /* Nothing to do here */ 133 case 1: 134 *slot_min = 4; 135 *slot_max = 7; 136 break; 137 case 2: 138 *slot_min = 0; 139 *slot_max = 3; 140 break; 141 #if defined(BCM_TOMAHAWK3_SUPPORT) 142 case 3: 143 if (SOC_IS_TOMAHAWK3(pcid_info->unit)) { 144 *slot_min = 0; 145 *slot_max = 7; 146 } 147 break; 148 #endif /* BCM_TOMAHAWK3_SUPPORT */ 149 default: 150 *slot_min = 0; 151 *slot_max = -1; 152 break; 153 } 154 } 155 156 return; 157 } 158 159 int 160 soc_internal_mpls_entry_read(pcid_info_t * pcid_info, uint32 addr, 161 mpls_entry_entry_t *entry) 162 { 163 int index = (addr & 0x3fff); 164 int blk; 165 soc_block_t sblk; 166 uint8 at; 167 uint32 address; 168 soc_mem_t mem; 169 170 mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm; 171 172 blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem); 173 sblk = SOC_BLOCK2SCH(pcid_info->unit, blk); 174 address = soc_mem_addr_get(pcid_info->unit, mem, 0, 175 blk, index, &at); 176 177 LOG_VERBOSE(BSL_LS_SOC_COMMON, 178 (BSL_META("mpls_entry read addr=0x%x\n"), addr)); 179 180 soc_internal_extended_read_mem(pcid_info, sblk, 0, address, (uint32 *) entry); 181 182 return 0; 183 } 184 185 int 186 soc_internal_mpls_entry_write(pcid_info_t * pcid_info, uint32 addr, 187 mpls_entry_entry_t *entry) 188 { 189 int index = (addr & 0x3fff); 190 int blk; 191 soc_block_t sblk; 192 uint8 at; 193 uint32 address; 194 soc_mem_t mem; 195 196 mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm; 197 198 blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem); 199 sblk = SOC_BLOCK2SCH(pcid_info->unit, blk); 200 address = soc_mem_addr_get(pcid_info->unit, mem, 0, 201 blk, index, &at); 202 203 LOG_VERBOSE(BSL_LS_SOC_COMMON, 204 (BSL_META("mpls_entry write addr=0x%x\n"), addr)); 205 206 soc_internal_extended_write_mem(pcid_info, sblk, 0, address, (uint32 *) entry); 207 208 return 0; 209 } 210 211 int 212 soc_internal_mpls_entry_ins(pcid_info_t *pcid_info, uint8 banks, 213 mpls_entry_entry_t *entry, uint32 *result) 214 { 215 uint32 tmp[SOC_MAX_MEM_WORDS]; 216 int index = 0, bucket, slot, free_index; 217 int slot_min = 0, slot_max = 7, dual = FALSE; 218 int unit = pcid_info->unit; 219 schan_genresp_t *genresp = (schan_genresp_t *)result; 220 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 221 int blk; 222 soc_block_t sblk; 223 uint8 acc_type; 224 uint32 addr; 225 soc_mem_t mem; 226 soc_field_t valid_fld; 227 228 LOG_VERBOSE(BSL_LS_SOC_COMMON, 229 (BSL_META_U(unit, 230 "MPLS_ENTRY Insert\n"))); 231 232 233 mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm; 234 235 valid_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf; 236 237 bucket = soc_internal_mpls_hash(pcid_info, entry, FALSE); 238 239 LOG_VERBOSE(BSL_LS_SOC_COMMON, 240 (BSL_META_U(unit, 241 "bucket %d\n"), bucket)); 242 243 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 244 soc_internal_mpls_dual_banks(pcid_info, banks, 245 &dual, &slot_min, &slot_max); 246 } 247 blk = SOC_MEM_BLOCK_ANY(unit, mem); 248 sblk = SOC_BLOCK2SCH(unit, blk); 249 250 /* Check if it should overwrite an existing entry */ 251 free_index = -1; 252 for (slot = slot_min; slot <= slot_max; slot++) { 253 if (dual && (slot == 4)) { 254 bucket = soc_internal_mpls_hash(pcid_info, entry, TRUE); 255 } 256 index = bucket * 8 + slot; 257 addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type); 258 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 259 if (soc_mem_field32_get(unit, mem, tmp, valid_fld)) { 260 if (soc_mem_compare_key(unit, mem, entry, tmp) == 0) { 261 LOG_VERBOSE(BSL_LS_SOC_COMMON, 262 (BSL_META_U(unit, 263 "write sblk %d acc_type %d bucket %d, " 264 "slot %d, index %d\n"), 265 sblk, acc_type, index / 8, index % 8, index)); 266 267 /* Overwrite the existing entry */ 268 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 269 addr, (uint32 *)entry); 270 271 /* Copy old entry immediately after response word */ 272 memcpy(&result[1], tmp, 273 soc_mem_entry_bytes(unit, mem)); 274 275 result[0] = 0; 276 if (soc_feature(unit, soc_feature_new_sbus_format) && 277 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 278 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 279 genresp_v2->index = index; 280 } else { 281 genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED; 282 genresp->index = index; 283 } 284 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 285 286 return 0; 287 } 288 } else { 289 if (free_index == -1) { 290 free_index = index; 291 } 292 } 293 } 294 295 /* Find first unused slot in bucket */ 296 if (free_index != -1) { 297 index = free_index; 298 addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type); 299 300 LOG_VERBOSE(BSL_LS_SOC_COMMON, 301 (BSL_META_U(unit, 302 "write sblk %d acc_type %d bucket %d, slot %d, " 303 "index %d\n"), 304 sblk, acc_type, index / 8, index % 8, index)); 305 306 /* Write the new entry */ 307 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 308 (uint32 *)entry); 309 310 result[0] = 0; 311 if (soc_feature(unit, soc_feature_new_sbus_format) && 312 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 313 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 314 genresp_v2->index = index; 315 } else { 316 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED; 317 genresp->index = index; 318 } 319 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 320 321 return 0; 322 } 323 324 LOG_VERBOSE(BSL_LS_SOC_COMMON, 325 (BSL_META_U(unit, 326 "Bucket full\n"))); 327 328 result[0] = 0; 329 if (soc_feature(unit, soc_feature_new_sbus_format) && 330 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 331 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 332 } else { 333 genresp->type = SCHAN_GEN_RESP_TYPE_FULL; 334 } 335 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 336 337 return 0; 338 } 339 340 int 341 soc_internal_mpls_entry_del(pcid_info_t * pcid_info, uint8 banks, 342 mpls_entry_entry_t *entry, uint32 *result) 343 { 344 uint32 tmp[SOC_MAX_MEM_WORDS]; 345 int index = 0, bucket, slot; 346 int slot_min = 0, slot_max = 7, dual = FALSE; 347 int unit = pcid_info->unit; 348 schan_genresp_t *genresp = (schan_genresp_t *)result; 349 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 350 int blk; 351 soc_block_t sblk; 352 uint8 acc_type; 353 uint32 addr; 354 soc_mem_t mem; 355 soc_field_t valid_fld; 356 357 mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm; 358 359 valid_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf; 360 361 LOG_VERBOSE(BSL_LS_SOC_COMMON, 362 (BSL_META_U(unit, 363 "MPLS_ENTRY Delete\n"))); 364 365 bucket = soc_internal_mpls_hash(pcid_info, entry, FALSE); 366 367 LOG_VERBOSE(BSL_LS_SOC_COMMON, 368 (BSL_META_U(unit, 369 "bucket %d\n"), bucket)); 370 371 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 372 soc_internal_mpls_dual_banks(pcid_info, banks, &dual, &slot_min, 373 &slot_max); 374 } 375 blk = SOC_MEM_BLOCK_ANY(unit, mem); 376 sblk = SOC_BLOCK2SCH(unit, blk); 377 378 /* Check if entry exists */ 379 for (slot = slot_min; slot <= slot_max; slot++) { 380 if (dual && (slot == 4)) { 381 bucket = soc_internal_mpls_hash(pcid_info, entry, TRUE); 382 } 383 index = bucket * 8 + slot; 384 addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type); 385 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 386 if (soc_mem_field32_get(unit, mem, tmp, valid_fld)) { 387 if (soc_mem_compare_key(unit, mem, entry, tmp) == 0) { 388 LOG_VERBOSE(BSL_LS_SOC_COMMON, 389 (BSL_META_U(unit, 390 "found sblk %d acc_type %d bucket %d, " 391 "slot %d, index %d\n"), 392 sblk, acc_type, bucket, slot, index)); 393 394 /* Copy entry immediately after response word */ 395 memcpy(&result[1], tmp, 396 soc_mem_entry_bytes(unit, mem)); 397 398 /* Invalidate entry */ 399 soc_mem_field32_set(unit, mem, tmp, valid_fld, 0); 400 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 401 addr, tmp); 402 403 result[0] = 0; 404 if (soc_feature(unit, soc_feature_new_sbus_format) && 405 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 406 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 407 genresp_v2->index = index; 408 } else { 409 genresp->type = SCHAN_GEN_RESP_TYPE_DELETED; 410 genresp->index = index; 411 } 412 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 413 414 return 0; 415 } 416 } 417 } 418 419 LOG_VERBOSE(BSL_LS_SOC_COMMON, 420 (BSL_META_U(unit, 421 "soc_internal_mpls_entry_del: Not found\n"))); 422 423 result[0] = 0; 424 if (soc_feature(unit, soc_feature_new_sbus_format) && 425 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 426 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 427 } else { 428 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 429 } 430 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 431 432 return 0; 433 } 434 435 int 436 soc_internal_mpls_entry_lkup(pcid_info_t * pcid_info, uint8 banks, 437 mpls_entry_entry_t *entry, uint32 *result) 438 { 439 uint32 tmp[SOC_MAX_MEM_WORDS]; 440 int index = 0, bucket, slot; 441 int slot_min = 0, slot_max = 7, dual = FALSE; 442 int unit = pcid_info->unit; 443 schan_genresp_t *genresp = (schan_genresp_t *)result; 444 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 445 int blk; 446 soc_block_t sblk; 447 uint8 acc_type; 448 uint32 addr; 449 soc_mem_t mem; 450 soc_field_t valid_fld; 451 452 mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm; 453 454 valid_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf; 455 456 LOG_VERBOSE(BSL_LS_SOC_COMMON, 457 (BSL_META_U(unit, 458 "MPLS_ENTRY Lookup\n"))); 459 460 bucket = soc_internal_mpls_hash(pcid_info, entry, FALSE); 461 462 LOG_VERBOSE(BSL_LS_SOC_COMMON, 463 (BSL_META_U(unit, 464 "bucket %d\n"), bucket)); 465 466 if (soc_feature(unit, soc_feature_dual_hash)) { 467 soc_internal_mpls_dual_banks(pcid_info, banks, &dual, &slot_min, 468 &slot_max); 469 } 470 blk = SOC_MEM_BLOCK_ANY(unit, mem); 471 sblk = SOC_BLOCK2SCH(unit, blk); 472 473 /* Check if entry exists */ 474 for (slot = slot_min; slot <= slot_max; slot++) { 475 if (dual && (slot == 4)) { 476 bucket = soc_internal_mpls_hash(pcid_info, entry, TRUE); 477 } 478 index = bucket * 8 + slot; 479 addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type); 480 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 481 if (soc_mem_field32_get(unit, mem, tmp, valid_fld)) { 482 if (soc_mem_compare_key(unit, mem, entry, tmp) == 0) { 483 LOG_VERBOSE(BSL_LS_SOC_COMMON, 484 (BSL_META_U(unit, 485 "found sblk %d acc_type %d bucket %d, " 486 "slot %d, index %d\n"), 487 sblk, acc_type, bucket, slot, index)); 488 489 /* Copy entry immediately after response word */ 490 memcpy(&result[1], tmp, 491 soc_mem_entry_bytes(unit, mem)); 492 493 result[0] = 0; 494 if (soc_feature(unit, soc_feature_new_sbus_format) && 495 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 496 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 497 genresp_v2->index = index; 498 } else { 499 genresp->type = SCHAN_GEN_RESP_TYPE_FOUND; 500 genresp->index = index; 501 } 502 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 503 504 return 0; 505 } 506 } 507 } 508 509 LOG_VERBOSE(BSL_LS_SOC_COMMON, 510 (BSL_META_U(unit, 511 "soc_internal_mpls_entry_lkup: Not found\n"))); 512 513 result[0] = 0; 514 if (soc_feature(unit, soc_feature_new_sbus_format) && 515 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 516 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 517 } else { 518 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 519 } 520 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 521 522 return 0; 523 } 524 #endif /* BCM_TRIUMPH_SUPPORT */