hash.c (63566B)
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: hash.c 8 * Purpose: Tomahawk3 hash table calculation routines 9 * Requires: 10 */ 11 12 #include <shared/bsl.h> 13 14 #include <soc/drv.h> 15 #include <soc/mem.h> 16 #include <soc/debug.h> 17 #include <soc/hash.h> 18 19 #if defined(BCM_TOMAHAWK3_SUPPORT) 20 21 #include <soc/tomahawk3.h> 22 23 /* Map physical to logical bank mapping for a memory 24 * mem - memory 25 * phy_bank - physical bank number 26 * log_bank - logical bank id 27 */ 28 STATIC int 29 soc_tomahawk3_phy_to_log_bank_map(int unit, soc_mem_t mem, int phy_bank, int *log_bank) 30 { 31 uint32 hash_control_entry[4]; 32 int i, done = 0; 33 int bank_min=0, bank_max=3; 34 static const soc_field_t logical_to_physical_fields[] = { 35 LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf, 36 LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf, 37 LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf, 38 LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf 39 }; 40 41 sal_memset(hash_control_entry, 0, sizeof(hash_control_entry)); 42 43 switch(mem) { 44 case EXACT_MATCH_2m: 45 case EXACT_MATCH_4m: 46 bank_min = 0; 47 bank_max = 3; 48 break; 49 default: 50 *log_bank = phy_bank; 51 done = 1; 52 } 53 54 /* Shared Banks */ 55 if (done == 0) { 56 /* Sanity */ 57 if (phy_bank < bank_min || phy_bank > bank_max) { 58 return SOC_E_PARAM; 59 } 60 61 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EXACT_MATCH_HASH_CONTROLm, MEM_BLOCK_ALL, 0, 62 hash_control_entry)); 63 for (i = bank_min; i <= bank_max; i++) { 64 if(soc_mem_field32_get(unit, EXACT_MATCH_HASH_CONTROLm, hash_control_entry, 65 logical_to_physical_fields[i]) == phy_bank) { 66 *log_bank = i; 67 break; 68 } 69 } 70 } 71 72 return SOC_E_NONE; 73 } 74 75 76 77 /* Map logical to physical bank mapping for a memory 78 * mem - memory 79 * log_bank - logical bank number (or sequence bank number) 80 * phy_bank_id - Physical bank id 81 */ 82 int 83 soc_tomahawk3_log_to_phy_bank_map(int unit, soc_mem_t mem, int log_bank, 84 int *phy_bank_id) 85 { 86 int done = 0, bank_min = 0, bank_max = 3; 87 uint32 hash_control_entry[4]; 88 89 static const soc_field_t logical_to_physical_fields[] = { 90 LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf, 91 LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf, 92 LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf, 93 LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf, 94 }; 95 96 97 switch(mem) { 98 case L2Xm: 99 case MPLS_ENTRY_SINGLEm: 100 bank_min = 0; 101 bank_max = 1; 102 done = 1; 103 break; 104 105 case L3_ENTRY_ONLY_SINGLEm: 106 case L3_ENTRY_ONLY_DOUBLEm: 107 case L3_ENTRY_ONLY_QUADm: 108 case L3_ENTRY_SINGLEm: 109 case L3_ENTRY_DOUBLEm: 110 case L3_ENTRY_QUADm: 111 case L3_TUNNEL_SINGLEm: 112 case L3_TUNNEL_DOUBLEm: 113 case L3_TUNNEL_QUADm: 114 bank_min = 0; 115 bank_max = 3; 116 done = 1; 117 break; 118 119 120 case EXACT_MATCH_2m: 121 case EXACT_MATCH_4m: 122 bank_min = 0; 123 bank_max = 3; 124 break; 125 126 default: 127 break; 128 } 129 130 if (log_bank < bank_min || log_bank > bank_max) { 131 return SOC_E_PARAM; 132 } 133 134 if (!done) { 135 sal_memset(hash_control_entry, 0, sizeof(hash_control_entry)); 136 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EXACT_MATCH_HASH_CONTROLm, MEM_BLOCK_ALL, 0, 137 hash_control_entry)); 138 *phy_bank_id = soc_mem_field32_get(unit, EXACT_MATCH_HASH_CONTROLm, hash_control_entry, 139 logical_to_physical_fields[log_bank]); 140 } else { 141 *phy_bank_id = log_bank; 142 } 143 144 return SOC_E_NONE; 145 } 146 147 STATIC int 148 _soc_tomahawk3_hash_entry_to_key(int unit, int bank, void *entry, uint8 *key, soc_mem_t mem, 149 soc_field_t *field_list) 150 { 151 soc_field_t field; 152 int index, key_index, val_index, fval_index; 153 int right_shift_count, left_shift_count; 154 uint32 val[SOC_MAX_MEM_WORDS], fval[SOC_MAX_MEM_WORDS]; 155 int bits, val_bits, fval_bits, nbits; 156 int8 field_length[16]; 157 #ifdef SOC_ROBUST_HASH 158 soc_robust_hash_config_t *rbh_cfg = NULL; 159 #endif /* SOC_ROBUST_HASH */ 160 161 val_bits = 0; 162 for (index = 0; field_list[index] != INVALIDf; index++) { 163 field = field_list[index]; 164 field_length[index] = soc_mem_field_length(unit, mem, field); 165 val_bits += field_length[index]; 166 } 167 168 switch (mem) { 169 case L2Xm: 170 val_bits = SOC_TH3_L2_ENTRY_MAX_KEY_WIDTH; 171 break; 172 case L3_ENTRY_ONLY_SINGLEm: 173 case L3_ENTRY_SINGLEm: 174 case L3_ENTRY_DOUBLEm: 175 case L3_ENTRY_QUADm: 176 val_bits = SOC_TH3_L3_MAX_KEY_WIDTH; 177 break; 178 case L3_TUNNEL_SINGLEm: 179 case L3_TUNNEL_DOUBLEm: 180 case L3_TUNNEL_QUADm: 181 val_bits = SOC_TH3_L3_TUNNEL_MAX_KEY_WIDTH; 182 break; 183 case MPLS_ENTRY_SINGLEm: 184 val_bits = SOC_TH3_L3_MPLS_MAX_KEY_WIDTH; 185 break; 186 case EXACT_MATCH_2m: 187 case EXACT_MATCH_4m: 188 val_bits = SOC_TH3_EXACT_MATCH_MAX_KEY_WIDTH; 189 break; 190 default: 191 break; 192 } 193 194 nbits = val_bits; 195 196 #ifdef SOC_ROBUST_HASH 197 if (soc_feature(unit, soc_feature_robust_hash)) { 198 switch (mem) { 199 case L2Xm: 200 rbh_cfg = &(ROBUSTHASH(unit)->l2); 201 break; 202 case L3_ENTRY_ONLY_SINGLEm: 203 case L3_ENTRY_SINGLEm: 204 case L3_ENTRY_DOUBLEm: 205 case L3_ENTRY_QUADm: 206 rbh_cfg = &(ROBUSTHASH(unit)->l3); 207 break; 208 case EXACT_MATCH_4m: 209 case EXACT_MATCH_2m: 210 rbh_cfg = &(ROBUSTHASH(unit)->exact_match); 211 break; 212 case MPLS_ENTRY_SINGLEm: 213 rbh_cfg = &(ROBUSTHASH(unit)->mpls_entry); 214 break; 215 case L3_TUNNEL_SINGLEm: 216 case L3_TUNNEL_DOUBLEm: 217 case L3_TUNNEL_QUADm: 218 rbh_cfg = &(ROBUSTHASH(unit)->tunnel); 219 break; 220 default: 221 break; 222 } 223 } 224 225 #endif /* SOC_ROBUST_HASH */ 226 bits = val_bits; 227 val_bits = 0; 228 229 sal_memset(val, 0, sizeof(val)); 230 for (index = 0; field_list[index] != INVALIDf; index++) { 231 field = field_list[index]; 232 soc_mem_field_get(unit, mem, entry, field, fval); 233 fval_bits = field_length[index]; 234 235 val_index = val_bits >> 5; 236 fval_index = 0; 237 left_shift_count = val_bits & 0x1f; 238 right_shift_count = 32 - left_shift_count; 239 val_bits += fval_bits; 240 241 if (left_shift_count) { 242 for (; fval_bits > 0; fval_bits -= 32) { 243 val[val_index++] |= fval[fval_index] << left_shift_count; 244 val[val_index] |= fval[fval_index++] >> right_shift_count; 245 } 246 } else { 247 for (; fval_bits > 0; fval_bits -= 32) { 248 val[val_index++] = fval[fval_index++]; 249 } 250 } 251 } 252 253 key_index = 0; 254 for (val_index = 0; val_bits > 0; val_index++) { 255 for (right_shift_count = 0; right_shift_count < 32; 256 right_shift_count += 8) { 257 if (val_bits <= 0) { 258 break; 259 } 260 key[key_index++] = (val[val_index] >> right_shift_count) & 0xff; 261 val_bits -= 8; 262 } 263 } 264 265 if ((bits + 7) / 8 > key_index) { 266 sal_memset(&key[key_index], 0, (bits + 7) / 8 - key_index); 267 } 268 269 bits = (((nbits - 1) / 32) + 1) * 32; 270 271 #ifdef SOC_ROBUST_HASH 272 if (soc_feature(unit, soc_feature_robust_hash)) { 273 if (rbh_cfg) { 274 if (rbh_cfg->enable) { 275 (void) soc_robust_hash_get2(unit, rbh_cfg, bank, key, nbits); /* nbits = unpadded */ 276 } 277 278 bits += ROBUST_HASH_KEY_SPACE_WIDTH; 279 } 280 } 281 #endif /* SOC_ROBUST_HASH */ 282 283 return bits; 284 } 285 286 STATIC int 287 _soc_tomahawk3_shared_hash(int unit, int hash_offset, uint32 key_nbits, uint8 *keyA, 288 uint8 *keyB, uint32 result_mask, uint16 lsb, int use_lsb) 289 { 290 uint32 crc_hi, crc_lo; 291 uint64 hash_vector, mask; 292 293 if (use_lsb) { 294 /* Debug Mode 295 * Hash Vector [63:48] -> Zero 296 * Hash Vector [47:32] -> Hash LSB 297 */ 298 crc_hi = lsb; 299 } else { 300 crc_hi = soc_crc32b(keyB, key_nbits); 301 } 302 303 crc_lo = soc_crc32b(keyA, key_nbits); 304 305 COMPILER_64_SET(hash_vector, crc_hi, crc_lo); 306 COMPILER_64_SET(mask, 0, result_mask); 307 COMPILER_64_SHR(hash_vector, hash_offset); 308 COMPILER_64_AND(hash_vector, mask); 309 return (int)COMPILER_64_LO(hash_vector); 310 } 311 312 /* Get number of banks for the hash table according to the config 313 */ 314 int 315 soc_tomahawk3_hash_bank_count_get(int unit, soc_mem_t mem, int *num_banks) 316 { 317 int count; 318 319 if (NULL == num_banks) { 320 return SOC_E_PARAM; 321 } 322 323 switch (mem) { 324 case L2Xm: 325 /* 326 * 4k single wide entries in each of 2 dedicated L2 bank 327 */ 328 *num_banks = 2; 329 break; 330 case L3_ENTRY_ONLY_SINGLEm: 331 case L3_ENTRY_ONLY_DOUBLEm: 332 case L3_ENTRY_ONLY_QUADm: 333 case L3_ENTRY_SINGLEm: 334 case L3_ENTRY_DOUBLEm: 335 case L3_ENTRY_QUADm: 336 /* 337 * 4k single wide entries in each of 4 dedicated L3 bank 338 */ 339 *num_banks = 4; 340 break; 341 342 case EXACT_MATCH_2m: 343 case EXACT_MATCH_4m: 344 /* 345 * 16k double wide entries in each shared bank 346 */ 347 count = soc_mem_index_count(unit, EXACT_MATCH_2m); 348 *num_banks = count / (16 * 1024); 349 break; 350 351 case MPLS_ENTRY_SINGLEm: 352 /* 353 * 8k single wide entries in each shared bank 354 */ 355 *num_banks = 2; 356 break; 357 case L3_TUNNEL_SINGLEm: 358 case L3_TUNNEL_DOUBLEm: 359 case L3_TUNNEL_QUADm: 360 /* 361 * 4k single wide entries in each dedicated bank 362 */ 363 *num_banks = 4; 364 break; 365 366 default: 367 return SOC_E_INTERNAL; 368 } 369 370 return SOC_E_NONE; 371 } 372 373 /* Map bank sequence number to physical bank number */ 374 int 375 soc_tomahawk3_hash_bank_number_get(int unit, soc_mem_t mem, int seq_num, 376 int *bank_num) { 377 int count; 378 379 SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_bank_count_get(unit, mem, &count)); 380 if (seq_num < 0 || seq_num >= count) { 381 return SOC_E_CONFIG; 382 } 383 SOC_IF_ERROR_RETURN(soc_tomahawk3_log_to_phy_bank_map(unit, mem, seq_num, 384 bank_num)); 385 386 return SOC_E_NONE; 387 } 388 389 int 390 soc_tomahawk3_hash_seq_number_get(int unit, soc_mem_t mem, int bank_num, int *seq_num) 391 { 392 int count; 393 394 SOC_IF_ERROR_RETURN(soc_tomahawk3_phy_to_log_bank_map(unit, mem, bank_num, 395 seq_num)); 396 397 SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_bank_count_get(unit, mem, &count)); 398 if (*seq_num < 0 || *seq_num >= count) { 399 return SOC_E_INTERNAL; 400 } 401 402 return SOC_E_NONE; 403 } 404 405 uint32 406 soc_tomahawk3_tunnel_hash(int unit, int bank, int hash_offset, int use_lsb, 407 int key_nbits, void *base_entry, uint8 *key1, uint8 *key2) 408 { 409 uint32 lsb_val; 410 uint32 hash_mask; 411 uint32 hash_bits; 412 413 hash_mask = 0x3FF; 414 hash_bits = 10; 415 416 if (use_lsb && (hash_offset + hash_bits > 32)) { 417 int key_type; 418 key_type = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, 419 base_entry, KEY_TYPEf); 420 switch (key_type) { 421 case TH3_MPLS_HASH_KEY_TYPE_MPLS: 422 lsb_val = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, base_entry, 423 MPLS__HASH_LSBf); 424 break; 425 426 case TH3_TUNNEL_HASH_KEY_TYPE_V4: 427 lsb_val = soc_mem_field32_get(unit, L3_TUNNEL_DOUBLEm, base_entry, 428 IPV4UC__HASH_LSBf); 429 break; 430 431 case TH3_TUNNEL_HASH_KEY_TYPE_V6: 432 lsb_val = soc_mem_field32_get(unit, L3_TUNNEL_QUADm, base_entry, 433 IPV6UC__HASH_LSBf); 434 break; 435 436 default: 437 lsb_val = 0; 438 break; 439 } 440 } else { 441 lsb_val = 0; 442 } 443 444 return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2, 445 hash_mask, lsb_val, use_lsb); 446 } 447 448 449 int 450 soc_tomahawk3_tunnel_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key) 451 { 452 soc_mem_t mem; 453 soc_field_t field_list[5]; 454 455 switch (soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, entry, KEY_TYPEf)) { 456 case TH3_TUNNEL_HASH_KEY_TYPE_MPLS: 457 mem = L3_TUNNEL_SINGLEm; 458 field_list[0] = MPLS__KEYf; 459 field_list[1] = INVALIDf; 460 break; 461 case TH3_TUNNEL_HASH_KEY_TYPE_V4: 462 mem = L3_TUNNEL_DOUBLEm; 463 field_list[0] = IPV4__KEY_0f; 464 field_list[1] = IPV4__KEY_1f; 465 field_list[2] = INVALIDf; 466 break; 467 case TH3_TUNNEL_HASH_KEY_TYPE_V6: 468 mem = L3_TUNNEL_QUADm; 469 field_list[0] = IPV6__KEY_0f; 470 field_list[1] = IPV6__KEY_1f; 471 field_list[2] = IPV6__KEY_2f; 472 field_list[3] = IPV6__KEY_3f; 473 field_list[4] = INVALIDf; 474 break; 475 default: 476 return 0; 477 } 478 return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, mem, field_list); 479 } 480 481 uint32 482 soc_tomahawk3_tunnel_entry_hash(int unit, int bank, int hash_offset, int use_lsb, 483 uint32 *entry) 484 { 485 int key_nbits; 486 uint8 key1[SOC_MAX_MEM_WORDS * 4] = {0}; 487 uint8 key2[SOC_MAX_MEM_WORDS * 4] = {0}; 488 489 /* Robust Hashed Key using Remap and Action Tables A */ 490 key_nbits = soc_tomahawk3_tunnel_base_entry_to_key(unit, 0, entry, key1); 491 /* Robust Hashed Key using Remap and Action Tables B */ 492 key_nbits = soc_tomahawk3_tunnel_base_entry_to_key(unit, 1, entry, key2); 493 return soc_tomahawk3_tunnel_hash(unit, bank, hash_offset, use_lsb, 494 key_nbits, entry, key1, key2); 495 } 496 497 uint32 498 soc_tomahawk3_tunnel_bank_entry_hash(int unit, int bank, uint32 *entry) 499 { 500 int rv, hash_offset, use_lsb; 501 502 rv = soc_tomahawk3_hash_offset_get(unit, L3_TUNNEL_SINGLEm, bank, &hash_offset, 503 &use_lsb); 504 if (SOC_FAILURE(rv)) { 505 return 0; 506 } 507 508 return soc_tomahawk3_tunnel_entry_hash(unit, bank, hash_offset, use_lsb, entry); 509 } 510 511 uint32 512 soc_tomahawk3_exact_match_hash(int unit, int bank, int hash_offset, int use_lsb, 513 int key_nbits, void *base_entry, uint8 *key1, 514 uint8 *key2) 515 { 516 uint32 lsb_val; 517 uint32 hash_mask; 518 uint32 hash_bits; 519 520 hash_mask = 0x1fff; /* 4k buckets per shared bank for EXACT_MATCH_2m -> 8k base buckets for BM0 */ 521 hash_bits = 13; 522 523 if (use_lsb && (hash_offset + hash_bits > 32)) { 524 switch (soc_mem_field32_get(unit, EXACT_MATCH_2m, base_entry, 525 KEY_TYPEf)) { 526 case TH3_FPEM_HASH_KEY_TYPE_128B: 527 lsb_val = soc_mem_field32_get(unit, EXACT_MATCH_2m, 528 base_entry, MODE128__HASH_LSBf); 529 break; 530 case TH3_FPEM_HASH_KEY_TYPE_160B: 531 lsb_val = soc_mem_field32_get(unit, EXACT_MATCH_2m, 532 base_entry, MODE160__HASH_LSBf); 533 break; 534 case TH3_FPEM_HASH_KEY_TYPE_320B: 535 lsb_val = soc_mem_field32_get(unit, EXACT_MATCH_4m, 536 base_entry, MODE320__HASH_LSBf); 537 break; 538 default: 539 lsb_val = 0; 540 break; 541 } 542 } else { 543 lsb_val = 0; 544 } 545 546 return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2, 547 hash_mask, lsb_val, use_lsb); 548 } 549 550 551 int 552 soc_tomahawk3_exact_match_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key) 553 { 554 soc_mem_t mem; 555 soc_field_t field_list[5]; 556 557 switch (soc_mem_field32_get(unit, EXACT_MATCH_2m, entry, KEY_TYPEf)) { 558 case TH3_FPEM_HASH_KEY_TYPE_128B: 559 mem = EXACT_MATCH_2m; 560 field_list[0] = MODE128__KEY_0f; 561 field_list[1] = MODE128__KEY_1f; 562 field_list[2] = INVALIDf; 563 break; 564 case TH3_FPEM_HASH_KEY_TYPE_160B: 565 mem = EXACT_MATCH_2m; 566 field_list[0] = MODE160__KEY_0f; 567 field_list[1] = MODE160__KEY_1f; 568 field_list[2] = INVALIDf; 569 break; 570 case TH3_FPEM_HASH_KEY_TYPE_320B: 571 mem = EXACT_MATCH_4m; 572 field_list[0] = MODE320__KEY_0f; 573 field_list[1] = MODE320__KEY_1f; 574 field_list[2] = MODE320__KEY_2f; 575 field_list[3] = INVALIDf; 576 break; 577 default: 578 return 0; 579 } 580 return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, mem, field_list); 581 } 582 583 uint32 584 soc_tomahawk3_exact_match_entry_hash(int unit, int bank, int hash_offset, 585 int use_lsb, uint32 *entry) 586 { 587 int key_nbits; 588 uint8 key1[SOC_MAX_MEM_WORDS * 4] = {0}; 589 uint8 key2[SOC_MAX_MEM_WORDS * 4] = {0}; 590 591 /* Robust Hashed Key using Remap and Action Tables A */ 592 key_nbits = soc_tomahawk3_exact_match_base_entry_to_key(unit, 0, entry, key1); 593 /* Robust Hashed Key using Remap and Action Tables B */ 594 key_nbits = soc_tomahawk3_exact_match_base_entry_to_key(unit, 1, entry, key2); 595 596 return soc_tomahawk3_exact_match_hash(unit, bank, hash_offset, use_lsb, 597 key_nbits, entry, key1, key2); 598 } 599 600 int 601 soc_tomahawk3_mpls_base_entry_to_key(int unit, int bank, void *entry, uint8 *key) { 602 603 soc_field_t field_list[2]; 604 switch (soc_mem_field32_get(unit, MPLS_ENTRY_SINGLEm, entry, KEY_TYPEf)) { 605 case TH3_MPLS_HASH_KEY_TYPE_MPLS: 606 607 field_list[0] = MPLS__KEYf; 608 break; 609 default: 610 return 0; 611 } 612 613 field_list[1] = INVALIDf; 614 return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, 615 MPLS_ENTRY_SINGLEm, field_list); 616 } 617 618 uint32 619 soc_tomahawk3_mpls_hash(int unit, int bank, int hash_offset, int use_lsb, 620 int key_nbits, void *base_entry, uint8 *key1, uint8 *key2) 621 { 622 uint32 lsb_val; 623 uint32 hash_mask; 624 uint32 hash_bits; 625 626 hash_mask = 0x7FF; /* 2k buckets per shared bank of size 8k */ 627 hash_bits = 11; 628 629 if (use_lsb && (hash_offset + hash_bits > 32)) { 630 switch (soc_mem_field32_get(unit, MPLS_ENTRY_SINGLEm, base_entry, 631 KEY_TYPEf)) { 632 case TH3_MPLS_HASH_KEY_TYPE_MPLS: 633 lsb_val = soc_mem_field32_get(unit, MPLS_ENTRY_SINGLEm, base_entry, 634 MPLS__HASH_LSBf); 635 break; 636 637 default: 638 lsb_val = 0; 639 break; 640 } 641 } else { 642 lsb_val = 0; 643 } 644 645 return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2, 646 hash_mask, lsb_val, use_lsb); 647 } 648 649 uint32 650 soc_tomahawk3_mpls_entry_hash(int unit, int bank, int hash_offset, 651 int use_lsb, uint32 *entry) 652 { 653 int key_nbits; 654 uint8 key1[SOC_MAX_MEM_WORDS * 4] = {0}; 655 uint8 key2[SOC_MAX_MEM_WORDS * 4] = {0}; 656 657 /* Robust Hashed Key using Remap and Action Tables A */ 658 key_nbits = soc_tomahawk3_mpls_base_entry_to_key(unit, 0, entry, key1); 659 /* Robust Hashed Key using Remap and Action Tables B */ 660 key_nbits = soc_tomahawk3_mpls_base_entry_to_key(unit, 1, entry, key2); 661 662 return soc_tomahawk3_mpls_hash(unit, bank, hash_offset, use_lsb, 663 key_nbits, entry, key1, key2); 664 } 665 666 uint32 667 soc_tomahawk3_mpls_bank_entry_hash(int unit, int bank, uint32 *entry) 668 { 669 int rv, hash_offset, use_lsb; 670 671 rv = soc_tomahawk3_hash_offset_get(unit, MPLS_ENTRY_SINGLEm, bank, &hash_offset, 672 &use_lsb); 673 if (SOC_FAILURE(rv)) { 674 return 0; 675 } 676 677 return soc_tomahawk3_mpls_entry_hash(unit, bank, hash_offset, use_lsb, entry); 678 } 679 680 int 681 soc_tomahawk3_hash_bank_info_get(int unit, soc_mem_t mem, int bank, 682 int *entries_per_bank, int *entries_per_row, 683 int *entries_per_bucket, int *bank_base, 684 int *bucket_offset) 685 { 686 int bank_size, row_size, bucket_size, base, offset; 687 int seq_num = 0; 688 689 /* Get logical bank number */ 690 SOC_IF_ERROR_RETURN(soc_tomahawk3_phy_to_log_bank_map(unit, mem, bank, &seq_num)); 691 bank = seq_num; 692 693 /* bank_size = logical entries per bank 694 * row_size = logical entries per base bucket 695 * bucket_size = logical entries per logical bucket = 4 696 * offset = 0 since this is bank_info 697 */ 698 699 switch (mem) { 700 case L2Xm: 701 bank_size = 4096; 702 row_size = 4; 703 bucket_size = 4; 704 offset = 0; 705 base = bank * bank_size; 706 break; 707 708 case L3_ENTRY_ONLY_SINGLEm: 709 case L3_ENTRY_SINGLEm: 710 case L3_ENTRY_DOUBLEm: 711 case L3_ENTRY_QUADm: 712 bucket_size = 4; 713 offset = 0; 714 if (mem == L3_ENTRY_QUADm) { 715 row_size = 1; 716 bank_size = 4096/4; 717 } else if (mem == L3_ENTRY_DOUBLEm) { 718 row_size = 2; 719 bank_size = 4096/2; 720 } else { 721 row_size = 4; 722 bank_size = 4096; 723 } 724 base = bank * bank_size; 725 break; 726 727 case EXACT_MATCH_2m: 728 row_size = 2; 729 bucket_size = 4; 730 offset = 0; 731 bank_size = 16384; 732 base = bank * bank_size; 733 break; 734 735 case EXACT_MATCH_4m: 736 row_size = 1; 737 bucket_size = 4; 738 offset = 0; 739 bank_size = 8192; 740 base = bank * bank_size; 741 break; 742 743 case L3_TUNNEL_SINGLEm: 744 case L3_TUNNEL_DOUBLEm: 745 case L3_TUNNEL_QUADm: 746 bucket_size = 4; 747 offset = 0; 748 if (mem == L3_TUNNEL_QUADm) { 749 row_size = 1; 750 bank_size = 4096/4; 751 } else if (mem == L3_TUNNEL_DOUBLEm) { 752 row_size = 2; 753 bank_size = 4096/2; 754 } else { 755 row_size = 4; 756 bank_size = 4096; 757 } 758 base = bank * bank_size; 759 break; 760 761 case MPLS_ENTRY_SINGLEm: 762 bank_size = 8192; 763 row_size = 1; 764 bucket_size = 4; 765 offset = 0; 766 base = bank_size * bank; 767 break; 768 769 default: 770 return SOC_E_INTERNAL; 771 } 772 773 if (entries_per_bank != NULL) { 774 *entries_per_bank = bank_size; 775 } 776 if (entries_per_row != NULL) { 777 *entries_per_row = row_size; 778 } 779 if (entries_per_bucket != NULL) { 780 *entries_per_bucket = bucket_size; 781 } 782 if (bank_base != NULL) { 783 *bank_base = base; 784 } 785 if (bucket_offset != NULL) { 786 *bucket_offset = offset; 787 } 788 return SOC_E_NONE; 789 } 790 791 int 792 soc_tomahawk3_hash_offset_get(int unit, soc_mem_t mem, int bank, int *hash_offset, 793 int *use_lsb) 794 { 795 uint32 hash_control_entry[4]; 796 int is_shared = 1; 797 soc_mem_t shared_mem = INVALIDm; 798 soc_field_t field; 799 static const soc_field_t uft_fields_d[] = { 800 HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f, 801 HASH_OFFSET_DEDICATED_BANK_2f, HASH_OFFSET_DEDICATED_BANK_3f 802 803 }; 804 static const soc_field_t uft_fields_s[] = { 805 B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf 806 }; 807 808 809 sal_memset(hash_control_entry, 0, sizeof(hash_control_entry)); 810 811 switch(mem) { 812 case L2Xm: 813 if (bank < 0 || bank > 1) { 814 return SOC_E_PARAM; 815 } 816 mem = L2_ENTRY_HASH_CONTROLm; 817 field = uft_fields_d[bank]; 818 is_shared = 0; 819 break; 820 case EXACT_MATCH_2m: 821 case EXACT_MATCH_4m: 822 if (bank < 0 || bank > 3) { 823 return SOC_E_PARAM; 824 } 825 mem = EXACT_MATCH_HASH_CONTROLm; 826 shared_mem = UFT_SHARED_BANKS_CONTROLm; 827 field = uft_fields_s[bank]; 828 break; 829 case L3_TUNNEL_SINGLEm: 830 case L3_TUNNEL_DOUBLEm: 831 case L3_TUNNEL_QUADm: 832 if (bank < 0 || bank > 3) { 833 return SOC_E_PARAM; 834 } 835 mem = L3_TUNNEL_HASH_CONTROLm; 836 field = uft_fields_d[bank]; 837 is_shared = 0; 838 break; 839 case L3_ENTRY_SINGLEm: 840 case L3_ENTRY_DOUBLEm: 841 case L3_ENTRY_QUADm: 842 case L3_ENTRY_ONLYm: 843 case L3_ENTRY_ONLY_SINGLEm: 844 if (bank < 0 || bank > 3) { 845 return SOC_E_PARAM; 846 } 847 mem = L3_ENTRY_HASH_CONTROLm; 848 field = uft_fields_d[bank]; 849 is_shared = 0; 850 break; 851 case MPLS_ENTRY_SINGLEm: 852 if (bank < 0 || bank > 1) { 853 return SOC_E_PARAM; 854 } 855 mem = MPLS_ENTRY_HASH_CONTROLm; 856 field = uft_fields_d[bank]; 857 is_shared = 0; 858 break; 859 default: 860 return SOC_E_INTERNAL; 861 } 862 863 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0, 864 hash_control_entry)); 865 if (use_lsb) { 866 *use_lsb = soc_mem_field32_get( 867 unit, mem, hash_control_entry, HASH_TABLE_TEST_MODEf); 868 } 869 870 /* Shared Banks */ 871 if (is_shared > 0) { 872 sal_memset(hash_control_entry, 0, sizeof(hash_control_entry)); 873 SOC_IF_ERROR_RETURN(soc_mem_read(unit, shared_mem, MEM_BLOCK_ALL, 0, 874 hash_control_entry)); 875 *hash_offset = soc_mem_field32_get(unit, shared_mem, 876 hash_control_entry, field); 877 } else { 878 *hash_offset = soc_mem_field32_get(unit, mem, hash_control_entry, field); 879 } 880 881 return SOC_E_NONE; 882 } 883 884 int 885 soc_tomahawk3_hash_offset_set(int unit, soc_mem_t mem, int bank, int hash_offset, 886 int use_lsb) 887 { 888 uint32 hash_control_entry[4]; 889 soc_mem_t shared_mem = INVALIDm; 890 soc_field_t field; 891 int is_shared = 1; 892 893 static const soc_field_t uft_fields_d[] = { 894 HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f, 895 HASH_OFFSET_DEDICATED_BANK_2f, HASH_OFFSET_DEDICATED_BANK_3f 896 897 }; 898 static const soc_field_t uft_fields_s[] = { 899 B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf 900 }; 901 902 903 sal_memset(hash_control_entry, 0, sizeof(hash_control_entry)); 904 905 switch(mem) { 906 case L2Xm: 907 if (bank < 0 || bank > 1) { 908 return SOC_E_PARAM; 909 } 910 mem = L2_ENTRY_HASH_CONTROLm; 911 field = uft_fields_d[bank]; 912 is_shared = 0; 913 break; 914 case EXACT_MATCH_2m: 915 case EXACT_MATCH_4m: 916 if (bank < 0 || bank > 3) { 917 return SOC_E_PARAM; 918 } 919 mem = EXACT_MATCH_HASH_CONTROLm; 920 shared_mem = UFT_SHARED_BANKS_CONTROLm; 921 field = uft_fields_s[bank]; 922 break; 923 case L3_TUNNEL_SINGLEm: 924 case L3_TUNNEL_DOUBLEm: 925 case L3_TUNNEL_QUADm: 926 if (bank < 0 || bank > 3) { 927 return SOC_E_PARAM; 928 } 929 mem = L3_TUNNEL_HASH_CONTROLm; 930 field = uft_fields_d[bank]; 931 is_shared = 0; 932 break; 933 case L3_ENTRY_SINGLEm: 934 case L3_ENTRY_DOUBLEm: 935 case L3_ENTRY_QUADm: 936 case L3_ENTRY_ONLYm: 937 case L3_ENTRY_ONLY_SINGLEm: 938 if (bank < 0 || bank > 3) { 939 return SOC_E_PARAM; 940 } 941 mem = L3_ENTRY_HASH_CONTROLm; 942 is_shared = 0; 943 field = uft_fields_d[bank]; 944 break; 945 case MPLS_ENTRY_SINGLEm: 946 if (bank < 0 || bank > 1) { 947 return SOC_E_PARAM; 948 } 949 mem = MPLS_ENTRY_HASH_CONTROLm; 950 is_shared = 0; 951 field = uft_fields_d[bank]; 952 break; 953 default: 954 return SOC_E_INTERNAL; 955 } 956 957 /* Shared Banks */ 958 if (is_shared > 0) { 959 SOC_IF_ERROR_RETURN(soc_mem_read(unit, shared_mem, MEM_BLOCK_ALL, 0, 960 hash_control_entry)); 961 soc_mem_field32_set(unit, shared_mem, hash_control_entry, field, hash_offset); 962 SOC_IF_ERROR_RETURN( 963 soc_mem_write(unit, shared_mem, MEM_BLOCK_ALL, 0, hash_control_entry)); 964 } else { 965 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0, 966 hash_control_entry)); 967 soc_mem_field32_set(unit, mem, hash_control_entry, HASH_TABLE_TEST_MODEf, 968 use_lsb); 969 soc_mem_field32_set(unit, mem, hash_control_entry, field, hash_offset); 970 SOC_IF_ERROR_RETURN( 971 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, hash_control_entry)); 972 } 973 974 return SOC_E_NONE; 975 } 976 977 978 int 979 soc_tomahawk3_hash_index_get(int unit, int mem, int bank, int bucket) 980 { 981 int rv; 982 int index = 0; 983 int entries_per_row, bank_base, bucket_offset, entries_per_bucket; 984 985 switch(mem) { 986 case MPLS_ENTRY_SINGLEm: 987 rv = soc_tomahawk3_hash_bank_info_get(unit, mem, bank, NULL, 988 NULL, &entries_per_bucket, 989 &bank_base, &bucket_offset); 990 if (SOC_SUCCESS(rv)) { 991 index = bank_base + bucket * entries_per_bucket + bucket_offset; 992 } 993 break; 994 995 default: 996 rv = soc_tomahawk3_hash_bank_info_get(unit, mem, bank, NULL, 997 &entries_per_row, NULL, &bank_base, 998 &bucket_offset); 999 if (SOC_SUCCESS(rv)) { 1000 index = bank_base + bucket * entries_per_row + bucket_offset; 1001 return index; 1002 } 1003 break; 1004 } 1005 1006 return index; 1007 } 1008 1009 1010 uint32 1011 soc_tomahawk3_l2x_hash(int unit, int bank, int hash_offset, int use_lsb, 1012 int key_nbits, void *base_entry, uint8 *key1, uint8 *key2) 1013 { 1014 uint16 lsb_val; 1015 uint32 hash_mask = 0x03FF; /* 1k buckets per dedicated L2 bank */ 1016 uint32 hash_bits = 10; 1017 1018 if (use_lsb && (hash_offset + hash_bits > 32)) { 1019 switch (soc_mem_field32_get(unit, L2Xm, base_entry, KEY_TYPEf)) { 1020 case TH3_L2_HASH_KEY_TYPE_BRIDGE: 1021 lsb_val = 1022 soc_mem_field32_get(unit, L2Xm, base_entry, L2__HASH_LSBf); 1023 break; 1024 default: 1025 lsb_val = 0; 1026 break; 1027 } 1028 } else { 1029 lsb_val = 0; 1030 } 1031 1032 return _soc_tomahawk3_shared_hash(unit, 1033 hash_offset, key_nbits, key1, key2, hash_mask, lsb_val, use_lsb); 1034 } 1035 1036 int 1037 soc_tomahawk3_l2x_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key) 1038 { 1039 soc_field_t field_list[2]; 1040 1041 switch (soc_mem_field32_get(unit, L2Xm, entry, KEY_TYPEf)) { 1042 case TH3_L2_HASH_KEY_TYPE_BRIDGE: 1043 field_list[0] = L2__KEYf; 1044 break; 1045 case TH3_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT: 1046 field_list[0] = VLAN__KEYf; 1047 break; 1048 default: 1049 return 0; 1050 } 1051 field_list[1] = INVALIDf; 1052 return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, L2Xm, field_list); 1053 } 1054 1055 uint32 1056 soc_tomahawk3_l2x_entry_hash(int unit, int bank, int hash_offset, int use_lsb, 1057 uint32 *entry) 1058 { 1059 int key_nbits; 1060 uint8 key1[SOC_MAX_MEM_WORDS * 4] = {0}; 1061 uint8 key2[SOC_MAX_MEM_WORDS * 4] = {0}; 1062 1063 key_nbits = soc_tomahawk3_l2x_base_entry_to_key(unit, 0, entry, key1); 1064 key_nbits = soc_tomahawk3_l2x_base_entry_to_key(unit, 1, entry, key2); 1065 return soc_tomahawk3_l2x_hash( 1066 unit, bank, hash_offset, use_lsb, key_nbits, entry, key1, key2); 1067 } 1068 1069 uint32 1070 soc_tomahawk3_l2x_bank_entry_hash(int unit, int bank, uint32 *entry) 1071 { 1072 int rv, hash_offset, use_lsb; 1073 1074 rv = soc_tomahawk3_hash_offset_get(unit, L2Xm, bank, &hash_offset, &use_lsb); 1075 if (SOC_FAILURE(rv)) { 1076 return 0; 1077 } 1078 1079 return soc_tomahawk3_l2x_entry_hash(unit, bank, hash_offset, use_lsb, entry); 1080 } 1081 1082 int 1083 soc_tomahawk3_hash_init(int unit) 1084 { 1085 #define KEY_ATTR_MEM_FIELD_CNT 5 1086 int index; 1087 int mem_idx, field_idx; 1088 int shared_bank_offset = 0; 1089 int num_fpem_banks = 0; 1090 int num_dedicated_banks = 2; 1091 int offset_base, offset_multiplier; 1092 uint32 fields_val[KEY_ATTR_MEM_FIELD_CNT] = {0}; 1093 uint32 hash_control_entry[SOC_MAX_MEM_WORDS]; 1094 uft_shared_banks_control_entry_t shared_hash_control_entry; 1095 static const soc_mem_t dedicated_bank_mem[][2] = { 1096 { L2Xm, L2_ENTRY_HASH_CONTROLm }, 1097 { L3_ENTRY_SINGLEm, L3_ENTRY_HASH_CONTROLm }, 1098 { MPLS_ENTRY_SINGLEm, MPLS_ENTRY_HASH_CONTROLm }, 1099 { L3_TUNNEL_SINGLEm, L3_TUNNEL_HASH_CONTROLm } 1100 }; 1101 static const soc_field_t logical_to_physical_fields[] = { 1102 LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf, 1103 LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf, 1104 LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf, 1105 LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf 1106 }; 1107 static const soc_field_t dedicated_fields[] = { 1108 HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f, 1109 HASH_OFFSET_DEDICATED_BANK_2f, HASH_OFFSET_DEDICATED_BANK_3f 1110 }; 1111 static const soc_field_t shared_fields[] = { 1112 B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf, 1113 B4_HASH_OFFSETf, B5_HASH_OFFSETf, B6_HASH_OFFSETf, B7_HASH_OFFSETf 1114 }; 1115 1116 /* PARAMETERS FOR <xyz>_KEY_ATTRIBUTE MEMORY 1117 * 1118 * NOTE: 1) Each supported KEY_TYPE for the mem should have one entry. 1119 * 2) All entries to the array should be sequential in terms of 1120 * the KEY_TYPE value, i.e. if a memory supports 2 keys with 1121 * values 0 and 2 then add three entries to the table with 2nd 1122 * entry as all 0's and comment as 'Not Supported'. See 1123 * l3_key_type_attr below as an example. 1124 * 3) If a new KEY TYPE is defined later, please add an entry below 1125 * 1126 * The below defined <XYZ>_key_type_attr array declares the values 1127 * for these five fields from the respective KEY_ATTRIBUTE memory, 1128 * { BUCKET |KEY |KEY |DATA |HASH } 1129 * { MODE |WIDTH |BASEWIDTH |BASEWIDTH |LSBOFFSET } 1130 */ 1131 static const uint8 l2x_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = { 1132 { 0 ,15 ,0 ,0 ,0 }, /* BRIDGE */ 1133 { 0 ,6 ,0 ,0 ,0 } /* SINGLE X CONNECT VLAN */ 1134 }; 1135 static const uint8 l3_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = { 1136 { 0 ,11 ,0 ,1 ,0 }, /* IPV4UC */ 1137 { 0 ,0 ,0 ,0 ,0 }, /* Not Supported */ 1138 { 0 ,15 ,1 ,2 ,0 }, /* IPV6UC */ 1139 { 0 ,0 ,0 ,0 ,0 }, /* Not Supported */ 1140 { 0 ,22 ,0 ,1 ,0 }, /* IPV4MC */ 1141 { 0 ,23 ,2 ,1 ,0 } /* IPV6MC */ 1142 }; 1143 static const uint8 mpls_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = { 1144 { 0 ,7 ,0 ,0 ,0 } /* MPLS */ 1145 }; 1146 static const uint8 tunnel_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = { 1147 { 0 ,7 ,0 ,0 ,0 }, /* MPLS */ 1148 { 0 ,3 ,1 ,0 ,0 }, /* IPV4 */ 1149 { 0 ,7 ,3 ,0 ,0 } /* IPv6 */ 1150 }; 1151 static const uint8 fpem_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = { 1152 { 0 ,3 ,1 ,0 ,0 }, /* MODE128 */ 1153 { 0 ,11 ,1 ,0 ,0 }, /* MODE160 */ 1154 { 0 ,21 ,2 ,1 ,0 } /* MODE320 */ 1155 }; 1156 static const struct key_type_attr_mem_mappings_s { 1157 soc_mem_t mem; /* Key Attribut Memory */ 1158 int key_cnt; /* KeyType Max count from the enums */ 1159 const uint8 (*map)[KEY_ATTR_MEM_FIELD_CNT]; /* key attr fields vals */ 1160 } key_attr_map[] = { 1161 { L2_ENTRY_KEY_ATTRIBUTESm, 1162 TH3_L2_HASH_KEY_TYPE_COUNT, l2x_key_type_attr }, 1163 { L3_ENTRY_KEY_ATTRIBUTESm, 1164 TH3_L3_HASH_KEY_TYPE_COUNT, l3_key_type_attr }, 1165 { MPLS_ENTRY_KEY_ATTRIBUTESm, 1166 TH3_MPLS_HASH_KEY_TYPE_COUNT, mpls_key_type_attr }, 1167 { L3_TUNNEL_KEY_ATTRIBUTESm, 1168 TH3_TUNNEL_HASH_KEY_TYPE_COUNT, tunnel_key_type_attr }, 1169 { EXACT_MATCH_KEY_ATTRIBUTESm, 1170 TH3_FPEM_HASH_KEY_TYPE_COUNT, fpem_key_type_attr } 1171 }; 1172 soc_field_t key_attr_mem_fields[KEY_ATTR_MEM_FIELD_CNT] = { 1173 BUCKET_MODEf, 1174 KEY_WIDTHf, 1175 KEY_BASE_WIDTHf, 1176 DATA_BASE_WIDTHf, 1177 HASH_LSB_OFFSETf 1178 }; 1179 1180 #if 0 1181 1182 if (soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) { 1183 int non_alpm = num_fpem_banks + num_l3_banks + 1184 num_l2_banks - 2 * (num_dedicated_banks); 1185 sal_memset(hash_control_entry, 0, 1186 sizeof(uft_shared_banks_control_entry_t)); 1187 SOC_IF_ERROR_RETURN 1188 (READ_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0, 1189 hash_control_entry)); 1190 if ((non_alpm) && (non_alpm <= 4)) { 1191 /* If Shared banks are used between ALPM and non-ALPM memories, 1192 * then ALPM uses Shared Bank B2, B3, B4, B5 and non-ALPM uses 1193 * B6, B7, B8, B9 banks 1194 */ 1195 soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm, 1196 hash_control_entry, ALPM_MODEf, 1); 1197 num_shared_alpm_banks[unit] = 4; 1198 shared_bank_offset += 4; 1199 } else { 1200 soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm, 1201 hash_control_entry, ALPM_MODEf, 0); 1202 num_shared_alpm_banks[unit] = 8; 1203 } 1204 SOC_IF_ERROR_RETURN 1205 (WRITE_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1206 hash_control_entry)); 1207 } 1208 #endif 1209 1210 /* Program the hash memories which has dedicated banks */ 1211 for (mem_idx = 0 ; mem_idx < COUNTOF(dedicated_bank_mem) ; mem_idx++) { 1212 sal_memset(hash_control_entry, 0, sizeof(hash_control_entry)); 1213 SOC_IF_ERROR_RETURN( 1214 soc_tomahawk3_hash_bank_count_get( 1215 unit, dedicated_bank_mem[mem_idx][0], &num_dedicated_banks)); 1216 1217 offset_multiplier = 64 / num_dedicated_banks; 1218 offset_base = 64 % num_dedicated_banks; 1219 1220 SOC_IF_ERROR_RETURN( 1221 soc_mem_read(unit, 1222 dedicated_bank_mem[mem_idx][1], 1223 MEM_BLOCK_ANY, 0, hash_control_entry)); 1224 soc_mem_field32_set( 1225 unit, dedicated_bank_mem[mem_idx][1], hash_control_entry, 1226 HASH_TABLE_BANK_CONFIGf, ((1 << num_dedicated_banks) - 1)); 1227 1228 for (index = 0; index < num_dedicated_banks; index++) { 1229 soc_mem_field32_set( 1230 unit, dedicated_bank_mem[mem_idx][1], hash_control_entry, 1231 dedicated_fields[index], offset_base+(index*offset_multiplier)); 1232 } 1233 SOC_IF_ERROR_RETURN( 1234 soc_mem_write(unit, 1235 dedicated_bank_mem[mem_idx][1], 1236 MEM_BLOCK_ALL, 0, hash_control_entry)); 1237 } 1238 1239 /* Program the hash memories which has shared banks */ 1240 sal_memset(hash_control_entry, 0, sizeof(exact_match_hash_control_entry_t)); 1241 sal_memset(&shared_hash_control_entry, 0, 1242 sizeof(uft_shared_banks_control_entry_t)); 1243 SOC_IF_ERROR_RETURN 1244 (READ_EXACT_MATCH_HASH_CONTROLm( 1245 unit, MEM_BLOCK_ANY, 0, hash_control_entry)); 1246 SOC_IF_ERROR_RETURN 1247 (READ_UFT_SHARED_BANKS_CONTROLm( 1248 unit, MEM_BLOCK_ANY, 0, &shared_hash_control_entry)); 1249 SOC_IF_ERROR_RETURN 1250 (soc_tomahawk3_hash_bank_count_get( 1251 unit, EXACT_MATCH_2m, &num_fpem_banks)); 1252 1253 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, hash_control_entry, 1254 HASH_TABLE_BANK_CONFIGf, 1255 ((1 << num_fpem_banks) - 1) << shared_bank_offset); 1256 /* Handle case where fpem banks are set to 0 */ 1257 if (num_fpem_banks) { 1258 offset_multiplier = 64 / num_fpem_banks; 1259 offset_base = 64 % num_fpem_banks; 1260 } 1261 for (index = 0 ; index < num_fpem_banks; index++) { 1262 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm , hash_control_entry, 1263 logical_to_physical_fields[index], index + 1264 shared_bank_offset); 1265 soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm, 1266 &shared_hash_control_entry, 1267 shared_fields[shared_bank_offset + index], 1268 offset_base + (index * offset_multiplier)); 1269 } 1270 1271 SOC_IF_ERROR_RETURN 1272 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1273 hash_control_entry)); 1274 SOC_IF_ERROR_RETURN 1275 (WRITE_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1276 &shared_hash_control_entry)); 1277 1278 /* Program the KEY_ATTRIBUTE memories */ 1279 for (mem_idx = 0 ; mem_idx < COUNTOF(key_attr_map) ; mem_idx++) { 1280 /* Clear the memory to begin-with */ 1281 1282 1283 /* Write the relevant entries in it */ 1284 for (index = 0 ; index < key_attr_map[mem_idx].key_cnt ; index++) { 1285 for (field_idx=0 ; field_idx<KEY_ATTR_MEM_FIELD_CNT ; field_idx++) { 1286 fields_val[field_idx] = 1287 (key_attr_map[mem_idx].map)[index][field_idx]; 1288 } 1289 SOC_IF_ERROR_RETURN( 1290 soc_mem_fields32_modify(unit, key_attr_map[mem_idx].mem, index, 1291 KEY_ATTR_MEM_FIELD_CNT, key_attr_mem_fields, fields_val)); 1292 } 1293 } 1294 #undef KEY_ATTR_MEM_FIELD_CNT 1295 1296 /* Robust Hash initialization */ 1297 #ifdef SOC_ROBUST_HASH 1298 1299 /* Initialize Robust Hash Global Datastructure */ 1300 if (soc_feature(unit, soc_feature_robust_hash)) { 1301 uint32 seed = 0; 1302 uint32 hash_control_entry[4]; 1303 1304 if (NULL == ROBUSTHASH(unit)) { 1305 ROBUSTHASH(unit) = sal_alloc(sizeof(soc_robust_hash_db_t), 1306 "soc_robust_hash"); 1307 if (ROBUSTHASH(unit) == NULL) { 1308 return SOC_E_MEMORY; 1309 } 1310 sal_memset(ROBUSTHASH(unit), 0, sizeof(soc_robust_hash_db_t)); 1311 } 1312 1313 /* L2 Robust Hash Init */ 1314 1315 sal_memset(hash_control_entry, 0, sizeof(l2_entry_hash_control_entry_t)); 1316 1317 /* Disable robust hash for L2 - this config variable is used only 1318 * for debug purposes*/ 1319 if ((soc_property_get(unit, "robust_hash_disable_l2", 0)) == 1) { 1320 SOC_IF_ERROR_RETURN 1321 (READ_L2_ENTRY_HASH_CONTROLm 1322 (unit, MEM_BLOCK_ANY, 0, hash_control_entry)); 1323 soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm , 1324 hash_control_entry, ROBUST_HASH_ENf, 0x0); 1325 SOC_IF_ERROR_RETURN 1326 (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1327 hash_control_entry)); 1328 ROBUSTHASH(unit)->l2.enable = 0; 1329 } else { 1330 /* Enable robust hashing */ 1331 SOC_IF_ERROR_RETURN 1332 (READ_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, 1333 hash_control_entry)); 1334 soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, 1335 hash_control_entry, ROBUST_HASH_ENf, 0x1); 1336 SOC_IF_ERROR_RETURN 1337 (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1338 hash_control_entry)); 1339 ROBUSTHASH(unit)->l2.enable = 1; 1340 1341 /* Configure remap and action tables for L2 table */ 1342 ROBUSTHASH(unit)->l2.remap_tab[0] = L2_ENTRY_REMAP_TABLE_Am; 1343 ROBUSTHASH(unit)->l2.remap_tab[1] = L2_ENTRY_REMAP_TABLE_Bm; 1344 ROBUSTHASH(unit)->l2.action_tab[0] = L2_ENTRY_ACTION_TABLE_Am; 1345 ROBUSTHASH(unit)->l2.action_tab[1] = L2_ENTRY_ACTION_TABLE_Bm; 1346 1347 /* Initialize seed for robust hash */ 1348 seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_L2, 16777213); 1349 1350 SOC_IF_ERROR_RETURN 1351 (soc_robust_hash_table_set(unit, 1352 &(ROBUSTHASH(unit)->l2), 1353 seed)); 1354 } 1355 1356 /* L3 Robust Hash Init */ 1357 1358 sal_memset(hash_control_entry, 0, sizeof(l3_entry_hash_control_entry_t)); 1359 1360 /* Disable robust hash for L3 - this config variable is used only 1361 * for debug purposes*/ 1362 if ((soc_property_get(unit, "robust_hash_disable_l3", 0)) == 1) { 1363 SOC_IF_ERROR_RETURN 1364 (READ_L3_ENTRY_HASH_CONTROLm 1365 (unit, MEM_BLOCK_ANY, 0, hash_control_entry)); 1366 soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm , 1367 hash_control_entry, ROBUST_HASH_ENf, 0x0); 1368 SOC_IF_ERROR_RETURN 1369 (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1370 hash_control_entry)); 1371 ROBUSTHASH(unit)->l3.enable = 0; 1372 } else { 1373 /* Enable robust hashing */ 1374 SOC_IF_ERROR_RETURN 1375 (READ_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, 1376 hash_control_entry)); 1377 soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, 1378 hash_control_entry, ROBUST_HASH_ENf, 0x1); 1379 SOC_IF_ERROR_RETURN 1380 (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1381 hash_control_entry)); 1382 ROBUSTHASH(unit)->l3.enable = 1; 1383 1384 /* Configure remap and action tables for L3 table */ 1385 ROBUSTHASH(unit)->l3.remap_tab[0] = L3_ENTRY_REMAP_TABLE_Am; 1386 ROBUSTHASH(unit)->l3.remap_tab[1] = L3_ENTRY_REMAP_TABLE_Bm; 1387 ROBUSTHASH(unit)->l3.action_tab[0] = L3_ENTRY_ACTION_TABLE_Am; 1388 ROBUSTHASH(unit)->l3.action_tab[1] = L3_ENTRY_ACTION_TABLE_Bm; 1389 1390 /* Initialize seed for robust hash */ 1391 seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_L3, 16777213); 1392 1393 SOC_IF_ERROR_RETURN 1394 (soc_robust_hash_table_set(unit, 1395 &(ROBUSTHASH(unit)->l3), 1396 seed)); 1397 } 1398 1399 /* Exact Match Robust Hash Init */ 1400 1401 sal_memset 1402 (hash_control_entry, 0, sizeof(exact_match_hash_control_entry_t)); 1403 1404 /* Disable robust hash for EM - this config variable is used only 1405 * for debug purposes*/ 1406 if ((soc_property_get 1407 (unit, "robust_hash_disable_exact_match", 0)) == 1) { 1408 SOC_IF_ERROR_RETURN 1409 (READ_EXACT_MATCH_HASH_CONTROLm 1410 (unit, MEM_BLOCK_ANY, 0, hash_control_entry)); 1411 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm , 1412 hash_control_entry, ROBUST_HASH_ENf, 0x0); 1413 SOC_IF_ERROR_RETURN 1414 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1415 hash_control_entry)); 1416 ROBUSTHASH(unit)->exact_match.enable = 0; 1417 } else { 1418 /* Enable robust hashing */ 1419 SOC_IF_ERROR_RETURN 1420 (READ_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, 1421 hash_control_entry)); 1422 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, 1423 hash_control_entry, ROBUST_HASH_ENf, 0x1); 1424 SOC_IF_ERROR_RETURN 1425 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1426 hash_control_entry)); 1427 ROBUSTHASH(unit)->exact_match.enable = 1; 1428 1429 /* Configure remap and action tables for EM table */ 1430 ROBUSTHASH(unit)->exact_match.remap_tab[0] = EXACT_MATCH_REMAP_TABLE_Am; 1431 ROBUSTHASH(unit)->exact_match.remap_tab[1] = EXACT_MATCH_REMAP_TABLE_Bm; 1432 ROBUSTHASH(unit)->exact_match.action_tab[0] = EXACT_MATCH_ACTION_TABLE_Am; 1433 ROBUSTHASH(unit)->exact_match.action_tab[1] = EXACT_MATCH_ACTION_TABLE_Bm; 1434 1435 /* Initialize seed for robust hash */ 1436 seed = soc_property_get 1437 (unit, spn_ROBUST_HASH_SEED_EXACT_MATCH, 16777213); 1438 1439 SOC_IF_ERROR_RETURN 1440 (soc_robust_hash_table_set(unit, 1441 &(ROBUSTHASH(unit)->exact_match), 1442 seed)); 1443 } 1444 1445 /* Mpls Robust Hash Init */ 1446 1447 sal_memset 1448 (hash_control_entry, 0, sizeof(mpls_entry_hash_control_entry_t)); 1449 1450 /* Disable robust hash for mpls - this config variable is 1451 * used only for debug purposes*/ 1452 if ((soc_property_get 1453 (unit, "robust_hash_disable_mpls", 0)) == 1) { 1454 SOC_IF_ERROR_RETURN 1455 (READ_MPLS_ENTRY_HASH_CONTROLm 1456 (unit, MEM_BLOCK_ANY, 0, hash_control_entry)); 1457 soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm , 1458 hash_control_entry, ROBUST_HASH_ENf, 0x0); 1459 SOC_IF_ERROR_RETURN 1460 (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1461 hash_control_entry)); 1462 ROBUSTHASH(unit)->mpls_entry.enable = 0; 1463 } else { 1464 /* Enable robust hashing */ 1465 SOC_IF_ERROR_RETURN 1466 (READ_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, 1467 hash_control_entry)); 1468 soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, 1469 hash_control_entry, ROBUST_HASH_ENf, 0x1); 1470 SOC_IF_ERROR_RETURN 1471 (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1472 hash_control_entry)); 1473 ROBUSTHASH(unit)->mpls_entry.enable = 1; 1474 1475 /* Configure remap and action tables for MPLS ENTRY table */ 1476 ROBUSTHASH(unit)->mpls_entry.remap_tab[0] = 1477 MPLS_ENTRY_REMAP_TABLE_Am; 1478 ROBUSTHASH(unit)->mpls_entry.remap_tab[1] = 1479 MPLS_ENTRY_REMAP_TABLE_Bm; 1480 ROBUSTHASH(unit)->mpls_entry.action_tab[0] = 1481 MPLS_ENTRY_ACTION_TABLE_Am; 1482 ROBUSTHASH(unit)->mpls_entry.action_tab[1] = 1483 MPLS_ENTRY_ACTION_TABLE_Bm; 1484 1485 /* Initialize seed for robust hash */ 1486 seed = soc_property_get 1487 (unit, spn_ROBUST_HASH_SEED_MPLS, 16777213); 1488 1489 SOC_IF_ERROR_RETURN 1490 (soc_robust_hash_table_set(unit, 1491 &(ROBUSTHASH(unit)->mpls_entry), 1492 seed)); 1493 } 1494 1495 1496 /* Tunnel Robust Hash Init */ 1497 1498 sal_memset 1499 (hash_control_entry, 0, sizeof(tunnel_hash_control_entry_t)); 1500 1501 /* Disable robust hash for mpls - this config variable is 1502 * used only for debug purposes*/ 1503 if ((soc_property_get 1504 (unit, "robust_hash_disable_mpls", 0)) == 1) { 1505 SOC_IF_ERROR_RETURN 1506 (READ_L3_TUNNEL_HASH_CONTROLm 1507 (unit, MEM_BLOCK_ANY, 0, hash_control_entry)); 1508 soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm , 1509 hash_control_entry, ROBUST_HASH_ENf, 0x0); 1510 SOC_IF_ERROR_RETURN 1511 (WRITE_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1512 hash_control_entry)); 1513 ROBUSTHASH(unit)->tunnel.enable = 0; 1514 } else { 1515 /* Enable robust hashing */ 1516 SOC_IF_ERROR_RETURN 1517 (READ_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, 1518 hash_control_entry)); 1519 soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm, 1520 hash_control_entry, ROBUST_HASH_ENf, 0x1); 1521 SOC_IF_ERROR_RETURN 1522 (WRITE_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 1523 hash_control_entry)); 1524 ROBUSTHASH(unit)->tunnel.enable = 1; 1525 1526 /* Configure remap and action tables for L3_TUNNEL ENTRY table */ 1527 ROBUSTHASH(unit)->tunnel.remap_tab[0] = 1528 L3_TUNNEL_REMAP_TABLE_Am; 1529 ROBUSTHASH(unit)->tunnel.remap_tab[1] = 1530 L3_TUNNEL_REMAP_TABLE_Bm; 1531 ROBUSTHASH(unit)->tunnel.action_tab[0] = 1532 L3_TUNNEL_ACTION_TABLE_Am; 1533 ROBUSTHASH(unit)->tunnel.action_tab[1] = 1534 L3_TUNNEL_ACTION_TABLE_Bm; 1535 1536 /* Initialize seed for robust hash */ 1537 seed = soc_property_get 1538 (unit, spn_ROBUST_HASH_SEED_L3_TUNNEL, 16777213); 1539 1540 SOC_IF_ERROR_RETURN 1541 (soc_robust_hash_table_set(unit, 1542 &(ROBUSTHASH(unit)->tunnel), 1543 seed)); 1544 } 1545 1546 1547 1548 } 1549 #endif /* SOC_ROBUST_HASH */ 1550 1551 return SOC_E_NONE; 1552 } 1553 1554 int 1555 soc_tomahawk3_shared_hash_mem_bucket_read(int unit, int ent, int entry_width, int *width, 1556 soc_mem_t base_mem, soc_mem_t *mem, 1557 void *bkt_entry, void *entry) 1558 { 1559 1560 soc_mem_info_t meminfo; 1561 soc_field_info_t fieldinfo; 1562 /* Exclude HIT bit */ 1563 int entry_bits = 0, hit_bits=0; 1564 1565 if (entry_width <= 0) { 1566 return (SOC_E_PARAM); 1567 } 1568 1569 switch (base_mem) { 1570 case L3_ENTRY_SINGLEm: 1571 case L3_ENTRY_ONLY_SINGLEm: 1572 case L3_ENTRY_DOUBLEm: 1573 case L3_ENTRY_QUADm: 1574 switch (entry_width) { 1575 case 1: /* 1 base_entry wide */ 1576 *width = 1; 1577 *mem = L3_ENTRY_SINGLEm; 1578 break; 1579 case 2: /* 2 base entries wide */ 1580 *width = 2; 1581 *mem = L3_ENTRY_DOUBLEm; 1582 break; 1583 default: 1584 *width = 4; /* 4 base_entries wide */ 1585 *mem = L3_ENTRY_QUADm; 1586 } 1587 hit_bits = *width; 1588 break; 1589 1590 case EXACT_MATCH_2m: 1591 case EXACT_MATCH_4m: 1592 switch (entry_width) { 1593 case 2: 1594 *width = 1; 1595 *mem = EXACT_MATCH_2m; 1596 break; 1597 case 4: 1598 default: 1599 *width = 2; 1600 *mem = EXACT_MATCH_4m; 1601 } 1602 break; 1603 1604 case MPLS_ENTRY_SINGLEm: 1605 *width = 1; 1606 *mem = MPLS_ENTRY_SINGLEm; 1607 break; 1608 1609 case L3_TUNNEL_SINGLEm: 1610 case L3_TUNNEL_DOUBLEm: 1611 case L3_TUNNEL_QUADm: 1612 switch (entry_width) { 1613 case 1: /* 1 base_entry wide */ 1614 *width = 1; 1615 *mem = L3_TUNNEL_SINGLEm; 1616 break; 1617 case 2: /* 2 base entries wide */ 1618 *width = 2; 1619 *mem = L3_TUNNEL_DOUBLEm; 1620 break; 1621 default: 1622 *width = 4; /* 4 base_entries wide */ 1623 *mem = L3_TUNNEL_QUADm; 1624 } 1625 break; 1626 1627 default: 1628 return SOC_E_PARAM; 1629 } 1630 1631 entry_bits = soc_mem_entry_bits(unit, *mem) - hit_bits; 1632 1633 meminfo.flags = 0; 1634 meminfo.bytes = SOC_MEM_WORDS(unit, base_mem) * 4; 1635 fieldinfo.flags = SOCF_LE; 1636 fieldinfo.len = entry_bits; 1637 1638 fieldinfo.bp = entry_bits * (ent/entry_width); 1639 (void)soc_meminfo_fieldinfo_field_get(bkt_entry, &meminfo, 1640 &fieldinfo, entry); 1641 1642 return SOC_E_NONE; 1643 1644 } 1645 1646 1647 int 1648 soc_tomahawk3_hash_mem_status_get(int unit, soc_mem_t mem, void* entry, uint32 *v) { 1649 int i; 1650 v[0] = v[1] = v[2] = v[3] = 0; 1651 1652 switch (mem) { 1653 case L3_ENTRY_QUADm: 1654 case L3_TUNNEL_QUADm: 1655 case EXACT_MATCH_4m: 1656 soc_mem_field_get(unit, mem, entry, BASE_VALID_3f, &v[3]); 1657 soc_mem_field_get(unit, mem, entry, BASE_VALID_2f, &v[2]); 1658 /* pass through */ 1659 case L3_ENTRY_DOUBLEm: 1660 case L3_TUNNEL_DOUBLEm: 1661 case EXACT_MATCH_2m: 1662 soc_mem_field_get(unit, mem, entry, BASE_VALID_1f, &v[1]); 1663 soc_mem_field_get(unit, mem, entry, BASE_VALID_0f, &v[0]); 1664 break; 1665 case L3_ENTRY_SINGLEm: 1666 case L3_TUNNEL_SINGLEm: 1667 case L3_ENTRY_ONLY_SINGLEm: 1668 case MPLS_ENTRY_SINGLEm: 1669 soc_mem_field_get(unit, mem, entry, BASE_VALIDf, &v[0]); 1670 break; 1671 default: 1672 v[0] = v[1] = v[2] = v[3] = 1; 1673 break; 1674 1675 } 1676 /* Use v[i] for constructing a valid bitmap */ 1677 for (i = 0; i < 4; i++) { 1678 v[i] = (v[i] > 0); 1679 } 1680 return SOC_E_NONE; 1681 } 1682 1683 1684 /* Get bank bitmap for the hash table 1685 * Required only for shared hash tables 1686 */ 1687 int 1688 soc_tomahawk3_hash_bank_phy_bitmap_get(int unit, soc_mem_t mem, uint32 *bitmap) 1689 { 1690 uint32 hash_control_entry[4]; 1691 switch(mem) { 1692 case L2Xm: 1693 mem = L2_ENTRY_HASH_CONTROLm; 1694 break; 1695 case L3_ENTRY_SINGLEm: 1696 case L3_ENTRY_ONLY_SINGLEm: 1697 case L3_ENTRY_DOUBLEm: 1698 case L3_ENTRY_ONLY_DOUBLEm: 1699 case L3_ENTRY_QUADm: 1700 case L3_ENTRY_ONLY_QUADm: 1701 mem = L3_ENTRY_HASH_CONTROLm; 1702 break; 1703 case EXACT_MATCH_2m: 1704 case EXACT_MATCH_4m: 1705 mem = EXACT_MATCH_HASH_CONTROLm; 1706 break; 1707 case MPLS_ENTRY_SINGLEm: 1708 mem = MPLS_ENTRY_HASH_CONTROLm; 1709 break; 1710 case L3_TUNNEL_SINGLEm: 1711 case L3_TUNNEL_DOUBLEm: 1712 case L3_TUNNEL_QUADm: 1713 mem = L3_TUNNEL_HASH_CONTROLm; 1714 break; 1715 default: 1716 return SOC_E_PARAM; 1717 } 1718 1719 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0, 1720 hash_control_entry)); 1721 *bitmap = soc_mem_field32_get(unit, mem, hash_control_entry, 1722 HASH_TABLE_BANK_CONFIGf); 1723 1724 return SOC_E_NONE; 1725 } 1726 1727 uint32 1728 soc_tomahawk3_l3x_hash(int unit, int bank, int hash_offset, int use_lsb, 1729 int key_nbits, void *base_entry, uint8 *key1, uint8 *key2) 1730 { 1731 uint32 lsb_val; 1732 uint32 hash_mask; 1733 uint32 hash_bits; 1734 1735 hash_mask = 0x3FF; /* 1k buckets per dedicated banks */ 1736 hash_bits = 10; 1737 1738 1739 if (use_lsb && (hash_offset + hash_bits > 32)) { 1740 switch (soc_mem_field32_get(unit, L3_ENTRY_SINGLEm, base_entry, 1741 KEY_TYPEf)) { 1742 case TH3_L3_HASH_KEY_TYPE_V4UC: 1743 case TH3_L3_HASH_KEY_TYPE_V4MC: 1744 case TH3_L3_HASH_KEY_TYPE_V6UC: 1745 case TH3_L3_HASH_KEY_TYPE_V6MC: 1746 lsb_val = soc_mem_field32_get(unit, L3_ENTRY_SINGLEm, 1747 base_entry, IPV4UC__HASH_LSBf); 1748 break; 1749 default: 1750 lsb_val = 0; 1751 break; 1752 } 1753 } else { 1754 lsb_val = 0; 1755 } 1756 1757 return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2, 1758 hash_mask, lsb_val, use_lsb); 1759 } 1760 1761 int 1762 soc_tomahawk3_l3x_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key) 1763 { 1764 soc_mem_t mem; 1765 soc_field_t field_list[5]; 1766 1767 switch (soc_mem_field32_get(unit, L3_ENTRY_SINGLEm, entry, KEY_TYPEf)) { 1768 case TH3_L3_HASH_KEY_TYPE_V4UC: 1769 mem = L3_ENTRY_SINGLEm; 1770 field_list[0] = IPV4UC__KEYf; 1771 field_list[1] = INVALIDf; 1772 break; 1773 case TH3_L3_HASH_KEY_TYPE_V6UC: 1774 mem = L3_ENTRY_DOUBLEm; 1775 field_list[0] = IPV6UC__KEY_0f; 1776 field_list[1] = IPV6UC__KEY_1f; 1777 field_list[2] = INVALIDf; 1778 break; 1779 case TH3_L3_HASH_KEY_TYPE_V4MC: 1780 mem = L3_ENTRY_DOUBLEm; 1781 field_list[0] = IPV4MC__KEYf; 1782 field_list[1] = INVALIDf; 1783 break; 1784 case TH3_L3_HASH_KEY_TYPE_V6MC: 1785 mem = L3_ENTRY_QUADm; 1786 field_list[0] = IPV6MC__KEY_0f; 1787 field_list[1] = IPV6MC__KEY_1f; 1788 field_list[2] = IPV6MC__KEY_2f; 1789 field_list[3] = INVALIDf; 1790 break; 1791 1792 default: 1793 return 0; 1794 } 1795 return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, mem, field_list); 1796 } 1797 1798 uint32 1799 soc_tomahawk3_l3x_entry_hash(int unit, int bank, int hash_offset, int use_lsb, 1800 uint32 *entry) 1801 { 1802 int key_nbits; 1803 uint8 key1[SOC_MAX_MEM_WORDS * 4] = {0}; 1804 uint8 key2[SOC_MAX_MEM_WORDS * 4] = {0}; 1805 1806 /* Robust Hashed Key using Remap and Action Tables A */ 1807 key_nbits = soc_tomahawk3_l3x_base_entry_to_key(unit, 0, entry, key1); 1808 /* Robust Hashed Key using Remap and Action Tables B */ 1809 key_nbits = soc_tomahawk3_l3x_base_entry_to_key(unit, 1, entry, key2); 1810 1811 return soc_tomahawk3_l3x_hash(unit, bank, hash_offset, use_lsb, key_nbits, 1812 entry, key1, key2); 1813 } 1814 1815 uint32 1816 soc_tomahawk3_l3x_bank_entry_hash(int unit, int bank, uint32 *entry) 1817 { 1818 int rv, hash_offset, use_lsb; 1819 1820 rv = soc_tomahawk3_hash_offset_get(unit, L3_ENTRY_SINGLEm, bank, &hash_offset, 1821 &use_lsb); 1822 if (SOC_FAILURE(rv)) { 1823 return 0; 1824 } 1825 1826 return soc_tomahawk3_l3x_entry_hash(unit, bank, hash_offset, use_lsb, entry); 1827 } 1828 1829 uint32 1830 soc_tomahawk3_exact_match_bank_entry_hash(int unit, int bank, uint32 *entry) 1831 { 1832 int rv, hash_offset, use_lsb; 1833 1834 rv = soc_tomahawk3_hash_offset_get(unit, EXACT_MATCH_2m, bank, &hash_offset, 1835 &use_lsb); 1836 if (SOC_FAILURE(rv)) { 1837 return 0; 1838 } 1839 1840 return soc_tomahawk3_exact_match_entry_hash(unit, bank, hash_offset, use_lsb, 1841 entry); 1842 } 1843 1844 int 1845 soc_tomahawk3_hash_bucket_get(int unit, int mem, int bank, uint32 *entry, 1846 uint32 *bucket) 1847 { 1848 /* The bits in the indexes cannot be limited as TH3 operates in BM0 */ 1849 switch (mem) { 1850 case L2Xm: 1851 *bucket = soc_tomahawk3_l2x_bank_entry_hash(unit, bank, entry); 1852 break; 1853 case L3_ENTRY_ONLY_SINGLEm: 1854 case L3_ENTRY_SINGLEm: 1855 case L3_ENTRY_DOUBLEm: 1856 case L3_ENTRY_QUADm: 1857 *bucket = soc_tomahawk3_l3x_bank_entry_hash(unit, bank, entry); 1858 break; 1859 case EXACT_MATCH_2m: 1860 case EXACT_MATCH_4m: 1861 *bucket = soc_tomahawk3_exact_match_bank_entry_hash(unit, bank, entry); 1862 break; 1863 case MPLS_ENTRY_SINGLEm: 1864 *bucket = soc_tomahawk3_mpls_bank_entry_hash(unit, bank, entry); 1865 break; 1866 case L3_TUNNEL_SINGLEm: 1867 case L3_TUNNEL_DOUBLEm: 1868 case L3_TUNNEL_QUADm: 1869 *bucket = soc_tomahawk3_tunnel_bank_entry_hash(unit, bank, entry); 1870 break; 1871 default: 1872 return SOC_E_PARAM; 1873 } 1874 return SOC_E_NONE; 1875 } 1876 1877 1878 1879 int 1880 soc_tomahawk3_tbl_entries_per_sram_entry_get(int unit, soc_mem_t mem, 1881 int *table_entries_per_sram_entry) 1882 { 1883 switch (mem) { 1884 case L2Xm: 1885 case L2_ENTRY_SINGLEm: 1886 case L2_ENTRY_ONLY_SINGLEm: 1887 case L3_ENTRY_SINGLEm: 1888 case L3_TUNNEL_SINGLEm: 1889 case L3_ENTRY_ONLY_SINGLEm: 1890 *table_entries_per_sram_entry = 4; 1891 break; 1892 1893 case L3_ENTRY_DOUBLEm: 1894 case L3_TUNNEL_DOUBLEm: 1895 case EXACT_MATCH_2m: 1896 *table_entries_per_sram_entry = 2; 1897 break; 1898 1899 case L3_ENTRY_QUADm: 1900 case L3_TUNNEL_QUADm: 1901 case EXACT_MATCH_4m: 1902 *table_entries_per_sram_entry = 1; 1903 break; 1904 1905 case MPLS_ENTRY_SINGLEm: 1906 *table_entries_per_sram_entry = 1; 1907 break; 1908 1909 default: 1910 return SOC_E_PARAM; 1911 } 1912 1913 return SOC_E_NONE; 1914 } 1915 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1916