fpem.c (42377B)
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: fpem.c 8 * Purpose: Exact match table support 9 * 10 * Provides: 11 * soc_internal_exact_match_read 12 * soc_internal_exact_match_write 13 * soc_internal_exact_match_ins 14 * soc_internal_exact_match_del 15 * soc_internal_exact_match_lkup 16 */ 17 18 #include <soc/mem.h> 19 #include <soc/hash.h> 20 #include <soc/drv.h> 21 #include <shared/bsl.h> 22 #ifdef BCM_TOMAHAWK_SUPPORT 23 #include <soc/tomahawk.h> 24 #endif /* BCM_TOMAHAWK_SUPPORT */ 25 #ifdef BCM_TOMAHAWK3_SUPPORT 26 #include <soc/tomahawk3.h> 27 #endif /* BCM_TOMAHAWK3_SUPPORT */ 28 #include <shared/bsl.h> 29 #include "pcid.h" 30 #include "mem.h" 31 #include "cmicsim.h" 32 33 #ifdef BCM_TOMAHAWK_SUPPORT 34 35 enum { 36 _ENTRY0f, 37 _ENTRY1f 38 } soc_EXACT_MATCH_DUMMYm_ftype; 39 40 static soc_field_info_t soc_EXACT_MATCH_DUMMYm_fields[] = { 41 #ifdef BCM_TOMAHAWK3_SUPPORT 42 { _ENTRY0f, 240, 240, SOCF_LE }, 43 { _ENTRY1f, 240, 0, SOCF_LE } 44 #else 45 { _ENTRY0f, 0, 0, SOCF_LE }, 46 { _ENTRY1f, 0, 0, SOCF_LE } 47 #endif 48 }; 49 static soc_mem_info_t exact_match_minfo = { 50 /* mem EXACT_MATCH_?m */ 51 /* flags */ 0, 52 /* cmp_fn */ _soc_mem_cmp_undef, 53 /* *null_entry */ _soc_mem_entry_null_zeroes, 54 /* index_min */ 0, 55 /* index_max */ 0, 56 /* minblock */ 0, 57 /* maxblock */ 0, 58 /* blocks */ 0, 59 /* blocks_hi */ 0, 60 /* base */ 0, 61 /* gran */ 1, 62 #ifdef BCM_TOMAHAWK3_SUPPORT 63 /* bytes */ 60, 64 #else 65 /* bytes */ 53, 66 #endif 67 /* nFields */ 2, /* Used */ 68 /* *fields */ soc_EXACT_MATCH_DUMMYm_fields, /* Used */ 69 }; 70 71 int 72 soc_internal_exact_match_read(pcid_info_t * pcid_info, soc_mem_t mem, 73 uint32 addr, uint32 *entry) 74 { 75 int unit; 76 int offset; 77 uint32 tmp_entry[SOC_MAX_MEM_WORDS]; 78 uint32 fval; 79 int bit; 80 int bucket; 81 int index; 82 int bucket_size; 83 int block_info_index; 84 soc_block_t block; 85 uint8 acc_type; 86 soc_mem_t alt_mem; 87 uint32 alt_addr; 88 static soc_field_t hit_fields[] = { HIT_0f, HIT_1f }; 89 90 unit = pcid_info->unit; 91 offset = addr ^ SOC_MEM_INFO(unit, mem).base; 92 sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32)); 93 94 bucket_size = 2; 95 96 /* 97 * Fix exact_match_minfo using info from EXACT_MATCH_*m table 98 */ 99 #ifdef BCM_TOMAHAWK3_SUPPORT 100 if(SOC_IS_TOMAHAWK3(unit)) { 101 soc_EXACT_MATCH_DUMMYm_fields[0].len = 102 soc_EXACT_MATCH_DUMMYm_fields[1].len = 103 soc_mem_entry_bits(unit, EXACT_MATCH_2m); 104 } 105 else 106 #endif 107 { 108 soc_EXACT_MATCH_DUMMYm_fields[0].len = 109 soc_EXACT_MATCH_DUMMYm_fields[1].len = 110 soc_mem_entry_bits(unit, EXACT_MATCH_2_ENTRY_ONLYm); 111 } 112 soc_EXACT_MATCH_DUMMYm_fields[0].bp = 0; 113 soc_EXACT_MATCH_DUMMYm_fields[1].bp = 114 soc_EXACT_MATCH_DUMMYm_fields[0].len; 115 116 switch (mem) { 117 case EXACT_MATCH_4m: 118 /* Uses two slots per entry */ 119 index = offset * 2; 120 bucket = index / bucket_size; 121 122 /* Read data only portion of content */ 123 #ifdef BCM_TOMAHAWK3_SUPPORT 124 if (SOC_IS_TOMAHAWK3(unit)) { 125 alt_mem = EXACT_MATCH_2m; 126 } else 127 #endif 128 { 129 alt_mem = EXACT_MATCH_2_ENTRY_ONLYm; 130 } 131 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 132 block = SOC_BLOCK2SCH(unit, block_info_index); 133 /* Read lower half of data only entry */ 134 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 135 block_info_index, index, &acc_type); 136 soc_internal_extended_read_mem(pcid_info, block, acc_type, alt_addr, 137 entry); 138 /* Read upper half of data only entry */ 139 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 140 block_info_index, index + 1, &acc_type); 141 soc_internal_extended_read_mem(pcid_info, block, acc_type, alt_addr, 142 tmp_entry); 143 soc_meminfo_field_set(mem, &exact_match_minfo, entry, _ENTRY1f, 144 tmp_entry); 145 146 /* Read hit bit portion of content */ 147 alt_mem = EXACT_MATCH_HIT_ONLYm; 148 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 149 block = SOC_BLOCK2SCH(unit, block_info_index); 150 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 151 block_info_index, bucket, &acc_type); 152 soc_internal_extended_read_mem(pcid_info, block, acc_type, alt_addr, 153 tmp_entry); 154 fval = soc_mem_field32_get(unit, alt_mem, tmp_entry, HIT_0f); 155 soc_mem_field32_set(unit, mem, entry, HIT_0f, fval); 156 fval = soc_mem_field32_get(unit, alt_mem, tmp_entry, HIT_1f); 157 soc_mem_field32_set(unit, mem, entry, HIT_1f, fval); 158 break; 159 160 case EXACT_MATCH_2m: 161 /* Uses one slot per entry */ 162 index = offset; 163 bucket = index / bucket_size; 164 bit = index % bucket_size; 165 166 /* Read data only portion of content */ 167 #ifdef BCM_TOMAHAWK3_SUPPORT 168 if (SOC_IS_TOMAHAWK3(unit)) { 169 alt_mem = EXACT_MATCH_2m; 170 } else 171 #endif 172 { 173 alt_mem = EXACT_MATCH_2_ENTRY_ONLYm; 174 } 175 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 176 block = SOC_BLOCK2SCH(unit, block_info_index); 177 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 178 block_info_index, index, &acc_type); 179 soc_internal_extended_read_mem(pcid_info, block, acc_type, alt_addr, 180 entry); 181 182 /* Read hit bit portion of content */ 183 alt_mem = EXACT_MATCH_HIT_ONLYm; 184 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 185 block = SOC_BLOCK2SCH(unit, block_info_index); 186 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 187 block_info_index, bucket, &acc_type); 188 soc_internal_extended_read_mem(pcid_info, block, acc_type, alt_addr, 189 tmp_entry); 190 fval = soc_mem_field32_get(unit, alt_mem, tmp_entry, hit_fields[bit]); 191 soc_mem_field32_set(unit, mem, entry, HIT_0f, fval); 192 break; 193 194 default: 195 return -1; 196 } 197 198 return 0; 199 } 200 201 int 202 soc_internal_exact_match_write(pcid_info_t * pcid_info, soc_mem_t mem, 203 uint32 addr, uint32 *entry) 204 { 205 int unit; 206 int offset; 207 uint32 tmp_entry[SOC_MAX_MEM_WORDS]; 208 uint32 fval; 209 int bit; 210 int bucket; 211 int index; 212 int bucket_size; 213 int block_info_index; 214 soc_block_t block; 215 uint8 acc_type; 216 soc_mem_t alt_mem; 217 uint32 alt_addr; 218 static soc_field_t hit_fields[] = { HIT_0f, HIT_1f }; 219 220 unit = pcid_info->unit; 221 offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0xfffff; 222 223 bucket_size = 2; 224 225 /* 226 * Fix exact_match_minfo using info from EXACT_MATCH_*m table 227 */ 228 #ifdef BCM_TOMAHAWK3_SUPPORT 229 if(SOC_IS_TOMAHAWK3(unit)) { 230 soc_EXACT_MATCH_DUMMYm_fields[0].len = 231 soc_EXACT_MATCH_DUMMYm_fields[1].len = 232 soc_mem_entry_bits(unit, EXACT_MATCH_2m); 233 } 234 else 235 #endif 236 { 237 soc_EXACT_MATCH_DUMMYm_fields[0].len = 238 soc_EXACT_MATCH_DUMMYm_fields[1].len = 239 soc_mem_entry_bits(unit, EXACT_MATCH_2_ENTRY_ONLYm); 240 } 241 soc_EXACT_MATCH_DUMMYm_fields[0].bp = 0; 242 soc_EXACT_MATCH_DUMMYm_fields[1].bp = 243 soc_EXACT_MATCH_DUMMYm_fields[0].len; 244 245 switch(mem) { 246 case EXACT_MATCH_4m: 247 /* Uses two slots per entry */ 248 index = offset * 2; 249 bucket = index / bucket_size; 250 251 /* Write data only portion of content */ 252 #ifdef BCM_TOMAHAWK3_SUPPORT 253 if (SOC_IS_TOMAHAWK3(unit)) { 254 alt_mem = EXACT_MATCH_2m; 255 } else 256 #endif 257 { 258 alt_mem = EXACT_MATCH_2_ENTRY_ONLYm; 259 } 260 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 261 block = SOC_BLOCK2SCH(unit, block_info_index); 262 /* Write lower half of data only entry */ 263 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 264 block_info_index, index, &acc_type); 265 soc_meminfo_field_get(mem, &exact_match_minfo, entry, _ENTRY0f, 266 tmp_entry, SOC_MAX_MEM_WORDS); 267 soc_internal_extended_write_mem(pcid_info, block, acc_type, alt_addr, 268 tmp_entry); 269 /* Write upper half of data only entry */ 270 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 271 block_info_index, index + 1, &acc_type); 272 soc_meminfo_field_get(mem, &exact_match_minfo, entry, _ENTRY1f, 273 tmp_entry, SOC_MAX_MEM_WORDS); 274 soc_internal_extended_write_mem(pcid_info, block, acc_type, alt_addr, 275 tmp_entry); 276 277 /* Write hit bit portion of content */ 278 alt_mem = EXACT_MATCH_HIT_ONLYm; 279 sal_memset(tmp_entry, 0, 280 soc_mem_entry_words(unit, alt_mem) * sizeof(uint32)); 281 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 282 block = SOC_BLOCK2SCH(unit, block_info_index); 283 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 284 block_info_index, bucket, &acc_type); 285 fval = soc_mem_field32_get(unit, mem, entry, HIT_0f); 286 soc_mem_field32_set(unit, alt_mem, tmp_entry, HIT_0f, fval); 287 fval = soc_mem_field32_get(unit, mem, entry, HIT_1f); 288 soc_mem_field32_set(unit, alt_mem, tmp_entry, HIT_1f, fval); 289 soc_internal_extended_write_mem(pcid_info, block, acc_type, alt_addr, 290 tmp_entry); 291 break; 292 293 case EXACT_MATCH_2m: 294 /* Uses one slot per entry */ 295 index = offset; 296 bucket = index / bucket_size; 297 bit = index % bucket_size; 298 299 /* Write data only portion of content */ 300 #ifdef BCM_TOMAHAWK3_SUPPORT 301 if (SOC_IS_TOMAHAWK3(unit)) { 302 alt_mem = EXACT_MATCH_2m; 303 } else 304 #endif 305 { 306 alt_mem = EXACT_MATCH_2_ENTRY_ONLYm; 307 } 308 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 309 block = SOC_BLOCK2SCH(unit, block_info_index); 310 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 311 block_info_index, index, &acc_type); 312 soc_meminfo_field_get(mem, &exact_match_minfo, entry, _ENTRY0f, 313 tmp_entry, SOC_MAX_MEM_WORDS); 314 soc_internal_extended_write_mem(pcid_info, block, acc_type, alt_addr, 315 tmp_entry); 316 317 /* Write hit bit portion of content */ 318 alt_mem = EXACT_MATCH_HIT_ONLYm; 319 sal_memset(tmp_entry, 0, 320 soc_mem_entry_words(unit, alt_mem) * sizeof(uint32)); 321 block_info_index = SOC_MEM_BLOCK_ANY(unit, alt_mem); 322 block = SOC_BLOCK2SCH(unit, block_info_index); 323 alt_addr = soc_mem_addr_get(pcid_info->unit, alt_mem, 0, 324 block_info_index, bucket, &acc_type); 325 soc_internal_extended_read_mem(pcid_info, block, acc_type, alt_addr, 326 tmp_entry); 327 fval = soc_mem_field32_get(unit, mem, entry, HIT_0f); 328 soc_mem_field32_set(unit, alt_mem, tmp_entry, hit_fields[bit], fval); 329 soc_internal_extended_write_mem(pcid_info, block, acc_type, alt_addr, 330 tmp_entry); 331 break; 332 333 default: 334 return -1; 335 } 336 337 return 0; 338 } 339 340 STATIC int 341 soc_internal_exact_match_size_get(pcid_info_t *pcid_info, void *entry, 342 soc_mem_t *mem, int *num_vbits) 343 { 344 int unit = pcid_info->unit; 345 int key_type; 346 #ifdef BCM_TOMAHAWK3_SUPPORT 347 if(SOC_IS_TOMAHAWK3(unit)) { 348 key_type = soc_mem_field32_get(unit, EXACT_MATCH_2m, entry, KEY_TYPEf); 349 } 350 else 351 #endif 352 { 353 key_type = soc_mem_field32_get(unit, EXACT_MATCH_2m, entry, KEY_TYPE_0f); 354 } 355 switch (key_type) { 356 case TH_FPEM_HASH_KEY_TYPE_128B: 357 case TH_FPEM_HASH_KEY_TYPE_160B: 358 *num_vbits = 1; 359 *mem = EXACT_MATCH_2m; 360 break; 361 case TH_FPEM_HASH_KEY_TYPE_320B: 362 *num_vbits = 2; 363 *mem = EXACT_MATCH_4m; 364 break; 365 default: 366 return -1; 367 } 368 369 return 0; 370 } 371 372 STATIC int 373 soc_internal_exact_match_bucket_get(pcid_info_t *pcid_info, int bank, 374 void *entry) 375 { 376 int bucket; 377 int unit = pcid_info->unit; 378 int block; 379 uint8 acc_type; 380 uint32 addr; 381 int hash_offset, use_lsb, index; 382 #ifdef BCM_TOMAHAWK3_SUPPORT 383 int block_info_index; 384 uint32 tmp[SOC_MAX_MEM_WORDS]; 385 #endif 386 soc_reg_t reg; 387 uint32 rval[2]; 388 uint32 (*entry_hash_proc)(int unit, int bank, int hash_offset, 389 int use_lsb, uint32 *entry); 390 #ifdef BCM_TOMAHAWK3_SUPPORT 391 if(SOC_IS_TOMAHAWK3(unit)) { 392 static const soc_field_t fields[] = { 393 B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, 394 B3_HASH_OFFSETf 395 }; 396 static const soc_field_t fpem_fields[] = { 397 LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf, 398 LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf, 399 LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf, 400 LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf 401 }; 402 403 block_info_index = SOC_MEM_BLOCK_ANY(unit, EXACT_MATCH_HASH_CONTROLm); 404 block = SOC_BLOCK2SCH(unit, block_info_index); 405 406 entry_hash_proc = soc_tomahawk3_exact_match_entry_hash; 407 addr = soc_mem_addr_get(unit, EXACT_MATCH_HASH_CONTROLm, 0, 408 block_info_index, 0, &acc_type); 409 soc_internal_extended_read_mem(pcid_info, block, acc_type, 410 addr, tmp); 411 index = soc_mem_field32_get( 412 unit, EXACT_MATCH_HASH_CONTROLm, tmp, 413 fpem_fields[bank]); 414 415 use_lsb = 0; 416 block_info_index = SOC_MEM_BLOCK_ANY(unit, UFT_SHARED_BANKS_CONTROLm); 417 block = SOC_BLOCK2SCH(unit, block_info_index); 418 addr = soc_mem_addr_get(unit, UFT_SHARED_BANKS_CONTROLm, 0, 419 block_info_index, 0, &acc_type); 420 soc_internal_extended_read_mem(pcid_info, block, acc_type, 421 addr, tmp); 422 hash_offset = soc_mem_field32_get( 423 unit, UFT_SHARED_BANKS_CONTROLm, tmp, 424 fields[index]); 425 bucket = entry_hash_proc(unit, bank, hash_offset, use_lsb, entry); 426 427 } 428 else 429 #endif 430 { 431 static const soc_field_t fields[] = { 432 BANK2_HASH_OFFSETf, BANK3_HASH_OFFSETf, BANK4_HASH_OFFSETf, 433 BANK5_HASH_OFFSETf 434 }; 435 static const soc_field_t fpem_fields[] = { 436 FPEM_ENTRY_BANK_0f, FPEM_ENTRY_BANK_1f, FPEM_ENTRY_BANK_2f, 437 FPEM_ENTRY_BANK_3f 438 }; 439 440 entry_hash_proc = soc_th_exact_match_entry_hash; 441 addr = soc_reg_addr_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, 442 SOC_REG_ADDR_OPTION_NONE, &block, &acc_type); 443 /* 444 * COVERITY 445 * 446 * the below coverity error (overrun-buffer-val) is marked as false because we know that 447 * the size of ISS_LOG_TO_PHY_BANK_MAPr (<=64 bits) means that the overrun will never be exercised 448 * in the code below (the macros called in soc_internal_extended_read_reg() are aware of the size of 449 * ISS_LOG_TO_PHY_BANK_MAPr and how much data it can access in rval). 450 */ 451 /* coverity[overrun-buffer-val : FALSE] */ 452 soc_internal_extended_read_reg(pcid_info, block, acc_type, addr, rval); 453 index = soc_reg_field_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, rval[0], 454 fpem_fields[bank]); 455 456 use_lsb = 0; 457 reg = SHARED_TABLE_HASH_CONTROLr; 458 addr = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0, 459 SOC_REG_ADDR_OPTION_NONE, &block, &acc_type); 460 /* 461 * COVERITY 462 * 463 * the below coverity error (overrun-buffer-val) is marked as false because we know that 464 * the size of SHARED_TABLE_HASH_CONTROLr (<=64 bits) means that the overrun will never be exercised 465 * in the code below (the macros called in soc_internal_extended_read_reg() are aware of the size of 466 * SHARED_TABLE_HASH_CONTROLr and how much data it can access in rval). 467 */ 468 /* coverity[overrun-buffer-val : FALSE] */ 469 soc_internal_extended_read_reg(pcid_info, block, acc_type, addr, rval); 470 hash_offset = soc_reg_field_get(unit, reg, rval[0], fields[index]); 471 bucket = entry_hash_proc(unit, bank, hash_offset, use_lsb, entry); 472 473 LOG_VERBOSE(BSL_LS_SOC_COMMON, 474 (BSL_META_U(unit, 475 "bank %d bucket %d\n"), bank, bucket)); 476 } 477 return bucket; 478 } 479 480 STATIC void 481 soc_internal_exact_match_bank_map_get(pcid_info_t *pcid_info, 482 uint32 *bank_map, int *bank_start, 483 int *bank_inc, int *do_first_fit) 484 { 485 uint32 rval[2]; 486 int unit = pcid_info->unit; 487 int block; 488 uint8 acc_type; 489 uint32 addr; 490 491 uint32 shared_bank_map; 492 int bit_count; 493 #ifdef BCM_TOMAHAWK3_SUPPORT 494 if(SOC_IS_TOMAHAWK3(unit)) { 495 uint32 tmp[SOC_MAX_MEM_WORDS]; 496 int block_info_index; 497 498 block_info_index = SOC_MEM_BLOCK_ANY(unit, EXACT_MATCH_HASH_CONTROLm); 499 block = SOC_BLOCK2SCH(unit, block_info_index); 500 501 addr = soc_mem_addr_get(unit, EXACT_MATCH_HASH_CONTROLm, 0, 502 block_info_index, 0, &acc_type); 503 soc_internal_extended_read_mem(pcid_info, block, acc_type, 504 addr, tmp); 505 /* hardcode shared_bank_map because the value is 0 in pcid */ 506 /*shared_bank_map = soc_mem_field32_get( 507 unit, EXACT_MATCH_HASH_CONTROLm, tmp, 508 HASH_TABLE_BANK_CONFIGf);*/ 509 /* calculate number of 1's in shared_bank_map */ 510 shared_bank_map = 0xf; 511 bit_count = shared_bank_map - ((shared_bank_map >> 1) & 0x5); 512 bit_count = ((bit_count & 0xc) >> 2) + (bit_count & 0x3); 513 514 *bank_map = (1 << bit_count) - 1; 515 *bank_start = 0; 516 *bank_inc = 1; 517 if (do_first_fit != NULL) { 518 *do_first_fit = FALSE; 519 } 520 } 521 else 522 #endif 523 { 524 addr = soc_reg_addr_get(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, 525 SOC_REG_ADDR_OPTION_NONE, &block, 526 &acc_type); 527 soc_internal_extended_read_reg(pcid_info, block, acc_type, addr, rval); 528 shared_bank_map = soc_reg_field_get(unit, ISS_BANK_CONFIGr, rval[0], 529 FPEM_ENTRY_BANK_CONFIGf); 530 /* calculate number of 1's in shared_bank_map */ 531 bit_count = shared_bank_map - ((shared_bank_map >> 1) & 0x5); 532 bit_count = ((bit_count & 0xc) >> 2) + (bit_count & 0x3); 533 534 *bank_map = (1 << bit_count) - 1; 535 *bank_start = 0; 536 *bank_inc = 1; 537 if (do_first_fit != NULL) { 538 *do_first_fit = FALSE; 539 } 540 } 541 } 542 543 STATIC void 544 soc_internal_exact_match_bank_size_get(pcid_info_t *pcid_info, int bank, 545 int *entries_per_bank, 546 int *entries_per_row, 547 int *entries_per_bucket, 548 int *bank_base, int *bucket_offset) 549 { 550 /* 551 * entry index = 552 * bank_base + bucket * entries_per_row + bucket_offset + slot; 553 */ 554 #ifdef BCM_TOMAHAWK3_SUPPORT 555 if(SOC_IS_TOMAHAWK3(pcid_info->unit)) { 556 /* hardcode because hash_bank_info_get will call soc_mem_read, which 557 * cannot be done from pcid. Assume passing bank = 0 */ 558 if(entries_per_bank != NULL) { 559 *entries_per_bank = 16384; 560 } 561 if(entries_per_row != NULL) { 562 *entries_per_row = 2; 563 } 564 if(entries_per_bucket != NULL) { 565 *entries_per_bucket = 2; 566 } 567 if(bank_base != NULL) { 568 *bank_base = bank * 16384; 569 } 570 if(bucket_offset != NULL) { 571 *bucket_offset = 0; 572 } 573 574 /* soc_tomahawk3_hash_bank_info_get(pcid_info->unit, EXACT_MATCH_2m, 575 bank, entries_per_bank, 576 entries_per_row, 577 entries_per_bucket, 578 bank_base, bucket_offset); 579 */ 580 } 581 else 582 #endif 583 { 584 soc_tomahawk_hash_bank_info_get(pcid_info->unit, EXACT_MATCH_2m, 585 bank, entries_per_bank, 586 entries_per_row, 587 entries_per_bucket, 588 bank_base, bucket_offset); 589 } 590 } 591 592 int 593 soc_internal_exact_match_ins(pcid_info_t *pcid_info, uint32 inv_bank_map, 594 void *entry, uint32 *result) 595 { 596 uint32 tmp[SOC_MAX_MEM_WORDS]; 597 uint32 ent[SOC_MAX_MEM_WORDS]; 598 int rv; 599 uint32 bank_map; 600 int bank, entries_per_bank, bank_start, bank_inc, free_bank; 601 int bucket, entries_per_row, bank_base, free_bucket; 602 int slot, entries_per_bucket, bucket_offset, free_slot; 603 int sub_slot; 604 int index, free_index; 605 int first_free_slot, free_slot_count, do_first_fit; 606 int best_free_slot_count, best_entries_per_bank; 607 int num_vbits = 0; 608 int validslot_cnt; 609 soc_mem_t mem; 610 int sub_fields[] = { _ENTRY0f, _ENTRY1f }; 611 int unit = pcid_info->unit; 612 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result; 613 int block_info_index; 614 soc_block_t block; 615 uint8 acc_type; 616 uint32 addr; 617 618 LOG_VERBOSE(BSL_LS_SOC_COMMON, 619 (BSL_META_U(unit, "EXACT_MATCH Insert\n"))); 620 621 rv = soc_internal_exact_match_size_get(pcid_info, entry, &mem, 622 &num_vbits); 623 if ((rv < 0) || (num_vbits == 0)) { 624 return rv; 625 } 626 627 sal_memset(ent, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 628 sal_memset(tmp, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 629 630 block_info_index = SOC_MEM_BLOCK_ANY(unit, EXACT_MATCH_2m); 631 block = SOC_BLOCK2SCH(unit, block_info_index); 632 633 free_index = -1; 634 635 soc_internal_exact_match_bank_map_get(pcid_info, &bank_map, &bank_start, 636 &bank_inc, &do_first_fit); 637 bank_map &= ~inv_bank_map; 638 639 best_free_slot_count = 0; 640 for (bank = bank_start; bank_map != 0; bank += bank_inc) { 641 if (!(bank_map & (1 << bank))) { 642 continue; 643 } 644 bank_map &= ~(1 << bank); 645 646 soc_internal_exact_match_bank_size_get(pcid_info, bank, 647 &entries_per_bank, 648 &entries_per_row, 649 &entries_per_bucket, 650 &bank_base, &bucket_offset); 651 652 bucket = soc_internal_exact_match_bucket_get(pcid_info, bank, entry); 653 654 free_slot_count = 0; 655 first_free_slot = -1; 656 for (slot = 0; slot < entries_per_bucket; slot += num_vbits) { 657 validslot_cnt = 0; 658 for (sub_slot = 0; sub_slot < num_vbits; sub_slot++) { 659 index = bank_base + bucket * entries_per_row + bucket_offset + 660 slot + sub_slot; 661 #ifdef BCM_TOMAHAWK3_SUPPORT 662 if (SOC_IS_TOMAHAWK3(unit)) { 663 addr = soc_mem_addr_get(unit, EXACT_MATCH_2m, 0, 664 block_info_index, index, &acc_type); 665 soc_internal_extended_read_mem(pcid_info, block, acc_type, 666 addr, tmp); 667 if (soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 668 BASE_VALID_0f) && 669 soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 670 BASE_VALID_1f)) { 671 soc_meminfo_field_set(mem, &exact_match_minfo, ent, 672 sub_fields[sub_slot], tmp); 673 validslot_cnt++; 674 } 675 676 } 677 else 678 #endif 679 { 680 addr = soc_mem_addr_get(unit, EXACT_MATCH_2m, 0, 681 block_info_index, index, &acc_type); 682 soc_internal_extended_read_mem(pcid_info, block, acc_type, 683 addr, tmp); 684 if (soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 685 VALID_0f) && 686 soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 687 VALID_1f)) { 688 soc_meminfo_field_set(mem, &exact_match_minfo, ent, 689 sub_fields[sub_slot], tmp); 690 validslot_cnt++; 691 } 692 } 693 } 694 695 if (validslot_cnt == num_vbits) { 696 if (_soc_mem_cmp_exact_match(unit, entry, ent) == 0) { 697 index /= num_vbits; 698 addr = soc_mem_addr_get(unit, mem, 0, block_info_index, 699 index, &acc_type); 700 701 LOG_VERBOSE(BSL_LS_SOC_COMMON, 702 (BSL_META_U(unit, 703 "write block %d acc_type %d bank %d " 704 "bucket %d, slot %d, index %d\n"), 705 block, acc_type, bank, bucket, slot, index)); 706 707 /* Overwrite the existing entry */ 708 soc_internal_extended_write_mem(pcid_info, block, 709 acc_type, addr, entry); 710 711 /* Copy old entry immediately after response word */ 712 memcpy(&result[1], ent, soc_mem_entry_bytes(unit, mem)); 713 result[0] = 0; 714 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 715 genresp_v2->index = index; 716 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 717 718 return 0; 719 } 720 } else if (validslot_cnt == 0) { 721 free_slot_count++; 722 if (first_free_slot == -1) { 723 first_free_slot = slot; 724 } 725 } 726 } 727 if (free_slot_count > 0) { 728 if (do_first_fit) { 729 if (free_index != -1) { 730 continue; 731 } 732 } else { 733 if (free_slot_count < best_free_slot_count) { 734 continue; 735 } else if (free_slot_count == best_free_slot_count) { 736 if (entries_per_bank < best_entries_per_bank) { 737 continue; 738 } else if (entries_per_bank == best_entries_per_bank) { 739 if (free_index != -1 && bank > free_bank) { 740 continue; 741 } 742 } 743 } 744 best_free_slot_count = free_slot_count; 745 best_entries_per_bank = entries_per_bank; 746 } 747 free_index = (index + 1 - entries_per_bucket + first_free_slot) / 748 num_vbits; 749 free_bank = bank; 750 free_bucket = bucket; 751 free_slot = first_free_slot; 752 } 753 } 754 755 /* Find first unused slot in bucket */ 756 if (free_index != -1) { 757 index = free_index; 758 addr = soc_mem_addr_get(unit, mem, 0, block_info_index, index, 759 &acc_type); 760 761 LOG_VERBOSE(BSL_LS_SOC_COMMON, 762 (BSL_META_U(unit, 763 "write block %d acc_type %d bank %d bucket %d, " 764 "slot %d, index %d\n"), 765 block, acc_type, free_bank, free_bucket, free_slot, index)); 766 767 /* Write the entry */ 768 soc_internal_extended_write_mem(pcid_info, block, acc_type, addr, 769 entry); 770 771 result[0] = 0; 772 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 773 genresp_v2->index = index; 774 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 775 776 return 0; 777 } 778 779 LOG_VERBOSE(BSL_LS_SOC_COMMON, 780 (BSL_META_U(unit, 781 "Bucket full\n"))); 782 result[0] = 0; 783 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 784 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 785 786 return 0; 787 } 788 789 int 790 soc_internal_exact_match_del(pcid_info_t *pcid_info, uint32 inv_bank_map, 791 void *entry, uint32 *result) 792 { 793 uint32 tmp[SOC_MAX_MEM_WORDS]; 794 uint32 ent[SOC_MAX_MEM_WORDS]; 795 int rv; 796 uint32 bank_map; 797 int bank, bank_start, bank_inc; 798 int bucket, entries_per_row, bank_base; 799 int slot, entries_per_bucket, bucket_offset; 800 int sub_slot; 801 int index; 802 int num_vbits = 0; 803 int validslot_cnt; 804 soc_mem_t mem; 805 int sub_fields[] = { _ENTRY0f, _ENTRY1f }; 806 int unit = pcid_info->unit; 807 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result; 808 int block_info_index; 809 soc_block_t block; 810 uint8 acc_type; 811 uint32 addr; 812 813 LOG_VERBOSE(BSL_LS_SOC_COMMON, 814 (BSL_META_U(unit, 815 "EXACT_MATCH Delete\n"))); 816 817 rv = soc_internal_exact_match_size_get(pcid_info, entry, &mem, 818 &num_vbits); 819 if ((rv < 0) || (num_vbits == 0)) { 820 return rv; 821 } 822 823 sal_memset(ent, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 824 sal_memset(tmp, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 825 826 #ifdef BCM_TOMAHAWK3_SUPPORT 827 if (SOC_IS_TOMAHAWK3(unit)) { 828 block_info_index = SOC_MEM_BLOCK_ANY(unit, EXACT_MATCH_2m); 829 } 830 else 831 #endif 832 { 833 block_info_index = SOC_MEM_BLOCK_ANY(unit, EXACT_MATCH_2m); 834 } 835 block = SOC_BLOCK2SCH(unit, block_info_index); 836 837 soc_internal_exact_match_bank_map_get(pcid_info, &bank_map, &bank_start, 838 &bank_inc, NULL); 839 bank_map &= ~inv_bank_map; 840 841 for (bank = bank_start; bank_map != 0; bank += bank_inc) { 842 if (!(bank_map & (1 << bank))) { 843 continue; 844 } 845 bank_map &= ~(1 << bank); 846 847 soc_internal_exact_match_bank_size_get(pcid_info, bank, NULL, 848 &entries_per_row, 849 &entries_per_bucket, 850 &bank_base, &bucket_offset); 851 852 bucket = soc_internal_exact_match_bucket_get(pcid_info, bank, entry); 853 854 for (slot = 0; slot < entries_per_bucket; slot += num_vbits) { 855 validslot_cnt = 0; 856 for (sub_slot = 0; sub_slot < num_vbits; sub_slot++) { 857 index = bank_base + bucket * entries_per_row + bucket_offset + 858 slot + sub_slot; 859 #ifdef BCM_TOMAHAWK3_SUPPORT 860 if (SOC_IS_TOMAHAWK3(unit)) { 861 addr = soc_mem_addr_get(unit, EXACT_MATCH_2m, 0, 862 block_info_index, index, &acc_type); 863 soc_internal_extended_read_mem(pcid_info, block, acc_type, 864 addr, tmp); 865 if (soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 866 BASE_VALID_0f) && 867 soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 868 BASE_VALID_1f)) { 869 soc_meminfo_field_set(mem, &exact_match_minfo, ent, 870 sub_fields[sub_slot], tmp); 871 validslot_cnt++; 872 } else { 873 break; 874 } 875 } 876 else 877 #endif 878 { 879 addr = soc_mem_addr_get(unit, EXACT_MATCH_2m, 0, 880 block_info_index, index, &acc_type); 881 soc_internal_extended_read_mem(pcid_info, block, acc_type, 882 addr, tmp); 883 if (soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 884 VALID_0f) && 885 soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 886 VALID_1f)) { 887 soc_meminfo_field_set(mem, &exact_match_minfo, ent, 888 sub_fields[sub_slot], tmp); 889 validslot_cnt++; 890 } else { 891 break; 892 } 893 } 894 } 895 896 if (validslot_cnt == num_vbits) { 897 if (_soc_mem_cmp_exact_match(unit, entry, ent) == 0) { 898 index /= num_vbits; 899 addr = soc_mem_addr_get(unit, mem, 0, block_info_index, 900 index, &acc_type); 901 902 LOG_VERBOSE(BSL_LS_SOC_COMMON, 903 (BSL_META_U(unit, 904 "delete block %d acc_type %d bank %d " 905 "bucket %d, slot %d, index %d\n"), 906 block, acc_type, bank, bucket, slot, index)); 907 908 /* Copy entry immediately after response word */ 909 memcpy(&result[1], ent, soc_mem_entry_bytes(unit, mem)); 910 911 /* Invalidate entry */ 912 memset(tmp, 0, sizeof(tmp)); 913 soc_internal_extended_write_mem(pcid_info, block, 914 acc_type, addr, 915 (uint32 *)tmp); 916 917 result[0] = 0; 918 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 919 genresp_v2->index = index; 920 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 921 922 return 0; 923 } 924 } 925 } 926 } 927 928 LOG_VERBOSE(BSL_LS_SOC_COMMON, 929 (BSL_META_U(unit, 930 "soc_internal_exact_match_del: Not found\n"))); 931 932 result[0] = 0; 933 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 934 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 935 936 return 0; 937 } 938 int 939 soc_internal_exact_match_lkup(pcid_info_t * pcid_info, uint32 inv_bank_map, 940 void *entry, uint32 *result) 941 { 942 uint32 tmp[SOC_MAX_MEM_WORDS]; 943 uint32 ent[SOC_MAX_MEM_WORDS]; 944 int rv; 945 uint32 bank_map; 946 int bank, bank_start, bank_inc; 947 int bucket, entries_per_row, bank_base; 948 int slot, entries_per_bucket, bucket_offset; 949 int sub_slot; 950 int index; 951 int num_vbits = 0; 952 int validslot_cnt; 953 soc_mem_t mem; 954 int sub_fields[] = { _ENTRY0f, _ENTRY1f }; 955 int unit = pcid_info->unit; 956 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result; 957 int block_info_index; 958 soc_block_t block; 959 uint8 acc_type; 960 uint32 addr; 961 962 LOG_VERBOSE(BSL_LS_SOC_COMMON, 963 (BSL_META_U(unit, 964 "EXACT_MATCH Lookup\n"))); 965 966 rv = soc_internal_exact_match_size_get(pcid_info, entry, &mem, 967 &num_vbits); 968 if ((rv < 0) || (num_vbits == 0)) { 969 return rv; 970 } 971 972 sal_memset(ent, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 973 sal_memset(tmp, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 974 975 #ifdef BCM_TOMAHAWK3_SUPPORT 976 if (SOC_IS_TOMAHAWK3(unit)) { 977 block_info_index = SOC_MEM_BLOCK_ANY(unit, EXACT_MATCH_2m); 978 } 979 else 980 #endif 981 { 982 block_info_index = SOC_MEM_BLOCK_ANY(unit, EXACT_MATCH_2m); 983 } 984 block = SOC_BLOCK2SCH(unit, block_info_index); 985 986 soc_internal_exact_match_bank_map_get(pcid_info, &bank_map, &bank_start, 987 &bank_inc, NULL); 988 bank_map &= ~inv_bank_map; 989 990 for (bank = bank_start; bank_map != 0; bank += bank_inc) { 991 if (!(bank_map & (1 << bank))) { 992 continue; 993 } 994 bank_map &= ~(1 << bank); 995 996 soc_internal_exact_match_bank_size_get(pcid_info, bank, NULL, 997 &entries_per_row, 998 &entries_per_bucket, 999 &bank_base, &bucket_offset); 1000 1001 bucket = soc_internal_exact_match_bucket_get(pcid_info, bank, entry); 1002 1003 for (slot = 0; slot < entries_per_bucket; slot += num_vbits) { 1004 validslot_cnt = 0; 1005 for (sub_slot = 0; sub_slot < num_vbits; sub_slot++) { 1006 index = bank_base + bucket * entries_per_row + bucket_offset + 1007 slot + sub_slot; 1008 #ifdef BCM_TOMAHAWK3_SUPPORT 1009 if (SOC_IS_TOMAHAWK3(unit)) { 1010 addr = soc_mem_addr_get(unit, EXACT_MATCH_2m, 0, 1011 block_info_index, index, &acc_type); 1012 soc_internal_extended_read_mem(pcid_info, block, acc_type, 1013 addr, tmp); 1014 if (soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 1015 BASE_VALID_0f) && 1016 soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 1017 BASE_VALID_1f)) { 1018 soc_meminfo_field_set(mem, &exact_match_minfo, ent, 1019 sub_fields[sub_slot], tmp); 1020 validslot_cnt++; 1021 } else { 1022 break; 1023 } 1024 } 1025 else 1026 #endif 1027 { 1028 addr = soc_mem_addr_get(unit, EXACT_MATCH_2m, 0, 1029 block_info_index, index, &acc_type); 1030 soc_internal_extended_read_mem(pcid_info, block, acc_type, 1031 addr, tmp); 1032 if (soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 1033 VALID_0f) && 1034 soc_mem_field32_get(unit, EXACT_MATCH_2m, tmp, 1035 VALID_1f)) { 1036 soc_meminfo_field_set(mem, &exact_match_minfo, ent, 1037 sub_fields[sub_slot], tmp); 1038 validslot_cnt++; 1039 } else { 1040 break; 1041 } 1042 } 1043 } 1044 1045 if (validslot_cnt == num_vbits) { 1046 if (_soc_mem_cmp_exact_match(unit, entry, ent) == 0) { 1047 index /= num_vbits; 1048 addr = soc_mem_addr_get(unit, mem, 0, block_info_index, 1049 index, &acc_type); 1050 1051 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1052 (BSL_META_U(unit, 1053 "found block %d acc_type %d bank %d " 1054 "bucket %d, slot %d, index %d\n"), 1055 block, acc_type, bank, bucket, slot, index)); 1056 1057 /* Copy entry immediately after response word */ 1058 memcpy(&result[1], ent, soc_mem_entry_bytes(unit, mem)); 1059 1060 result[0] = 0; 1061 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 1062 genresp_v2->index = index; 1063 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1064 1065 return 0; 1066 } 1067 } 1068 } 1069 } 1070 1071 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1072 (BSL_META_U(unit, 1073 "soc_internal_exact_match_lkup: Not found\n"))); 1074 1075 result[0] = 0; 1076 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1077 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1078 1079 return 0; 1080 } 1081 #endif /* BCM_TOMAHAWK_SUPPORT */