l2x.c (48872B)
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: l2x.c 8 * 9 * Provides: 10 * soc_internal_l2x_read 11 * soc_internal_l2x_write 12 * soc_internal_l2x_lkup 13 * soc_internal_l2x_init 14 * soc_internal_l2x_del 15 * soc_internal_l2x_ins 16 * 17 * Requires: 18 */ 19 20 #include <shared/bsl.h> 21 22 #include <soc/mem.h> 23 #include <soc/hash.h> 24 #include <soc/drv.h> 25 #include <soc/l2x.h> 26 #ifdef BCM_TRIDENT2_SUPPORT 27 #include <soc/trident2.h> 28 #endif /* BCM_TRIDENT2_SUPPORT */ 29 #ifdef BCM_TOMAHAWK_SUPPORT 30 #include <soc/tomahawk.h> 31 #endif /* BCM_TOMAHAWK_SUPPORT */ 32 #ifdef BCM_TOMAHAWK3_SUPPORT 33 #include <soc/tomahawk3.h> 34 #endif /* BCM_TOMAHAWK3_SUPPORT */ 35 #ifdef BCM_APACHE_SUPPORT 36 #include <soc/apache.h> 37 #endif /* BCM_APACHE_SUPPORT */ 38 #ifdef BCM_MONTEREY_SUPPORT 39 #include <soc/apache.h> 40 #endif /* BCM_MONTEREY_SUPPORT */ 41 42 #include "pcid.h" 43 #include "mem.h" 44 #include "cmicsim.h" 45 46 #ifdef BCM_XGS_SWITCH_SUPPORT 47 #ifdef BCM_FIREBOLT_SUPPORT 48 int 49 soc_internal_l2x2_hash(pcid_info_t * pcid_info, l2x_entry_t *entry, int dual) 50 { 51 uint32 tmp_hs[SOC_MAX_MEM_WORDS]; 52 int hash_sel; 53 uint8 at, key[8]; 54 int index; 55 soc_block_t blk; 56 57 LOG_VERBOSE(BSL_LS_SOC_COMMON, 58 (BSL_META("L2X2 hash\n"))); 59 60 if (dual) { 61 soc_internal_extended_read_reg(pcid_info, blk, at, 62 soc_reg_addr_get(pcid_info->unit, L2_AUX_HASH_CONTROLr, 63 REG_PORT_ANY, 0, 64 SOC_REG_ADDR_OPTION_NONE, &blk, &at), 65 tmp_hs); 66 hash_sel = soc_reg_field_get(pcid_info->unit, L2_AUX_HASH_CONTROLr, 67 tmp_hs[0], HASH_SELECTf); 68 } else { 69 soc_internal_extended_read_reg(pcid_info, blk, at, 70 soc_reg_addr_get(pcid_info->unit, HASH_CONTROLr, REG_PORT_ANY, 71 0, SOC_REG_ADDR_OPTION_NONE, &blk, &at), 72 tmp_hs); 73 hash_sel = soc_reg_field_get(pcid_info->unit, HASH_CONTROLr, 74 tmp_hs[0], L2_AND_VLAN_MAC_HASH_SELECTf); 75 } 76 77 LOG_VERBOSE(BSL_LS_SOC_COMMON, 78 (BSL_META("hash_sel%s %d\n"), dual ? "" : "(aux)", hash_sel)); 79 80 soc_draco_l2x_base_entry_to_key(pcid_info->unit, entry, key); 81 82 index = soc_fb_l2_hash(pcid_info->unit, hash_sel, key); 83 84 if (SOC_IS_FIREBOLT2(pcid_info->unit)) { 85 uint32 addr_mask; 86 soc_internal_read_reg(pcid_info, 87 soc_reg_addr(pcid_info->unit, L2_ENTRY_ADDR_MASKr, 88 REG_PORT_ANY, 0), 89 tmp_hs); 90 addr_mask = soc_reg_field_get(pcid_info->unit, L2_ENTRY_ADDR_MASKr, 91 tmp_hs[0], MASKf); 92 index &= addr_mask; 93 } 94 95 LOG_VERBOSE(BSL_LS_SOC_COMMON, 96 (BSL_META("index %d\n"), index)); 97 98 return index; 99 } 100 101 void 102 soc_internal_l2x2_dual_banks(pcid_info_t *pcid_info, uint8 banks, 103 int *dual, int *slot_min, int *slot_max) 104 { 105 uint32 tmp[SOC_MAX_MEM_WORDS]; 106 soc_block_t blk; 107 uint8 at; 108 109 soc_internal_extended_read_reg(pcid_info, blk, at, 110 soc_reg_addr_get(pcid_info->unit, 111 L2_AUX_HASH_CONTROLr, 112 REG_PORT_ANY, 0, 113 SOC_REG_ADDR_OPTION_NONE, &blk, &at), 114 tmp); 115 *dual = soc_reg_field_get(pcid_info->unit, L2_AUX_HASH_CONTROLr, 116 tmp[0], ENABLEf); 117 118 if (*dual) { 119 switch (banks) { 120 case 0: 121 return; /* Nothing to do here */ 122 case 1: 123 *slot_min = 4; 124 *slot_max = 7; 125 break; 126 case 2: 127 *slot_min = 0; 128 *slot_max = 3; 129 break; 130 default: 131 *slot_min = 0; 132 *slot_max = -1; 133 break; 134 } 135 } 136 137 return; 138 } 139 140 int 141 soc_internal_l2x2_entry_ins(pcid_info_t *pcid_info, uint8 banks, 142 l2x_entry_t *entry, uint32 *result) 143 { 144 uint32 tmp[SOC_MAX_MEM_WORDS]; 145 int index = 0, bucket, slot, free_index; 146 int slot_min = 0, slot_max = 7, dual = FALSE; 147 int unit = pcid_info->unit; 148 int op_fail_pos; 149 uint8 at; 150 151 LOG_VERBOSE(BSL_LS_SOC_COMMON, 152 (BSL_META_U(unit, 153 "l2_entry Insert\n"))); 154 155 bucket = soc_internal_l2x2_hash(pcid_info, entry, FALSE); 156 157 LOG_VERBOSE(BSL_LS_SOC_COMMON, 158 (BSL_META_U(unit, 159 "bucket %d\n"), bucket)); 160 161 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 162 soc_internal_l2x2_dual_banks(pcid_info, banks, 163 &dual, &slot_min, &slot_max); 164 } 165 166 /* Check if it should overwrite an existing entry */ 167 free_index = -1; 168 for (slot = slot_min; slot <= slot_max; slot++) { 169 if (dual && (slot == 4)) { 170 bucket = soc_internal_l2x2_hash(pcid_info, entry, TRUE); 171 } 172 index = bucket * 8 + slot; 173 soc_internal_extended_read_mem(pcid_info, 174 SOC_MEM_BLOCK_ANY(unit, L2Xm), at, 175 soc_mem_addr_get(unit, L2Xm, 0, 176 SOC_MEM_BLOCK_ANY(unit, L2Xm), 177 index, &at), 178 tmp); 179 if (soc_mem_field32_get(unit, L2Xm, tmp, VALIDf)) { 180 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) { 181 /* Overwrite the existing entry */ 182 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 183 184 LOG_VERBOSE(BSL_LS_SOC_COMMON, 185 (BSL_META_U(unit, 186 "write bucket %d, slot %d, index %d\n"), 187 index / 8, index % 8, index)); 188 soc_internal_extended_write_mem(pcid_info, 189 SOC_MEM_BLOCK_ANY(unit, L2Xm), at, 190 soc_mem_addr_get(unit, L2Xm, 0, 191 SOC_MEM_BLOCK_ANY(unit, L2Xm), 192 index, &at), 193 (uint32 *)entry); 194 195 result[3] = 0x000; 196 return 0; 197 } 198 } else { 199 if (free_index == -1) { 200 free_index = index; 201 } 202 } 203 } 204 205 /* Find first unused slot in bucket */ 206 if (free_index != -1) { 207 index = free_index; 208 209 /* Write the existing entry */ 210 result[3] = 0x000; 211 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 212 213 LOG_VERBOSE(BSL_LS_SOC_COMMON, 214 (BSL_META_U(unit, 215 "write bucket %d, slot %d, index %d\n"), 216 index / 8, index % 8, index)); 217 soc_internal_extended_write_mem(pcid_info, 218 SOC_MEM_BLOCK_ANY(unit, L2Xm), at, 219 soc_mem_addr_get(unit, L2Xm, 0, 220 SOC_MEM_BLOCK_ANY(unit, L2Xm), 221 index, &at), 222 (uint32 *)entry); 223 return 0; 224 } 225 226 LOG_VERBOSE(BSL_LS_SOC_COMMON, 227 (BSL_META_U(unit, 228 "Bucket full\n"))); 229 230 /* 231 * ============================================================= 232 * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index | L2x entry data | 233 * ============================================================= 234 */ 235 op_fail_pos = SOC_L2X_OP_FAIL_POS(unit); 236 237 result[3] = (1 << op_fail_pos); 238 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 239 return 0; 240 } 241 242 int 243 soc_internal_l2x2_entry_del(pcid_info_t * pcid_info, uint8 banks, 244 l2x_entry_t *entry, uint32 *result) 245 { 246 uint32 tmp[SOC_MAX_MEM_WORDS]; 247 int op_fail_pos; 248 int index = 0, bucket, slot; 249 int slot_min = 0, slot_max = 7, dual = FALSE; 250 int unit = pcid_info->unit; 251 252 LOG_VERBOSE(BSL_LS_SOC_COMMON, 253 (BSL_META_U(unit, 254 "l2_entry Delete\n"))); 255 256 bucket = soc_internal_l2x2_hash(pcid_info, entry, FALSE); 257 258 LOG_VERBOSE(BSL_LS_SOC_COMMON, 259 (BSL_META_U(unit, 260 "bucket %d\n"), bucket)); 261 262 /* 263 * ============================================================= 264 * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index | L2x entry data | 265 * ============================================================= 266 */ 267 op_fail_pos = SOC_L2X_OP_FAIL_POS(unit); 268 269 result[3] = (1 << op_fail_pos); 270 271 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 272 soc_internal_l2x2_dual_banks(pcid_info, banks, 273 &dual, &slot_min, &slot_max); 274 } 275 276 /* Check if entry exists */ 277 for (slot = slot_min; slot <= slot_max; slot++) { 278 if (dual && (slot == 4)) { 279 bucket = soc_internal_l2x2_hash(pcid_info, entry, TRUE); 280 } 281 index = bucket * 8 + slot; 282 soc_internal_read_mem(pcid_info, soc_mem_addr(unit, L2Xm, 0, 283 SOC_MEM_BLOCK_ANY(unit, L2Xm), 284 index), tmp); 285 if (soc_mem_field32_get(unit, L2Xm, tmp, VALIDf)) { 286 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) { 287 result[3] = 0x000; 288 289 /* Invalidate entry */ 290 soc_mem_field32_set(unit, L2Xm, tmp, VALIDf, 0); 291 soc_internal_write_mem(pcid_info, 292 soc_mem_addr(unit, L2Xm, 0, 293 SOC_MEM_BLOCK_ANY(unit, L2Xm), 294 index), (uint32 *)tmp); 295 } 296 } 297 } 298 299 LOG_VERBOSE(BSL_LS_SOC_COMMON, 300 (BSL_META_U(unit, 301 "Not found\n"))); 302 303 return 0; 304 } 305 306 /* 307 * soc_internal_l2x2_entry_lkup 308 * 309 * Note: entry_lookup and entry_result may overlap. 310 */ 311 312 int 313 soc_internal_l2x2_entry_lkup(pcid_info_t * pcid_info, uint8 banks, 314 l2x_entry_t *entry_lookup, uint32 *result) 315 { 316 uint32 tmp[SOC_MAX_MEM_WORDS]; 317 int op_fail_pos; 318 int index = 0, bucket, slot; 319 int slot_min = 0, slot_max = 7, dual = FALSE; 320 int unit = pcid_info->unit; 321 uint8 at; 322 323 LOG_VERBOSE(BSL_LS_SOC_COMMON, 324 (BSL_META_U(unit, 325 "l2_entry Lookup\n"))); 326 327 bucket = soc_internal_l2x2_hash(pcid_info, entry_lookup, FALSE); 328 329 LOG_VERBOSE(BSL_LS_SOC_COMMON, 330 (BSL_META_U(unit, 331 "bucket %d\n"), bucket)); 332 333 /* 334 * ============================================================= 335 * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index | L2x entry data | 336 * ============================================================= 337 */ 338 op_fail_pos = SOC_L2X_OP_FAIL_POS(unit); 339 340 result[3] = (1 << op_fail_pos); 341 342 343 if (soc_feature(unit, soc_feature_dual_hash)) { 344 soc_internal_l2x2_dual_banks(pcid_info, banks, 345 &dual, &slot_min, &slot_max); 346 } 347 348 /* Check if entry exists */ 349 for (slot = slot_min; slot <= slot_max; slot++) { 350 if (dual && (slot == 4)) { 351 bucket = soc_internal_l2x2_hash(pcid_info, entry_lookup, TRUE); 352 } 353 index = bucket * 8 + slot; 354 soc_internal_extended_read_mem(pcid_info, 355 SOC_MEM_BLOCK_ANY(unit, L2Xm), at, 356 soc_mem_addr_get(unit, L2Xm, 0, 357 SOC_MEM_BLOCK_ANY(unit, L2Xm), 358 index, &at), 359 tmp); 360 if (soc_mem_field32_get(unit, L2Xm, tmp, VALIDf)) { 361 if (soc_mem_compare_key(unit, L2Xm, entry_lookup, tmp) == 0) { 362 int nbits; /* Data Bits in last word */ 363 364 nbits = soc_mem_entry_bits(unit, L2Xm) % 32; 365 366 result[0] = tmp[0]; 367 result[1] = tmp[1]; 368 if (nbits) { 369 result[2] = (tmp[2] & ((1 << nbits) - 1)) | 370 ((index & ((1 << (32 - nbits)) - 1)) << nbits); 371 result[3] = (index >> (32 - nbits)) & 372 ((soc_mem_index_max(unit, L2Xm)) >> (32 - nbits)); 373 } else { 374 result[2] = index; 375 result[3] = 0; 376 } 377 return 0; 378 } 379 } 380 } 381 382 LOG_VERBOSE(BSL_LS_SOC_COMMON, 383 (BSL_META_U(unit, 384 "Not found\n"))); 385 386 return 0; 387 } 388 #endif /* BCM_FIREBOLT_SUPPORT */ 389 390 #ifdef BCM_TRX_SUPPORT 391 STATIC int 392 soc_internal_l2_tr_bucket_get(pcid_info_t *pcid_info, int bank, void *entry) 393 { 394 uint32 rval[SOC_MAX_MEM_WORDS]; 395 int bucket, hash_sel; 396 int unit = pcid_info->unit; 397 int blk; 398 uint8 acc_type; 399 uint32 addr; 400 401 #if defined(BCM_TOMAHAWK3_SUPPORT) 402 if (SOC_IS_TOMAHAWK3(pcid_info->unit)) { 403 soc_block_t sblk; 404 int use_lsb; 405 static const soc_field_t fields[] = { 406 HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f 407 }; 408 if (bank < 0 || bank > 1) { 409 return -1; 410 } 411 blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_HASH_CONTROLm); 412 sblk = SOC_BLOCK2SCH(unit, blk); 413 addr = soc_mem_addr_get( 414 unit, L2_ENTRY_HASH_CONTROLm, 0, blk, 0, &acc_type); 415 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, rval); 416 use_lsb = soc_mem_field32_get( 417 unit, L2_ENTRY_HASH_CONTROLm, rval, HASH_TABLE_TEST_MODEf); 418 hash_sel = soc_mem_field32_get( 419 unit, L2_ENTRY_HASH_CONTROLm, rval, fields[bank]); 420 bucket = soc_tomahawk3_l2x_entry_hash(unit, bank, hash_sel, use_lsb, entry); 421 } else 422 #endif /* BCM_TOMAHAWK3_SUPPORT */ 423 #ifdef BCM_TRIDENT2_SUPPORT 424 if (SOC_IS_TD2_TT2(unit)) { 425 int hash_offset, use_lsb, index; 426 soc_reg_t reg; 427 static const soc_field_t fields[] = { 428 BANK0_HASH_OFFSETf, BANK1_HASH_OFFSETf, BANK2_HASH_OFFSETf, 429 BANK3_HASH_OFFSETf, BANK4_HASH_OFFSETf, BANK5_HASH_OFFSETf 430 }; 431 int is_shared_bank; 432 uint32 (*entry_hash_proc)(int unit, int bank, int hash_offset, 433 int use_lsb, uint32 *entry); 434 435 #if defined(BCM_TOMAHAWK_SUPPORT) 436 if (SOC_IS_TOMAHAWKX(unit)) { 437 static const soc_field_t l2_fields[] = { 438 L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f, 439 L2_ENTRY_BANK_5f 440 }; 441 entry_hash_proc = soc_th_l2x_entry_hash; 442 if (bank < 2) { 443 is_shared_bank = FALSE; 444 index = bank; 445 } else { 446 is_shared_bank = TRUE; 447 addr = soc_reg_addr_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, 448 REG_PORT_ANY, 0, 449 SOC_REG_ADDR_OPTION_NONE, 450 &blk, &acc_type); 451 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, 452 rval); 453 index = soc_reg_field_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, 454 rval[0], l2_fields[bank - 2]) + 2; 455 } 456 } else 457 #endif /* BCM_TOMAHAWK_SUPPORT */ 458 #if defined(BCM_APACHE_SUPPORT) 459 if (SOC_IS_APACHE(unit)) { 460 static const soc_field_t l2_fields[] = { 461 L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f, 462 L2_ENTRY_BANK_5f 463 }; 464 entry_hash_proc = soc_ap_l2x_entry_hash; 465 466 if (bank < 2) { 467 is_shared_bank = FALSE; 468 index = bank; 469 } else { 470 is_shared_bank = TRUE; 471 addr = soc_reg_addr_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, 472 REG_PORT_ANY, 0, 473 SOC_REG_ADDR_OPTION_NONE, 474 &blk, &acc_type); 475 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, 476 rval); 477 index = soc_reg_field_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, 478 rval[0], l2_fields[bank - 2]) + 2; 479 } 480 481 482 483 484 } else 485 #endif /* BCM_APACHE_SUPPORT */ 486 { 487 entry_hash_proc = soc_td2_l2x_entry_hash; 488 is_shared_bank = bank > 1; 489 index = bank; 490 } 491 492 reg = L2_TABLE_HASH_CONTROLr; 493 addr = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0, 494 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 495 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval); 496 use_lsb = soc_reg_field_get(unit, reg, rval[0], HASH_ZERO_OR_LSBf); 497 498 if (is_shared_bank) { 499 reg = SHARED_TABLE_HASH_CONTROLr; 500 addr = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0, 501 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 502 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, 503 rval); 504 } 505 hash_offset = soc_reg_field_get(unit, reg, rval[0], fields[index]); 506 bucket = entry_hash_proc(unit, bank, hash_offset, use_lsb, entry); 507 } else 508 #endif /* BCM_TRIDENT2_SUPPORT */ 509 { 510 hash_sel = -1; 511 if (bank == 1) { 512 addr = soc_reg_addr_get(unit, L2_AUX_HASH_CONTROLr, REG_PORT_ANY, 513 0, SOC_REG_ADDR_OPTION_NONE, 514 &blk, &acc_type); 515 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, 516 rval); 517 if (soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr, rval[0], 518 ENABLEf)) { 519 hash_sel = soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr, 520 rval[0], HASH_SELECTf); 521 } 522 } 523 if (hash_sel == -1) { 524 addr = soc_reg_addr_get(unit, HASH_CONTROLr, REG_PORT_ANY, 0, 525 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 526 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, 527 rval); 528 hash_sel = soc_reg_field_get(unit, HASH_CONTROLr, rval[0], 529 L2_AND_VLAN_MAC_HASH_SELECTf); 530 } 531 532 bucket = soc_tr_l2x_entry_hash(unit, hash_sel, entry); 533 } 534 535 LOG_VERBOSE(BSL_LS_SOC_COMMON, 536 (BSL_META_U(unit, 537 "bank %d bucket %d\n"), bank, bucket)); 538 539 return bucket; 540 } 541 542 STATIC void 543 soc_internal_l2_tr_bank_map_get(pcid_info_t *pcid_info, uint32 *bank_map, 544 int *bank_start, int *bank_inc, 545 int *do_first_fit) 546 { 547 uint32 rval[SOC_MAX_MEM_WORDS]; 548 int unit = pcid_info->unit; 549 int blk; 550 uint8 acc_type; 551 uint32 addr; 552 553 #if defined(BCM_TOMAHAWK3_SUPPORT) || defined(BCM_MONTEREY_SUPPORT) 554 if (SOC_IS_TOMAHAWK3(pcid_info->unit) || SOC_IS_MONTEREY(pcid_info->unit)) { 555 556 *bank_map = 0x3; 557 *bank_start = 0; 558 *bank_inc = 1; 559 if (do_first_fit != NULL) { 560 *do_first_fit = FALSE; 561 } 562 } else 563 #endif /* BCM_TOMAHAWK_SUPPORT3 or BCM_MONTEREY_SUPPORT*/ 564 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 565 if (SOC_IS_TOMAHAWKX(pcid_info->unit) || SOC_IS_APACHE(pcid_info->unit)) { 566 uint32 shared_bank_map; 567 int bit_count; 568 #ifdef BCM_APACHE_SUPPORT 569 if (SOC_IS_APACHE(pcid_info->unit)) { 570 addr = soc_reg_addr_get(unit, L2_ISS_BANK_CONFIGr, REG_PORT_ANY, 0, 571 FALSE, &blk, &acc_type); 572 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval); 573 shared_bank_map = soc_reg_field_get(unit, L2_ISS_BANK_CONFIGr, 574 rval[0], L2_ENTRY_BANK_CONFIGf); 575 } else 576 577 #endif /* BCM_APACHE_SUPPORT */ 578 { 579 580 addr = soc_reg_addr_get(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, 581 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 582 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval); 583 shared_bank_map = soc_reg_field_get(unit, ISS_BANK_CONFIGr, 584 rval[0], L2_ENTRY_BANK_CONFIGf); 585 } 586 /* calculate number of 1's in shared_bank_map */ 587 bit_count = shared_bank_map - ((shared_bank_map >> 1) & 0x5); 588 bit_count = ((bit_count & 0xc) >> 2) + (bit_count & 0x3); 589 590 *bank_map = (1 << (bit_count + 2)) - 1; 591 *bank_start = 0; 592 *bank_inc = 1; 593 if (do_first_fit != NULL) { 594 *do_first_fit = FALSE; 595 } 596 } else 597 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_APACHE_SUPPORT */ 598 #ifdef BCM_TRIDENT2_SUPPORT 599 if (SOC_IS_TD2_TT2(pcid_info->unit)) { 600 int mode; 601 602 addr = soc_reg_addr_get(unit, L2_TABLE_HASH_CONTROLr, REG_PORT_ANY, 0, 603 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 604 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval); 605 mode = soc_reg_field_get(unit, L2_TABLE_HASH_CONTROLr, rval[0], MODEf); 606 switch (mode) { 607 case 0: 608 *bank_map = 0x3f; 609 break; 610 case 1: 611 *bank_map = 0x1f; 612 break; 613 case 2: 614 *bank_map = 0xf; 615 break; 616 case 3: 617 *bank_map = 0x7; 618 break; 619 default: 620 *bank_map = 0x3; 621 } 622 *bank_start = 0; 623 *bank_inc = 1; 624 if (do_first_fit != NULL) { 625 *do_first_fit = FALSE; 626 } 627 } else 628 #endif /* BCM_TRIDENT2_SUPPORT */ 629 { 630 *bank_map = 0x3; 631 *bank_start = 0; 632 *bank_inc = 1; 633 634 addr = soc_reg_addr_get(unit, L2_AUX_HASH_CONTROLr, REG_PORT_ANY, 0, 635 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 636 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval); 637 if (do_first_fit != NULL) { 638 *do_first_fit = 639 soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr, rval[0], 640 INSERT_LEAST_FULL_HALFf) ? FALSE : TRUE; 641 } 642 } 643 } 644 645 STATIC void 646 soc_internal_l2_tr_bank_size_get(pcid_info_t *pcid_info, int bank, 647 int *entries_per_bank, int *entries_per_row, 648 int *entries_per_bucket, int *bank_base, 649 int *bucket_offset) 650 { 651 /* 652 * entry index = 653 * bank_base + bucket * entries_per_row + bucket_offest + slot; 654 */ 655 656 #if defined(BCM_TOMAHAWK3_SUPPORT) 657 if (SOC_IS_TOMAHAWK3(pcid_info->unit)) { 658 (void)soc_tomahawk3_hash_bank_info_get(pcid_info->unit, L2Xm, 659 bank, entries_per_bank, 660 entries_per_row, 661 entries_per_bucket, 662 bank_base, bucket_offset); 663 } else 664 #endif /* BCM_TOMAHAWK3_SUPPORT */ 665 #ifdef BCM_APACHE_SUPPORT 666 if (SOC_IS_APACHE(pcid_info->unit)) { 667 (void)soc_apache_hash_bank_info_get(pcid_info->unit, L2Xm, 668 bank, entries_per_bank, 669 entries_per_row, 670 entries_per_bucket, 671 bank_base, bucket_offset); 672 } else 673 #endif /* BCM_TOMAHAWK_SUPPORT */ 674 675 #ifdef BCM_TOMAHAWK_SUPPORT 676 if (SOC_IS_TOMAHAWKX(pcid_info->unit)) { 677 (void)soc_tomahawk_hash_bank_info_get(pcid_info->unit, L2Xm, 678 bank, entries_per_bank, 679 entries_per_row, 680 entries_per_bucket, 681 bank_base, bucket_offset); 682 } else 683 #endif /* BCM_TOMAHAWK_SUPPORT */ 684 #ifdef BCM_TRIDENT2_SUPPORT 685 if (SOC_IS_TD2_TT2(pcid_info->unit)) { 686 (void)soc_trident2_hash_bank_info_get(pcid_info->unit, L2Xm, 687 bank, entries_per_bank, 688 entries_per_row, 689 entries_per_bucket, 690 bank_base, bucket_offset); 691 } else 692 #endif /* BCM_TRIDENT2_SUPPORT */ 693 { 694 /* 695 * 8 entries per bucket 696 * first half of entries (slot 0) in each bucket are for bank 0 697 * the other half of entries (slot 1) in each bucket are for bank 1 698 */ 699 if (entries_per_bank != NULL) { 700 *entries_per_bank = soc_mem_index_count(pcid_info->unit, L2Xm) / 2; 701 } 702 *entries_per_row = 8; 703 *entries_per_bucket = *entries_per_row / 2; 704 *bank_base = 0; 705 *bucket_offset = bank * *entries_per_bucket; 706 } 707 } 708 709 int 710 soc_internal_l2_tr_entry_ins(pcid_info_t *pcid_info, uint32 inv_bank_map, 711 void *entry, uint32 *result) 712 { 713 uint32 tmp[SOC_MAX_MEM_WORDS]; 714 uint32 bank_map; 715 int bank, entries_per_bank, bank_start, bank_inc, free_bank; 716 int bucket, entries_per_row, bank_base, free_bucket; 717 int slot, entries_per_bucket, bucket_offset, free_slot; 718 int index, free_index; 719 int first_free_slot, free_slot_count, do_first_fit; 720 int best_free_slot_count, best_entries_per_bank; 721 int unit = pcid_info->unit; 722 schan_genresp_t *genresp = (schan_genresp_t *) result; 723 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result; 724 int blk; 725 soc_block_t sblk; 726 uint8 acc_type; 727 uint32 addr; 728 soc_field_t vld_fld; 729 #ifdef BCM_HURRICANE3_SUPPORT 730 uint32 l2_entry_overflow_count; 731 #endif /* BCM_HURRICANE3_SUPPORT */ 732 LOG_VERBOSE(BSL_LS_SOC_COMMON, 733 (BSL_META_U(unit, 734 "L2X Insert\n"))); 735 736 blk = SOC_MEM_BLOCK_ANY(unit, L2Xm); 737 sblk = SOC_BLOCK2SCH(unit, blk); 738 739 vld_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf; 740 741 free_index = -1; 742 743 soc_internal_l2_tr_bank_map_get(pcid_info, &bank_map, &bank_start, 744 &bank_inc, &do_first_fit); 745 bank_map &= ~inv_bank_map; 746 747 best_free_slot_count = 0; 748 for (bank = bank_start; bank_map != 0; bank += bank_inc) { 749 if (!(bank_map & (1 << bank))) { 750 continue; 751 } 752 bank_map &= ~(1 << bank); 753 754 soc_internal_l2_tr_bank_size_get(pcid_info, bank, &entries_per_bank, 755 &entries_per_row, &entries_per_bucket, 756 &bank_base, &bucket_offset); 757 bucket = soc_internal_l2_tr_bucket_get(pcid_info, bank, entry); 758 free_slot_count = 0; 759 first_free_slot = -1; 760 for (slot = 0; slot < entries_per_bucket; slot++) { 761 index = bank_base + bucket * entries_per_row + bucket_offset + 762 slot; 763 addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type); 764 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, 765 tmp); 766 if (soc_mem_field32_get(unit, L2Xm, tmp, vld_fld)) { 767 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) { 768 LOG_VERBOSE(BSL_LS_SOC_COMMON, 769 (BSL_META_U(unit, 770 "write sblk %d acc_type %d bank %d " 771 "bucket %d, slot %d, index %d\n"), 772 sblk, acc_type, bank, bucket, slot, index)); 773 774 /* Overwrite the existing entry */ 775 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 776 addr, (uint32 *)entry); 777 778 /* Copy old entry immediately after response word */ 779 memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, L2Xm)); 780 781 result[0] = 0; 782 if (soc_feature(unit, soc_feature_new_sbus_format) && 783 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 784 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 785 genresp_v2->index = index; 786 } else { 787 genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED; 788 genresp->index = index; 789 } 790 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 791 792 return 0; 793 } 794 } else { 795 free_slot_count++; 796 if (first_free_slot == -1) { 797 first_free_slot = slot; 798 } 799 } 800 } 801 if (free_slot_count > 0) { 802 if (do_first_fit) { 803 if (free_index != -1) { 804 continue; 805 } 806 } else { 807 if (free_slot_count < best_free_slot_count) { 808 continue; 809 } else if (free_slot_count == best_free_slot_count) { 810 if (entries_per_bank < best_entries_per_bank) { 811 continue; 812 } else if (entries_per_bank == best_entries_per_bank) { 813 if (free_index != -1 && bank > free_bank) { 814 continue; 815 } 816 } 817 } 818 best_free_slot_count = free_slot_count; 819 best_entries_per_bank = entries_per_bank; 820 } 821 free_index = index + 1 - entries_per_bucket + first_free_slot; 822 free_bank = bank; 823 free_bucket = bucket; 824 free_slot = first_free_slot; 825 } 826 } 827 828 /* Find first unused slot in bucket */ 829 if (free_index != -1) { 830 index = free_index; 831 addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type); 832 833 LOG_VERBOSE(BSL_LS_SOC_COMMON, 834 (BSL_META_U(unit, 835 "write sblk %d acc_type %d bank %d bucket %d, " 836 "slot %d, index %d\n"), 837 sblk, acc_type, free_bank, free_bucket, free_slot, index)); 838 839 /* Write the entry */ 840 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 841 entry); 842 843 result[0] = 0; 844 if (soc_feature(unit, soc_feature_new_sbus_format) && 845 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 846 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 847 genresp_v2->index = index; 848 } else { 849 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED; 850 genresp->index = index; 851 } 852 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 853 854 return 0; 855 } 856 857 #ifdef BCM_HURRICANE3_SUPPORT 858 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 859 /* Check L2_ENTRY_OVERFLOW */ 860 l2_entry_overflow_count = soc_mem_index_count(unit, L2_ENTRY_OVERFLOWm); 861 blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_OVERFLOWm); 862 sblk = SOC_BLOCK2SCH(unit, blk); 863 for (index = 0; index < l2_entry_overflow_count; index++) { 864 865 addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, blk, 866 index, &acc_type); 867 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, 868 tmp); 869 if (soc_mem_field32_get(unit, L2_ENTRY_OVERFLOWm, tmp, VALIDf)) { 870 if (soc_mem_compare_key(unit, L2_ENTRY_OVERFLOWm, entry, tmp) 871 == 0) { 872 LOG_VERBOSE(BSL_LS_SOC_COMMON, 873 (BSL_META_U(unit, "write sblk %d acc_type %d bank %d " 874 "bucket %d, slot %d, index %d in L2_ENTRY_OVERFLOW\n"), 875 sblk, acc_type, bank, bucket, slot, index)); 876 877 /* Overwrite the existing entry */ 878 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 879 addr, (uint32 *)entry); 880 881 /* Copy old entry immediately after response word */ 882 memcpy(&result[1], tmp, 883 soc_mem_entry_bytes(unit, L2_ENTRY_OVERFLOWm)); 884 885 result[0] = 0; 886 if (soc_feature(unit, soc_feature_new_sbus_format) && 887 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 888 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 889 genresp_v2->index = index; 890 genresp_v2->index |= 891 SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit); 892 } else { 893 genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED; 894 genresp->index = index; 895 } 896 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 897 898 return 0; 899 } 900 } else { 901 if (free_index == -1) { 902 free_index = index; 903 } 904 } 905 } 906 907 /* Find first unused entry in L2_ENTRY_OVERFLOW */ 908 if (free_index != -1) { 909 index = free_index; 910 addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, 911 blk, index, &acc_type); 912 913 LOG_VERBOSE(BSL_LS_SOC_COMMON, 914 (BSL_META_U(unit,"write sblk %d acc_type %d bank %d bucket %d," 915 " slot %d, index %d in L2_ENTRY_OVERFLOW\n"), 916 sblk, acc_type, free_bank, free_bucket, free_slot, index)); 917 918 /* Write the entry */ 919 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 920 entry); 921 922 result[0] = 0; 923 if (soc_feature(unit, soc_feature_new_sbus_format) && 924 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 925 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 926 genresp_v2->index = index; 927 genresp_v2->index |= SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit); 928 } else { 929 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED; 930 genresp->index = index; 931 genresp->index |= SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit); 932 } 933 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 934 935 return 0; 936 } 937 } 938 #endif /* BCM_HURRICANE3_SUPPORT */ 939 940 LOG_VERBOSE(BSL_LS_SOC_COMMON, 941 (BSL_META_U(unit, 942 "Bucket full\n"))); 943 result[0] = 0; 944 if (soc_feature(unit, soc_feature_new_sbus_format) && 945 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 946 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 947 } else { 948 genresp->type = SCHAN_GEN_RESP_TYPE_FULL; 949 } 950 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 951 952 return 0; 953 } 954 955 int 956 soc_internal_l2_tr_entry_del(pcid_info_t *pcid_info, uint32 inv_bank_map, 957 void *entry, uint32 *result) 958 { 959 uint32 tmp[SOC_MAX_MEM_WORDS]; 960 uint32 bank_map; 961 int bank, bank_start, bank_inc, bank_base; 962 int bucket, entries_per_row; 963 int slot, entries_per_bucket, bucket_offset; 964 int index; 965 int unit = pcid_info->unit; 966 schan_genresp_t *genresp = (schan_genresp_t *) result; 967 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result; 968 int blk; 969 soc_block_t sblk; 970 uint8 acc_type; 971 uint32 addr; 972 soc_field_t vld_fld; 973 #ifdef BCM_HURRICANE3_SUPPORT 974 uint32 l2_entry_overflow_count; 975 #endif /* BCM_HURRICANE3_SUPPORT */ 976 977 LOG_VERBOSE(BSL_LS_SOC_COMMON, 978 (BSL_META_U(unit, 979 "L2X Delete\n"))); 980 981 vld_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf; 982 blk = SOC_MEM_BLOCK_ANY(unit, L2Xm); 983 sblk = SOC_BLOCK2SCH(unit, blk); 984 985 soc_internal_l2_tr_bank_map_get(pcid_info, &bank_map, &bank_start, 986 &bank_inc, NULL); 987 bank_map &= ~inv_bank_map; 988 989 for (bank = bank_start; bank_map != 0; bank += bank_inc) { 990 if (!(bank_map & (1 << bank))) { 991 continue; 992 } 993 bank_map &= ~(1 << bank); 994 995 soc_internal_l2_tr_bank_size_get(pcid_info, bank, NULL, 996 &entries_per_row, &entries_per_bucket, 997 &bank_base, &bucket_offset); 998 bucket = soc_internal_l2_tr_bucket_get(pcid_info, bank, entry); 999 1000 for (slot = 0; slot < entries_per_bucket; slot++) { 1001 index = bank_base + bucket * entries_per_row + bucket_offset + 1002 slot; 1003 addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type); 1004 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, 1005 tmp); 1006 if (soc_mem_field32_get(unit, L2Xm, tmp, vld_fld)) { 1007 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) { 1008 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1009 (BSL_META_U(unit, 1010 "delete sblk %d acc_type %d bank %d " 1011 "bucket %d, slot %d, index %d\n"), 1012 sblk, acc_type, bank, bucket, slot, index)); 1013 1014 /* Copy entry immediately after response word */ 1015 memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, L2Xm)); 1016 1017 /* Invalidate entry */ 1018 soc_mem_field32_set(unit, L2Xm, tmp, vld_fld, 0); 1019 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1020 addr, (uint32 *)tmp); 1021 1022 result[0] = 0; 1023 if (soc_feature(unit, soc_feature_new_sbus_format) && 1024 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1025 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 1026 genresp_v2->index = index; 1027 } else { 1028 genresp->type = SCHAN_GEN_RESP_TYPE_DELETED; 1029 genresp->index = index; 1030 } 1031 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1032 1033 return 0; 1034 } 1035 } 1036 } 1037 } 1038 1039 #ifdef BCM_HURRICANE3_SUPPORT 1040 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 1041 /* Check L2_ENTRY_OVERFLOW */ 1042 l2_entry_overflow_count = soc_mem_index_count(unit, L2_ENTRY_OVERFLOWm); 1043 blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_OVERFLOWm); 1044 sblk = SOC_BLOCK2SCH(unit, blk); 1045 for (index = 0; index < l2_entry_overflow_count; index++) { 1046 1047 addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, blk, 1048 index, &acc_type); 1049 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, 1050 tmp); 1051 if (soc_mem_field32_get(unit, L2_ENTRY_OVERFLOWm, tmp, VALIDf)) { 1052 if (soc_mem_compare_key(unit, L2_ENTRY_OVERFLOWm, 1053 entry, tmp) == 0) { 1054 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1055 (BSL_META_U(unit, "delete sblk %d acc_type %d bank %d " 1056 "bucket %d, slot %d, index %d in L2_ENTRY_OVERFLOW\n"), 1057 sblk, acc_type, bank, bucket, slot, index)); 1058 1059 /* Copy entry immediately after response word */ 1060 memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, 1061 L2_ENTRY_OVERFLOWm)); 1062 1063 /* Invalidate entry */ 1064 soc_mem_field32_set(unit, L2_ENTRY_OVERFLOWm, 1065 tmp, VALIDf, 0); 1066 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1067 addr, (uint32 *)tmp); 1068 1069 result[0] = 0; 1070 if (soc_feature(unit, soc_feature_new_sbus_format) && 1071 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1072 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 1073 genresp_v2->index = index; 1074 genresp_v2->index |= 1075 SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit); 1076 } else { 1077 genresp->type = SCHAN_GEN_RESP_TYPE_DELETED; 1078 genresp->index = index; 1079 genresp->index |= 1080 SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit); 1081 } 1082 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1083 1084 return 0; 1085 } 1086 } 1087 } 1088 } 1089 #endif /* BCM_HURRICANE3_SUPPORT */ 1090 1091 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1092 (BSL_META_U(unit, 1093 "soc_internal_l2_tr_entry_del: Not found\n"))); 1094 1095 result[0] = 0; 1096 if (soc_feature(unit, soc_feature_new_sbus_format) && 1097 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1098 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1099 } else { 1100 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1101 } 1102 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1103 1104 return 0; 1105 } 1106 1107 /* 1108 * soc_internal_l2_tr_entry_lkup 1109 * 1110 * Note: entry_lookup and entry_result may overlap. 1111 */ 1112 1113 int 1114 soc_internal_l2_tr_entry_lkup(pcid_info_t *pcid_info, uint32 inv_bank_map, 1115 void *entry, uint32 *result) 1116 { 1117 uint32 tmp[SOC_MAX_MEM_WORDS]; 1118 uint32 bank_map; 1119 int bank, bank_start, bank_inc, bank_base; 1120 int bucket, entries_per_row; 1121 int slot, entries_per_bucket, bucket_offset; 1122 int index; 1123 int unit = pcid_info->unit; 1124 schan_genresp_t *genresp = (schan_genresp_t *) result; 1125 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result; 1126 int blk; 1127 soc_block_t sblk; 1128 uint8 acc_type; 1129 uint32 addr; 1130 soc_field_t vld_fld; 1131 #ifdef BCM_HURRICANE3_SUPPORT 1132 uint32 l2_entry_overflow_count; 1133 #endif /* BCM_HURRICANE3_SUPPORT */ 1134 1135 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1136 (BSL_META_U(unit, 1137 "L2X Lookup\n"))); 1138 1139 vld_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf; 1140 blk = SOC_MEM_BLOCK_ANY(unit, L2Xm); 1141 sblk = SOC_BLOCK2SCH(unit, blk); 1142 1143 soc_internal_l2_tr_bank_map_get(pcid_info, &bank_map, &bank_start, 1144 &bank_inc, NULL); 1145 bank_map &= ~inv_bank_map; 1146 1147 for (bank = bank_start; bank_map != 0; bank += bank_inc) { 1148 if (!(bank_map & (1 << bank))) { 1149 continue; 1150 } 1151 bank_map &= ~(1 << bank); 1152 1153 soc_internal_l2_tr_bank_size_get(pcid_info, bank, NULL, 1154 &entries_per_row, &entries_per_bucket, 1155 &bank_base, &bucket_offset); 1156 bucket = soc_internal_l2_tr_bucket_get(pcid_info, bank, entry); 1157 1158 for (slot = 0; slot < entries_per_bucket; slot++) { 1159 index = bank_base + bucket * entries_per_row + bucket_offset + 1160 slot; 1161 addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type); 1162 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, 1163 tmp); 1164 if (soc_mem_field32_get(unit, L2Xm, tmp, vld_fld)) { 1165 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) { 1166 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1167 (BSL_META_U(unit, 1168 "found sblk %d acc_type %d bank %d " 1169 "bucket %d, slot %d, index %d\n"), 1170 sblk, acc_type, bank, bucket, slot, index)); 1171 1172 /* Copy entry immediately after response word */ 1173 memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, L2Xm)); 1174 1175 result[0] = 0; 1176 if (soc_feature(unit, soc_feature_new_sbus_format) && 1177 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1178 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 1179 genresp_v2->index = index; 1180 } else { 1181 genresp->type = SCHAN_GEN_RESP_TYPE_FOUND; 1182 genresp->index = index; 1183 } 1184 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1185 1186 return 0; 1187 } 1188 } 1189 } 1190 } 1191 1192 #ifdef BCM_HURRICANE3_SUPPORT 1193 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 1194 /* Check L2_ENTRY_OVERFLOW */ 1195 l2_entry_overflow_count = soc_mem_index_count(unit, L2_ENTRY_OVERFLOWm); 1196 blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_OVERFLOWm); 1197 sblk = SOC_BLOCK2SCH(unit, blk); 1198 for (index = 0; index < l2_entry_overflow_count; index++) { 1199 1200 addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, blk, 1201 index, &acc_type); 1202 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, 1203 tmp); 1204 if (soc_mem_field32_get(unit, L2_ENTRY_OVERFLOWm, tmp, VALIDf)) { 1205 if (soc_mem_compare_key(unit, L2_ENTRY_OVERFLOWm, 1206 entry, tmp) == 0) { 1207 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1208 (BSL_META_U(unit, "found sblk %d acc_type %d bank %d " 1209 "bucket %d, slot %d, index %d in L2_ENTRY_OVERFLOW\n"), 1210 sblk, acc_type, bank, bucket, slot, index)); 1211 1212 /* Copy entry immediately after response word */ 1213 memcpy(&result[1], tmp, 1214 soc_mem_entry_bytes(unit, L2_ENTRY_OVERFLOWm)); 1215 1216 result[0] = 0; 1217 if (soc_feature(unit, soc_feature_new_sbus_format) && 1218 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1219 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 1220 genresp_v2->index = index; 1221 genresp_v2->index |= 1222 SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit); 1223 } else { 1224 genresp->type = SCHAN_GEN_RESP_TYPE_FOUND; 1225 genresp->index = index; 1226 genresp->index |= 1227 SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit); 1228 } 1229 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1230 1231 return 0; 1232 } 1233 } 1234 } 1235 } 1236 #endif /* BCM_HURRICANE3_SUPPORT */ 1237 1238 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1239 (BSL_META_U(unit, 1240 "soc_internal_l2_tr_entry_lkup: Not found\n"))); 1241 1242 result[0] = 0; 1243 if (soc_feature(unit, soc_feature_new_sbus_format) && 1244 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1245 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1246 } else { 1247 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1248 } 1249 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1250 1251 return 0; 1252 } 1253 #endif /* BCM_TRX_SUPPORT */ 1254 #endif