vlan.c (91808B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: vlan.c 8 * 9 * Provides: 10 * soc_internal_vlan_xlate_hash 11 * soc_internal_vlan_xlate_dual_banks 12 * soc_internal_vlan_xlate_entry_read 13 * soc_internal_vlan_xlate_entry_write 14 * soc_internal_vlan_xlate_entry_ins 15 * soc_internal_vlan_xlate_entry_del 16 * soc_internal_vlan_xlate_entry_lkup 17 * soc_internal_egr_vlan_xlate_hash 18 * soc_internal_egr_vlan_xlate_dual_banks 19 * soc_internal_egr_vlan_xlate_entry_read 20 * soc_internal_egr_vlan_xlate_entry_write 21 * soc_internal_egr_vlan_xlate_entry_ins 22 * soc_internal_egr_vlan_xlate_entry_del 23 * soc_internal_egr_vlan_xlate_entry_lkup 24 * 25 * Requires: 26 */ 27 28 #include <shared/bsl.h> 29 30 #include <soc/mem.h> 31 #include <soc/hash.h> 32 #include <soc/drv.h> 33 #include <soc/l2x.h> 34 #ifdef BCM_TRIDENT2_SUPPORT 35 #include <soc/trident2.h> 36 #endif 37 38 #include "pcid.h" 39 #include "mem.h" 40 #include "cmicsim.h" 41 42 #ifdef BCM_TRX_SUPPORT 43 44 int 45 soc_internal_vlan_xlate_hash(pcid_info_t * pcid_info, 46 vlan_xlate_entry_t *entry, int dual) 47 { 48 uint32 tmp_hs[SOC_MAX_MEM_WORDS]; 49 int hash_sel; 50 uint8 at, key[8]; 51 int index, bits; 52 soc_block_t blk; 53 54 LOG_VERBOSE(BSL_LS_SOC_COMMON, 55 (BSL_META("VLAN_XLATE hash\n"))); 56 57 soc_internal_extended_read_reg(pcid_info, blk, at, 58 soc_reg_addr_get(pcid_info->unit, VLAN_XLATE_HASH_CONTROLr, 59 REG_PORT_ANY, 0, SOC_REG_ADDR_OPTION_NONE, 60 &blk, &at), 61 tmp_hs); 62 if (dual) { 63 hash_sel = soc_reg_field_get(pcid_info->unit, VLAN_XLATE_HASH_CONTROLr, 64 tmp_hs[0], HASH_SELECT_Bf); 65 } else { 66 hash_sel = soc_reg_field_get(pcid_info->unit, VLAN_XLATE_HASH_CONTROLr, 67 tmp_hs[0], HASH_SELECT_Af); 68 } 69 70 LOG_VERBOSE(BSL_LS_SOC_COMMON, 71 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 72 73 #ifdef BCM_TRIDENT2_SUPPORT 74 if (SOC_IS_TD2_TT2(pcid_info->unit)) { 75 bits = soc_td2_vlan_xlate_base_entry_to_key(pcid_info->unit, dual, entry, 76 key); 77 index = soc_td2_vlan_xlate_hash(pcid_info->unit, hash_sel, bits, entry, 78 key); 79 } else 80 #endif /* BCM_TRIDENT2_SUPPORT */ 81 { 82 bits = soc_tr_vlan_xlate_base_entry_to_key(pcid_info->unit, entry, 83 key); 84 index = soc_tr_vlan_xlate_hash(pcid_info->unit, hash_sel, bits, entry, 85 key); 86 } 87 88 LOG_VERBOSE(BSL_LS_SOC_COMMON, 89 (BSL_META("index %d\n"), index)); 90 91 return index; 92 } 93 94 void 95 soc_internal_vlan_xlate_dual_banks(pcid_info_t *pcid_info, uint8 banks, 96 int *dual, int *slot_min, int *slot_max) 97 { 98 /* Dual hash always enabled for VLAN_XLATE */ 99 *dual = TRUE; 100 101 if (*dual) { 102 switch (banks) { 103 case 0: 104 return; /* Nothing to do here */ 105 case 1: 106 *slot_min = 4; 107 *slot_max = 7; 108 break; 109 case 2: 110 *slot_min = 0; 111 *slot_max = 3; 112 break; 113 default: 114 *slot_min = 0; 115 *slot_max = -1; 116 break; 117 } 118 } 119 120 return; 121 } 122 123 int 124 soc_internal_vlan_xlate_entry_read(pcid_info_t * pcid_info, uint32 addr, 125 vlan_xlate_entry_t *entry) 126 { 127 int index = (addr & 0x3fff); 128 int blk; 129 soc_block_t sblk; 130 uint8 at; 131 uint32 address; 132 133 blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, VLAN_XLATEm); 134 sblk = SOC_BLOCK2SCH(pcid_info->unit, blk); 135 136 address = soc_mem_addr_get(pcid_info->unit, VLAN_XLATEm, 0, 137 blk, index, &at); 138 139 LOG_VERBOSE(BSL_LS_SOC_COMMON, 140 (BSL_META("vlan_xlate read addr=0x%x\n"), addr)); 141 142 soc_internal_extended_read_mem(pcid_info, sblk, 0, address, 143 (uint32 *) entry); 144 145 return 0; 146 } 147 148 int 149 soc_internal_vlan_xlate_entry_write(pcid_info_t * pcid_info, uint32 addr, 150 vlan_xlate_entry_t *entry) 151 { 152 int index = (addr & 0x3fff); 153 int blk; 154 soc_block_t sblk; 155 uint8 at; 156 uint32 address; 157 158 blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, VLAN_XLATEm); 159 sblk = SOC_BLOCK2SCH(pcid_info->unit, blk); 160 address = soc_mem_addr_get(pcid_info->unit, VLAN_XLATEm, 0, 161 blk, index, &at); 162 163 LOG_VERBOSE(BSL_LS_SOC_COMMON, 164 (BSL_META("vlan_xlate write addr=0x%x\n"), addr)); 165 166 soc_internal_extended_write_mem(pcid_info, sblk, 0, address, 167 (uint32 *) entry); 168 169 return 0; 170 } 171 172 int 173 soc_internal_vlan_xlate_entry_ins(pcid_info_t *pcid_info, uint8 banks, 174 vlan_xlate_entry_t *entry, uint32 *result) 175 { 176 uint32 tmp[SOC_MAX_MEM_WORDS]; 177 int index = 0, bucket, slot, free_index; 178 int slot_min = 0, slot_max = 7, dual = FALSE; 179 int unit = pcid_info->unit; 180 schan_genresp_t *genresp = (schan_genresp_t *)result; 181 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 182 int blk; 183 soc_block_t sblk; 184 uint8 acc_type; 185 uint32 addr; 186 187 LOG_VERBOSE(BSL_LS_SOC_COMMON, 188 (BSL_META_U(unit, 189 "VLAN_XLAEGT Insert\n"))); 190 191 bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, FALSE); 192 193 LOG_VERBOSE(BSL_LS_SOC_COMMON, 194 (BSL_META_U(unit, 195 "bucket %d\n"), bucket)); 196 197 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 198 soc_internal_vlan_xlate_dual_banks(pcid_info, banks, &dual, &slot_min, 199 &slot_max); 200 } 201 blk = SOC_MEM_BLOCK_ANY(unit, VLAN_XLATEm); 202 sblk = SOC_BLOCK2SCH(unit, blk); 203 204 /* Check if it should overwrite an existing entry */ 205 free_index = -1; 206 for (slot = slot_min; slot <= slot_max; slot++) { 207 if (dual && (slot == 4)) { 208 bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, TRUE); 209 } 210 index = bucket * 8 + slot; 211 addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type); 212 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 213 if (soc_mem_field32_get(unit, VLAN_XLATEm, tmp, VALIDf)) { 214 if (soc_mem_compare_key(unit, VLAN_XLATEm, entry, tmp) == 0) { 215 LOG_VERBOSE(BSL_LS_SOC_COMMON, 216 (BSL_META_U(unit, 217 "write sblk %d acc_type %d bucket %d, " 218 "slot %d, index %d\n"), 219 sblk, acc_type, index / 8, index % 8, index)); 220 221 /* Overwrite the existing entry */ 222 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 223 addr, (uint32 *)entry); 224 225 /* Copy old entry immediately after response word */ 226 memcpy(&result[1], tmp, 227 soc_mem_entry_bytes(unit, VLAN_XLATEm)); 228 229 result[0] = 0; 230 if (soc_feature(unit, soc_feature_new_sbus_format) && 231 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 232 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 233 genresp_v2->index = index; 234 } else { 235 genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED; 236 genresp->index = index; 237 } 238 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 239 240 return 0; 241 } 242 } else { 243 if (free_index == -1) { 244 free_index = index; 245 } 246 } 247 } 248 249 /* Find first unused slot in bucket */ 250 if (free_index != -1) { 251 index = free_index; 252 addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type); 253 254 LOG_VERBOSE(BSL_LS_SOC_COMMON, 255 (BSL_META_U(unit, 256 "write sblk %d acc_type %d bucket %d, slot %d, " 257 "index %d\n"), 258 sblk, acc_type, index / 8, index % 8, index)); 259 260 /* Write the new entry */ 261 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 262 (uint32 *)entry); 263 264 result[0] = 0; 265 if (soc_feature(unit, soc_feature_new_sbus_format) && 266 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 267 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 268 genresp_v2->index = index; 269 } else { 270 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED; 271 genresp->index = index; 272 } 273 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 274 275 return 0; 276 } 277 278 LOG_VERBOSE(BSL_LS_SOC_COMMON, 279 (BSL_META_U(unit, 280 "Bucket full\n"))); 281 282 result[0] = 0; 283 if (soc_feature(unit, soc_feature_new_sbus_format) && 284 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 285 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 286 } else { 287 genresp->type = SCHAN_GEN_RESP_TYPE_FULL; 288 } 289 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 290 291 return 0; 292 } 293 294 int 295 soc_internal_vlan_xlate_entry_del(pcid_info_t * pcid_info, uint8 banks, 296 vlan_xlate_entry_t *entry, uint32 *result) 297 { 298 uint32 tmp[SOC_MAX_MEM_WORDS]; 299 int index = 0, bucket, slot; 300 int slot_min = 0, slot_max = 7, dual = FALSE; 301 int unit = pcid_info->unit; 302 schan_genresp_t *genresp = (schan_genresp_t *)result; 303 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 304 int blk; 305 soc_block_t sblk; 306 uint8 acc_type; 307 uint32 addr; 308 309 LOG_VERBOSE(BSL_LS_SOC_COMMON, 310 (BSL_META_U(unit, 311 "VLAN_XLATE Delete\n"))); 312 313 bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, FALSE); 314 315 LOG_VERBOSE(BSL_LS_SOC_COMMON, 316 (BSL_META_U(unit, 317 "bucket %d\n"), bucket)); 318 319 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 320 soc_internal_vlan_xlate_dual_banks(pcid_info, banks, &dual, 321 &slot_min, &slot_max); 322 } 323 blk = SOC_MEM_BLOCK_ANY(unit, VLAN_XLATEm); 324 sblk = SOC_BLOCK2SCH(unit, blk); 325 326 /* Check if entry exists */ 327 for (slot = slot_min; slot <= slot_max; slot++) { 328 if (dual && (slot == 4)) { 329 bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, TRUE); 330 } 331 index = bucket * 8 + slot; 332 addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type); 333 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 334 if (soc_mem_field32_get(unit, VLAN_XLATEm, tmp, VALIDf)) { 335 if (soc_mem_compare_key(unit, VLAN_XLATEm, entry, tmp) == 0) { 336 LOG_VERBOSE(BSL_LS_SOC_COMMON, 337 (BSL_META_U(unit, 338 "found sblk %d acc_type %d bucket %d, " 339 "slot %d, index %d\n"), 340 sblk, acc_type, bucket, slot, index)); 341 342 /* Copy entry immediately after response word */ 343 memcpy(&result[1], tmp, 344 soc_mem_entry_bytes(unit, VLAN_XLATEm)); 345 346 /* Invalidate entry */ 347 soc_mem_field32_set(unit, VLAN_XLATEm, tmp, VALIDf, 0); 348 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 349 addr, tmp); 350 351 result[0] = 0; 352 if (soc_feature(unit, soc_feature_new_sbus_format) && 353 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 354 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 355 genresp_v2->index = index; 356 } else { 357 genresp->type = SCHAN_GEN_RESP_TYPE_DELETED; 358 genresp->index = index; 359 } 360 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 361 362 return 0; 363 } 364 } 365 } 366 367 LOG_VERBOSE(BSL_LS_SOC_COMMON, 368 (BSL_META_U(unit, 369 "soc_internal_vlan_xlate_entry_del: Not found\n"))); 370 371 result[0] = 0; 372 if (soc_feature(unit, soc_feature_new_sbus_format) && 373 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 374 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 375 } else { 376 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 377 } 378 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 379 return 0; 380 } 381 382 int 383 soc_internal_vlan_xlate_entry_lkup(pcid_info_t * pcid_info, uint8 banks, 384 vlan_xlate_entry_t *entry, uint32 *result) 385 { 386 uint32 tmp[SOC_MAX_MEM_WORDS]; 387 int index = 0, bucket, slot; 388 int slot_min = 0, slot_max = 7, dual = FALSE; 389 int unit = pcid_info->unit; 390 schan_genresp_t *genresp = (schan_genresp_t *)result; 391 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 392 int blk; 393 soc_block_t sblk; 394 uint8 acc_type; 395 uint32 addr; 396 397 LOG_VERBOSE(BSL_LS_SOC_COMMON, 398 (BSL_META_U(unit, 399 "VLAN_XLATE Lookup\n"))); 400 401 bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, FALSE); 402 403 LOG_VERBOSE(BSL_LS_SOC_COMMON, 404 (BSL_META_U(unit, 405 "bucket %d\n"), bucket)); 406 407 if (soc_feature(unit, soc_feature_dual_hash)) { 408 soc_internal_vlan_xlate_dual_banks(pcid_info, banks, &dual, 409 &slot_min, &slot_max); 410 } 411 blk = SOC_MEM_BLOCK_ANY(unit, VLAN_XLATEm); 412 sblk = SOC_BLOCK2SCH(unit, blk); 413 414 /* Check if entry exists */ 415 for (slot = slot_min; slot <= slot_max; slot++) { 416 if (dual && (slot == 4)) { 417 bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, TRUE); 418 } 419 index = bucket * 8 + slot; 420 addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type); 421 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 422 if (soc_mem_field32_get(unit, VLAN_XLATEm, tmp, VALIDf)) { 423 if (soc_mem_compare_key(unit, VLAN_XLATEm, entry, tmp) == 0) { 424 LOG_VERBOSE(BSL_LS_SOC_COMMON, 425 (BSL_META_U(unit, 426 "found sblk %d acc_type %d bucket %d, " 427 "slot %d, index %d\n"), 428 sblk, acc_type, bucket, slot, index)); 429 430 /* Copy entry immediately after response word */ 431 memcpy(&result[1], tmp, 432 soc_mem_entry_bytes(unit, VLAN_XLATEm)); 433 434 result[0] = 0; 435 if (soc_feature(unit, soc_feature_new_sbus_format) && 436 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 437 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 438 genresp_v2->index = index; 439 } else { 440 genresp->type = SCHAN_GEN_RESP_TYPE_FOUND; 441 genresp->index = index; 442 } 443 444 return 0; 445 } 446 } 447 } 448 449 LOG_VERBOSE(BSL_LS_SOC_COMMON, 450 (BSL_META_U(unit, 451 "soc_internal_vlan_xlate_entry_lkup: Not found\n"))); 452 453 result[0] = 0; 454 if (soc_feature(unit, soc_feature_new_sbus_format) && 455 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 456 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 457 } else { 458 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 459 } 460 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 461 return 0; 462 } 463 464 int 465 soc_internal_egr_vlan_xlate_hash(pcid_info_t * pcid_info, 466 egr_vlan_xlate_entry_t *entry, int dual) 467 { 468 uint32 tmp_hs[SOC_MAX_MEM_WORDS]; 469 int hash_sel; 470 uint8 at, key[8]; 471 int index, bits; 472 soc_block_t blk; 473 474 LOG_VERBOSE(BSL_LS_SOC_COMMON, 475 (BSL_META("EGR_VLAN_XLATE hash\n"))); 476 477 soc_internal_extended_read_reg(pcid_info, blk, at, 478 soc_reg_addr_get(pcid_info->unit, EGR_VLAN_XLATE_HASH_CONTROLr, 479 REG_PORT_ANY, 0, SOC_REG_ADDR_OPTION_NONE, 480 &blk, &at), 481 tmp_hs); 482 if (dual) { 483 hash_sel = soc_reg_field_get(pcid_info->unit, EGR_VLAN_XLATE_HASH_CONTROLr, 484 tmp_hs[0], HASH_SELECT_Bf); 485 } else { 486 hash_sel = soc_reg_field_get(pcid_info->unit, EGR_VLAN_XLATE_HASH_CONTROLr, 487 tmp_hs[0], HASH_SELECT_Af); 488 } 489 490 LOG_VERBOSE(BSL_LS_SOC_COMMON, 491 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 492 493 #ifdef BCM_TRIDENT2_SUPPORT 494 if (SOC_IS_TD2_TT2(pcid_info->unit)) { 495 bits = soc_td2_egr_vlan_xlate_base_entry_to_key(pcid_info->unit, dual, 496 entry, key); 497 index = soc_td2_egr_vlan_xlate_hash(pcid_info->unit, hash_sel, bits, 498 entry, key); 499 } else 500 #endif /* BCM_TRIDENT2_SUPPORT */ 501 { 502 bits = soc_tr_egr_vlan_xlate_base_entry_to_key(pcid_info->unit, 503 entry, key); 504 index = soc_tr_egr_vlan_xlate_hash(pcid_info->unit, hash_sel, bits, 505 entry, key); 506 } 507 508 LOG_VERBOSE(BSL_LS_SOC_COMMON, 509 (BSL_META("index %d\n"), index)); 510 511 return index; 512 } 513 514 void 515 soc_internal_egr_vlan_xlate_dual_banks(pcid_info_t *pcid_info, uint8 banks, 516 int *dual, int *slot_min, int *slot_max) 517 { 518 /* Dual hash always enabled for EGR_VLAN_XLATE */ 519 *dual = TRUE; 520 521 if (*dual) { 522 switch (banks) { 523 case 0: 524 return; /* Nothing to do here */ 525 case 1: 526 *slot_min = 4; 527 *slot_max = 7; 528 break; 529 case 2: 530 *slot_min = 0; 531 *slot_max = 3; 532 break; 533 default: 534 *slot_min = 0; 535 *slot_max = -1; 536 break; 537 } 538 } 539 540 return; 541 } 542 543 int 544 soc_internal_egr_vlan_xlate_entry_ins(pcid_info_t *pcid_info, uint8 banks, 545 egr_vlan_xlate_entry_t *entry, 546 uint32 *result) 547 { 548 uint32 tmp[SOC_MAX_MEM_WORDS]; 549 int index = 0, bucket, slot, free_index; 550 int slot_min = 0, slot_max = 7, dual = FALSE; 551 int unit = pcid_info->unit; 552 schan_genresp_t *genresp = (schan_genresp_t *)result; 553 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 554 int blk; 555 soc_block_t sblk; 556 uint8 acc_type; 557 uint32 addr; 558 559 LOG_VERBOSE(BSL_LS_SOC_COMMON, 560 (BSL_META_U(unit, 561 "EGR_VLAN_XLATE Insert\n"))); 562 563 bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, FALSE); 564 565 LOG_VERBOSE(BSL_LS_SOC_COMMON, 566 (BSL_META_U(unit, 567 "bucket %d\n"), bucket)); 568 569 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 570 soc_internal_egr_vlan_xlate_dual_banks(pcid_info, banks, &dual, 571 &slot_min, &slot_max); 572 } 573 blk = SOC_MEM_BLOCK_ANY(unit, EGR_VLAN_XLATEm); 574 sblk = SOC_BLOCK2SCH(unit, blk); 575 576 /* Check if it should overwrite an existing entry */ 577 free_index = -1; 578 for (slot = slot_min; slot <= slot_max; slot++) { 579 if (dual && (slot == 4)) { 580 bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, TRUE); 581 } 582 index = bucket * 8 + slot; 583 addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index, 584 &acc_type); 585 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 586 if (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, tmp, VALIDf)) { 587 if (soc_mem_compare_key(unit, EGR_VLAN_XLATEm, entry, tmp) == 0) { 588 LOG_VERBOSE(BSL_LS_SOC_COMMON, 589 (BSL_META_U(unit, 590 "write sblk %d acc_type %d bucket %d, " 591 "slot %d, index %d\n"), 592 sblk, acc_type, index / 8, index % 8, index)); 593 594 /* Overwrite the existing entry */ 595 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 596 addr, (uint32 *)entry); 597 598 /* Copy old entry immediately after response word */ 599 memcpy(&result[1], tmp, 600 soc_mem_entry_bytes(unit, EGR_VLAN_XLATEm)); 601 602 result[0] = 0; 603 if (soc_feature(unit, soc_feature_new_sbus_format) && 604 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 605 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 606 genresp_v2->index = index; 607 } else { 608 genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED; 609 genresp->index = index; 610 } 611 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 612 613 return 0; 614 } 615 } else { 616 if (free_index == -1) { 617 free_index = index; 618 } 619 } 620 } 621 622 /* Find first unused slot in bucket */ 623 if (free_index != -1) { 624 index = free_index; 625 addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index, 626 &acc_type); 627 628 LOG_VERBOSE(BSL_LS_SOC_COMMON, 629 (BSL_META_U(unit, 630 "write sblk %d acc_type %d bucket %d, slot %d, " 631 "index %d\n"), 632 sblk, acc_type, index / 8, index % 8, index)); 633 634 /* Write the new entry */ 635 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 636 (uint32 *)entry); 637 638 result[0] = 0; 639 if (soc_feature(unit, soc_feature_new_sbus_format) && 640 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 641 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 642 genresp_v2->index = index; 643 } else { 644 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED; 645 genresp->index = index; 646 } 647 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 648 649 return 0; 650 } 651 652 LOG_VERBOSE(BSL_LS_SOC_COMMON, 653 (BSL_META_U(unit, 654 "Bucket full\n"))); 655 656 result[0] = 0; 657 if (soc_feature(unit, soc_feature_new_sbus_format) && 658 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 659 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 660 } else { 661 genresp->type = SCHAN_GEN_RESP_TYPE_FULL; 662 } 663 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 664 665 return 0; 666 } 667 668 int 669 soc_internal_egr_vlan_xlate_entry_del(pcid_info_t * pcid_info, uint8 banks, 670 egr_vlan_xlate_entry_t *entry, 671 uint32 *result) 672 { 673 uint32 tmp[SOC_MAX_MEM_WORDS]; 674 int index = 0, bucket, slot; 675 int slot_min = 0, slot_max = 7, dual = FALSE; 676 int unit = pcid_info->unit; 677 schan_genresp_t *genresp = (schan_genresp_t *)result; 678 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 679 int blk; 680 soc_block_t sblk; 681 uint8 acc_type; 682 uint32 addr; 683 684 LOG_VERBOSE(BSL_LS_SOC_COMMON, 685 (BSL_META_U(unit, 686 "EGR_VLAN_XLATE Delete\n"))); 687 688 bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, FALSE); 689 690 LOG_VERBOSE(BSL_LS_SOC_COMMON, 691 (BSL_META_U(unit, 692 "bucket %d\n"), bucket)); 693 694 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 695 soc_internal_egr_vlan_xlate_dual_banks(pcid_info, banks, &dual, 696 &slot_min, &slot_max); 697 } 698 blk = SOC_MEM_BLOCK_ANY(unit, EGR_VLAN_XLATEm); 699 sblk = SOC_BLOCK2SCH(unit, blk); 700 701 /* Check if entry exists */ 702 for (slot = slot_min; slot <= slot_max; slot++) { 703 if (dual && (slot == 4)) { 704 bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, TRUE); 705 } 706 index = bucket * 8 + slot; 707 addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index, 708 &acc_type); 709 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 710 if (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, tmp, VALIDf)) { 711 if (soc_mem_compare_key(unit, EGR_VLAN_XLATEm, entry, tmp) == 0) { 712 LOG_VERBOSE(BSL_LS_SOC_COMMON, 713 (BSL_META_U(unit, 714 "found sblk %d acc_type %d bucket %d, " 715 "slot %d, index %d\n"), 716 sblk, acc_type, bucket, slot, index)); 717 718 /* Copy entry immediately after response word */ 719 memcpy(&result[1], tmp, 720 soc_mem_entry_bytes(unit, EGR_VLAN_XLATEm)); 721 722 /* Invalidate entry */ 723 soc_mem_field32_set(unit, EGR_VLAN_XLATEm, tmp, VALIDf, 0); 724 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 725 addr, tmp); 726 727 result[0] = 0; 728 if (soc_feature(unit, soc_feature_new_sbus_format) && 729 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 730 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 731 genresp_v2->index = index; 732 } else { 733 genresp->type = SCHAN_GEN_RESP_TYPE_DELETED; 734 genresp->index = index; 735 } 736 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 737 738 return 0; 739 } 740 } 741 } 742 743 LOG_VERBOSE(BSL_LS_SOC_COMMON, 744 (BSL_META_U(unit, 745 "soc_internal_egr_vlan_xlate_entry_del: Not found\n"))); 746 747 result[0] = 0; 748 if (soc_feature(unit, soc_feature_new_sbus_format) && 749 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 750 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 751 } else { 752 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 753 } 754 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 755 return 0; 756 } 757 758 int 759 soc_internal_egr_vlan_xlate_entry_lkup(pcid_info_t * pcid_info, uint8 banks, 760 egr_vlan_xlate_entry_t *entry, 761 uint32 *result) 762 { 763 uint32 tmp[SOC_MAX_MEM_WORDS]; 764 int index = 0, bucket, slot; 765 int slot_min = 0, slot_max = 7, dual = FALSE; 766 int unit = pcid_info->unit; 767 schan_genresp_t *genresp = (schan_genresp_t *)result; 768 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 769 int blk; 770 soc_block_t sblk; 771 uint8 acc_type; 772 uint32 addr; 773 774 LOG_VERBOSE(BSL_LS_SOC_COMMON, 775 (BSL_META_U(unit, 776 "EGR_VLAN_XLATE Lookup\n"))); 777 778 bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, FALSE); 779 780 LOG_VERBOSE(BSL_LS_SOC_COMMON, 781 (BSL_META_U(unit, 782 "bucket %d\n"), bucket)); 783 784 if (soc_feature(unit, soc_feature_dual_hash)) { 785 soc_internal_egr_vlan_xlate_dual_banks(pcid_info, banks, &dual, 786 &slot_min, &slot_max); 787 } 788 blk = SOC_MEM_BLOCK_ANY(unit, EGR_VLAN_XLATEm); 789 sblk = SOC_BLOCK2SCH(unit, blk); 790 791 /* Check if entry exists */ 792 for (slot = slot_min; slot <= slot_max; slot++) { 793 if (dual && (slot == 4)) { 794 bucket = 795 soc_internal_egr_vlan_xlate_hash(pcid_info, entry, TRUE); 796 } 797 index = bucket * 8 + slot; 798 addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index, 799 &acc_type); 800 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 801 if (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, tmp, VALIDf)) { 802 if (soc_mem_compare_key(unit, EGR_VLAN_XLATEm, entry, tmp) == 0) { 803 LOG_VERBOSE(BSL_LS_SOC_COMMON, 804 (BSL_META_U(unit, 805 "found sblk %d acc_type %d bucket %d, " 806 "slot %d, index %d\n"), 807 sblk, acc_type, bucket, slot, index)); 808 809 /* Copy entry immediately after response word */ 810 memcpy(&result[1], tmp, 811 soc_mem_entry_bytes(unit, EGR_VLAN_XLATEm)); 812 813 result[0] = 0; 814 if (soc_feature(unit, soc_feature_new_sbus_format) && 815 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 816 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 817 genresp_v2->index = index; 818 } else { 819 genresp->type = SCHAN_GEN_RESP_TYPE_FOUND; 820 genresp->index = index; 821 } 822 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 823 824 return 0; 825 } 826 } 827 } 828 829 LOG_VERBOSE(BSL_LS_SOC_COMMON, 830 (BSL_META_U(unit, 831 "soc_internal_egr_vlan_xlate_entry_lkup: Not found\n"))); 832 833 result[0] = 0; 834 if (soc_feature(unit, soc_feature_new_sbus_format) && 835 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 836 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 837 } else { 838 genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 839 } 840 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 841 return 0; 842 } 843 844 #ifdef BCM_TRIDENT2_SUPPORT 845 int 846 soc_internal_ing_vp_vlan_member_hash(pcid_info_t *pcid_info, void *entry, 847 int dual) 848 { 849 soc_reg_t reg; 850 soc_field_t field; 851 uint32 tmp[SOC_MAX_MEM_WORDS]; 852 int hash_sel; 853 uint8 key[8]; 854 int index, bits; 855 soc_block_t blk; 856 uint8 acc_type; 857 uint32 addr; 858 859 LOG_VERBOSE(BSL_LS_SOC_COMMON, 860 (BSL_META("ING_VP_VLAN_MEMBERSHIP hash\n"))); 861 862 reg = ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLr; 863 field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af; 864 865 addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0, 866 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 867 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp); 868 hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field); 869 870 LOG_VERBOSE(BSL_LS_SOC_COMMON, 871 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 872 873 bits = soc_td2_ing_vp_vlan_member_base_entry_to_key(pcid_info->unit, dual, 874 entry, key); 875 index = soc_td2_ing_vp_vlan_member_hash(pcid_info->unit, hash_sel, bits, 876 entry, key); 877 878 LOG_VERBOSE(BSL_LS_SOC_COMMON, 879 (BSL_META("index %d\n"), index)); 880 881 return index; 882 } 883 884 void 885 soc_internal_ing_vp_vlan_member_dual_banks(pcid_info_t *pcid_info, uint8 banks, 886 int *dual, int *slot_min, 887 int *slot_max) 888 { 889 /* Dual hash always enabled for ING_VP_VLAN_MEMBERSHIP */ 890 *dual = TRUE; 891 892 if (*dual) { 893 switch (banks) { 894 case 0: 895 return; /* Nothing to do here */ 896 case 1: 897 *slot_min = 4; 898 *slot_max = 7; 899 break; 900 case 2: 901 *slot_min = 0; 902 *slot_max = 3; 903 break; 904 default: 905 *slot_min = 0; 906 *slot_max = -1; 907 break; 908 } 909 } 910 911 return; 912 } 913 914 int 915 soc_internal_ing_vp_vlan_member_ins(pcid_info_t *pcid_info, uint8 banks, 916 void *entry, uint32 *result) 917 { 918 uint32 tmp[SOC_MAX_MEM_WORDS]; 919 int index = 0, bucket, slot, free_index; 920 int slot_min = 0, slot_max = 7, dual = FALSE; 921 int unit = pcid_info->unit; 922 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 923 int blk; 924 soc_block_t sblk; 925 uint8 acc_type; 926 uint32 addr; 927 928 LOG_VERBOSE(BSL_LS_SOC_COMMON, 929 (BSL_META_U(unit, 930 "ING_VP_VLAN_MEMBERSHIP Insert\n"))); 931 932 bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, FALSE); 933 934 LOG_VERBOSE(BSL_LS_SOC_COMMON, 935 (BSL_META_U(unit, 936 "bucket %d\n"), bucket)); 937 938 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 939 soc_internal_ing_vp_vlan_member_dual_banks(pcid_info, banks, &dual, 940 &slot_min, &slot_max); 941 } 942 blk = SOC_MEM_BLOCK_ANY(unit, ING_VP_VLAN_MEMBERSHIPm); 943 sblk = SOC_BLOCK2SCH(unit, blk); 944 945 /* Check if it should overwrite an existing entry */ 946 free_index = -1; 947 for (slot = slot_min; slot <= slot_max; slot++) { 948 if (dual && (slot == 4)) { 949 bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, 950 TRUE); 951 } 952 index = bucket * 8 + slot; 953 addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index, 954 &acc_type); 955 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 956 if (soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) { 957 if (soc_mem_compare_key(unit, ING_VP_VLAN_MEMBERSHIPm, entry, tmp) 958 == 0) { 959 LOG_VERBOSE(BSL_LS_SOC_COMMON, 960 (BSL_META_U(unit, 961 "write sblk %d acc_type %d bucket %d, " 962 "slot %d, index %d\n"), 963 sblk, acc_type, index / 8, index % 8, index)); 964 965 /* Overwrite the existing entry */ 966 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 967 addr, entry); 968 969 /* Copy old entry immediately after response word */ 970 memcpy(&result[1], tmp, 971 soc_mem_entry_bytes(unit, ING_VP_VLAN_MEMBERSHIPm)); 972 973 result[0] = 0; 974 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 975 genresp_v2->index = index; 976 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 977 978 return 0; 979 } 980 } else { 981 if (free_index == -1) { 982 free_index = index; 983 } 984 } 985 } 986 987 /* Find first unused slot in bucket */ 988 if (free_index != -1) { 989 index = free_index; 990 addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index, 991 &acc_type); 992 993 LOG_VERBOSE(BSL_LS_SOC_COMMON, 994 (BSL_META_U(unit, 995 "write sblk %d acc_type %d bucket %d, slot %d, " 996 "index %d\n"), 997 sblk, acc_type, index / 8, index % 8, index)); 998 999 /* Write the new entry */ 1000 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 1001 entry); 1002 1003 result[0] = 0; 1004 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 1005 genresp_v2->index = index; 1006 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1007 1008 return 0; 1009 } 1010 1011 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1012 (BSL_META_U(unit, 1013 "Bucket full\n"))); 1014 1015 result[0] = 0; 1016 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 1017 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1018 1019 return 0; 1020 } 1021 1022 int 1023 soc_internal_ing_vp_vlan_member_del(pcid_info_t *pcid_info, uint8 banks, 1024 void *entry, uint32 *result) 1025 { 1026 uint32 tmp[SOC_MAX_MEM_WORDS]; 1027 int index = 0, bucket, slot; 1028 int slot_min = 0, slot_max = 7, dual = FALSE; 1029 int unit = pcid_info->unit; 1030 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1031 int blk; 1032 soc_block_t sblk; 1033 uint8 acc_type; 1034 uint32 addr; 1035 1036 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1037 (BSL_META_U(unit, 1038 "ING_VP_VLAN_MEMBERSHIP Delete\n"))); 1039 1040 bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, FALSE); 1041 1042 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1043 (BSL_META_U(unit, 1044 "bucket %d\n"), bucket)); 1045 1046 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 1047 soc_internal_ing_vp_vlan_member_dual_banks(pcid_info, banks, &dual, 1048 &slot_min, &slot_max); 1049 } 1050 blk = SOC_MEM_BLOCK_ANY(unit, ING_VP_VLAN_MEMBERSHIPm); 1051 sblk = SOC_BLOCK2SCH(unit, blk); 1052 1053 /* Check if entry exists */ 1054 for (slot = slot_min; slot <= slot_max; slot++) { 1055 if (dual && (slot == 4)) { 1056 bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, 1057 TRUE); 1058 } 1059 index = bucket * 8 + slot; 1060 addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index, 1061 &acc_type); 1062 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1063 if (soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) { 1064 if (soc_mem_compare_key(unit, ING_VP_VLAN_MEMBERSHIPm, entry, tmp) 1065 == 0) { 1066 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1067 (BSL_META_U(unit, 1068 "found sblk %d acc_type %d bucket %d, " 1069 "slot %d, index %d\n"), 1070 sblk, acc_type, bucket, slot, index)); 1071 1072 /* Copy entry immediately after response word */ 1073 memcpy(&result[1], tmp, 1074 soc_mem_entry_bytes(unit, ING_VP_VLAN_MEMBERSHIPm)); 1075 1076 /* Invalidate entry */ 1077 soc_mem_field32_set(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf, 1078 0); 1079 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1080 addr, tmp); 1081 1082 result[0] = 0; 1083 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 1084 genresp_v2->index = index; 1085 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1086 1087 return 0; 1088 } 1089 } 1090 } 1091 1092 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1093 (BSL_META_U(unit, 1094 "soc_internal_ing_vp_vlan_member_del: " 1095 "Not found\n"))); 1096 1097 result[0] = 0; 1098 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1099 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1100 return 0; 1101 } 1102 1103 int 1104 soc_internal_ing_vp_vlan_member_lkup(pcid_info_t *pcid_info, uint8 banks, 1105 void *entry, uint32 *result) 1106 { 1107 uint32 tmp[SOC_MAX_MEM_WORDS]; 1108 int index = 0, bucket, slot; 1109 int slot_min = 0, slot_max = 7, dual = FALSE; 1110 int unit = pcid_info->unit; 1111 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1112 int blk; 1113 soc_block_t sblk; 1114 uint8 acc_type; 1115 uint32 addr; 1116 1117 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1118 (BSL_META_U(unit, 1119 "ING_VP_VLAN_MEMBERSHIP Lookup\n"))); 1120 1121 bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, FALSE); 1122 1123 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1124 (BSL_META_U(unit, 1125 "bucket %d\n"), bucket)); 1126 1127 if (soc_feature(unit, soc_feature_dual_hash)) { 1128 soc_internal_ing_vp_vlan_member_dual_banks(pcid_info, banks, &dual, 1129 &slot_min, &slot_max); 1130 } 1131 blk = SOC_MEM_BLOCK_ANY(unit, ING_VP_VLAN_MEMBERSHIPm); 1132 sblk = SOC_BLOCK2SCH(unit, blk); 1133 1134 /* Check if entry exists */ 1135 for (slot = slot_min; slot <= slot_max; slot++) { 1136 if (dual && (slot == 4)) { 1137 bucket = 1138 soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, TRUE); 1139 } 1140 index = bucket * 8 + slot; 1141 addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index, 1142 &acc_type); 1143 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1144 if (soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) { 1145 if (soc_mem_compare_key(unit, ING_VP_VLAN_MEMBERSHIPm, entry, tmp) 1146 == 0) { 1147 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1148 (BSL_META_U(unit, 1149 "found sblk %d acc_type %d bucket %d, " 1150 "slot %d, index %d\n"), 1151 sblk, acc_type, bucket, slot, index)); 1152 1153 /* Copy entry immediately after response word */ 1154 memcpy(&result[1], tmp, 1155 soc_mem_entry_bytes(unit, ING_VP_VLAN_MEMBERSHIPm)); 1156 1157 result[0] = 0; 1158 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 1159 genresp_v2->index = index; 1160 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1161 1162 return 0; 1163 } 1164 } 1165 } 1166 1167 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1168 (BSL_META_U(unit, 1169 "soc_internal_ing_vp_vlan_member_lkup: Not found\n"))); 1170 1171 result[0] = 0; 1172 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1173 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1174 return 0; 1175 } 1176 1177 int 1178 soc_internal_egr_vp_vlan_member_hash(pcid_info_t *pcid_info, void *entry, 1179 int dual) 1180 { 1181 soc_reg_t reg; 1182 soc_field_t field; 1183 uint32 tmp[SOC_MAX_MEM_WORDS]; 1184 int hash_sel; 1185 uint8 key[8]; 1186 int index, bits; 1187 soc_block_t blk; 1188 uint8 acc_type; 1189 uint32 addr; 1190 1191 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1192 (BSL_META("EGR_VP_VLAN_MEMBERSHIP hash\n"))); 1193 1194 reg = EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLr; 1195 field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af; 1196 1197 addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0, 1198 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 1199 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp); 1200 hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field); 1201 1202 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1203 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 1204 1205 bits = soc_td2_egr_vp_vlan_member_base_entry_to_key(pcid_info->unit, dual, 1206 entry, key); 1207 index = soc_td2_egr_vp_vlan_member_hash(pcid_info->unit, hash_sel, bits, 1208 entry, key); 1209 1210 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1211 (BSL_META("index %d\n"), index)); 1212 1213 return index; 1214 } 1215 1216 void 1217 soc_internal_egr_vp_vlan_member_dual_banks(pcid_info_t *pcid_info, uint8 banks, 1218 int *dual, int *slot_min, 1219 int *slot_max) 1220 { 1221 /* Dual hash always enabled for EGR_VP_VLAN_MEMBERSHIP */ 1222 *dual = TRUE; 1223 1224 if (*dual) { 1225 switch (banks) { 1226 case 0: 1227 return; /* Nothing to do here */ 1228 case 1: 1229 *slot_min = 4; 1230 *slot_max = 7; 1231 break; 1232 case 2: 1233 *slot_min = 0; 1234 *slot_max = 3; 1235 break; 1236 default: 1237 *slot_min = 0; 1238 *slot_max = -1; 1239 break; 1240 } 1241 } 1242 1243 return; 1244 } 1245 1246 int 1247 soc_internal_egr_vp_vlan_member_ins(pcid_info_t *pcid_info, uint8 banks, 1248 void *entry, uint32 *result) 1249 { 1250 uint32 tmp[SOC_MAX_MEM_WORDS]; 1251 int index = 0, bucket, slot, free_index; 1252 int slot_min = 0, slot_max = 7, dual = FALSE; 1253 int unit = pcid_info->unit; 1254 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1255 int blk; 1256 soc_block_t sblk; 1257 uint8 acc_type; 1258 uint32 addr; 1259 1260 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1261 (BSL_META_U(unit, 1262 "EGR_VP_VLAN_MEMBERSHIP Insert\n"))); 1263 1264 bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, FALSE); 1265 1266 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1267 (BSL_META_U(unit, 1268 "bucket %d\n"), bucket)); 1269 1270 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 1271 soc_internal_egr_vp_vlan_member_dual_banks(pcid_info, banks, &dual, 1272 &slot_min, &slot_max); 1273 } 1274 blk = SOC_MEM_BLOCK_ANY(unit, EGR_VP_VLAN_MEMBERSHIPm); 1275 sblk = SOC_BLOCK2SCH(unit, blk); 1276 1277 /* Check if it should overwrite an existing entry */ 1278 free_index = -1; 1279 for (slot = slot_min; slot <= slot_max; slot++) { 1280 if (dual && (slot == 4)) { 1281 bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, 1282 TRUE); 1283 } 1284 index = bucket * 8 + slot; 1285 addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index, 1286 &acc_type); 1287 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1288 if (soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) { 1289 if (soc_mem_compare_key(unit, EGR_VP_VLAN_MEMBERSHIPm, entry, tmp) 1290 == 0) { 1291 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1292 (BSL_META_U(unit, 1293 "write sblk %d acc_type %d bucket %d, " 1294 "slot %d, index %d\n"), 1295 sblk, acc_type, index / 8, index % 8, index)); 1296 1297 /* Overwrite the existing entry */ 1298 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1299 addr, entry); 1300 1301 /* Copy old entry immediately after response word */ 1302 memcpy(&result[1], tmp, 1303 soc_mem_entry_bytes(unit, EGR_VP_VLAN_MEMBERSHIPm)); 1304 1305 result[0] = 0; 1306 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 1307 genresp_v2->index = index; 1308 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1309 1310 return 0; 1311 } 1312 } else { 1313 if (free_index == -1) { 1314 free_index = index; 1315 } 1316 } 1317 } 1318 1319 /* Find first unused slot in bucket */ 1320 if (free_index != -1) { 1321 index = free_index; 1322 addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index, 1323 &acc_type); 1324 1325 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1326 (BSL_META_U(unit, 1327 "write sblk %d acc_type %d bucket %d, slot %d, " 1328 "index %d\n"), 1329 sblk, acc_type, index / 8, index % 8, index)); 1330 1331 /* Write the new entry */ 1332 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 1333 entry); 1334 1335 result[0] = 0; 1336 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 1337 genresp_v2->index = index; 1338 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1339 1340 return 0; 1341 } 1342 1343 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1344 (BSL_META_U(unit, 1345 "Bucket full\n"))); 1346 1347 result[0] = 0; 1348 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 1349 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1350 1351 return 0; 1352 } 1353 1354 int 1355 soc_internal_egr_vp_vlan_member_del(pcid_info_t *pcid_info, uint8 banks, 1356 void *entry, uint32 *result) 1357 { 1358 uint32 tmp[SOC_MAX_MEM_WORDS]; 1359 int index = 0, bucket, slot; 1360 int slot_min = 0, slot_max = 7, dual = FALSE; 1361 int unit = pcid_info->unit; 1362 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1363 int blk; 1364 soc_block_t sblk; 1365 uint8 acc_type; 1366 uint32 addr; 1367 1368 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1369 (BSL_META_U(unit, 1370 "EGR_VP_VLAN_MEMBERSHIP Delete\n"))); 1371 1372 bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, FALSE); 1373 1374 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1375 (BSL_META_U(unit, 1376 "bucket %d\n"), bucket)); 1377 1378 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 1379 soc_internal_egr_vp_vlan_member_dual_banks(pcid_info, banks, &dual, 1380 &slot_min, &slot_max); 1381 } 1382 blk = SOC_MEM_BLOCK_ANY(unit, EGR_VP_VLAN_MEMBERSHIPm); 1383 sblk = SOC_BLOCK2SCH(unit, blk); 1384 1385 /* Check if entry exists */ 1386 for (slot = slot_min; slot <= slot_max; slot++) { 1387 if (dual && (slot == 4)) { 1388 bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, 1389 TRUE); 1390 } 1391 index = bucket * 8 + slot; 1392 addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index, 1393 &acc_type); 1394 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1395 if (soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) { 1396 if (soc_mem_compare_key(unit, EGR_VP_VLAN_MEMBERSHIPm, entry, tmp) 1397 == 0) { 1398 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1399 (BSL_META_U(unit, 1400 "found sblk %d acc_type %d bucket %d, " 1401 "slot %d, index %d\n"), 1402 sblk, acc_type, bucket, slot, index)); 1403 1404 /* Copy entry immediately after response word */ 1405 memcpy(&result[1], tmp, 1406 soc_mem_entry_bytes(unit, EGR_VP_VLAN_MEMBERSHIPm)); 1407 1408 /* Invalidate entry */ 1409 soc_mem_field32_set(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf, 1410 0); 1411 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1412 addr, tmp); 1413 1414 result[0] = 0; 1415 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 1416 genresp_v2->index = index; 1417 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1418 1419 return 0; 1420 } 1421 } 1422 } 1423 1424 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1425 (BSL_META_U(unit, 1426 "soc_internal_egr_vp_vlan_member_del: " 1427 "Not found\n"))); 1428 1429 result[0] = 0; 1430 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1431 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1432 return 0; 1433 } 1434 1435 int 1436 soc_internal_egr_vp_vlan_member_lkup(pcid_info_t *pcid_info, uint8 banks, 1437 void *entry, uint32 *result) 1438 { 1439 uint32 tmp[SOC_MAX_MEM_WORDS]; 1440 int index = 0, bucket, slot; 1441 int slot_min = 0, slot_max = 7, dual = FALSE; 1442 int unit = pcid_info->unit; 1443 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1444 int blk; 1445 soc_block_t sblk; 1446 uint8 acc_type; 1447 uint32 addr; 1448 1449 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1450 (BSL_META_U(unit, 1451 "EGR_VP_VLAN_MEMBERSHIP Lookup\n"))); 1452 1453 bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, FALSE); 1454 1455 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1456 (BSL_META_U(unit, 1457 "bucket %d\n"), bucket)); 1458 1459 if (soc_feature(unit, soc_feature_dual_hash)) { 1460 soc_internal_egr_vp_vlan_member_dual_banks(pcid_info, banks, &dual, 1461 &slot_min, &slot_max); 1462 } 1463 blk = SOC_MEM_BLOCK_ANY(unit, EGR_VP_VLAN_MEMBERSHIPm); 1464 sblk = SOC_BLOCK2SCH(unit, blk); 1465 1466 /* Check if entry exists */ 1467 for (slot = slot_min; slot <= slot_max; slot++) { 1468 if (dual && (slot == 4)) { 1469 bucket = 1470 soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, TRUE); 1471 } 1472 index = bucket * 8 + slot; 1473 addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index, 1474 &acc_type); 1475 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1476 if (soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) { 1477 if (soc_mem_compare_key(unit, EGR_VP_VLAN_MEMBERSHIPm, entry, tmp) 1478 == 0) { 1479 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1480 (BSL_META_U(unit, 1481 "found sblk %d acc_type %d bucket %d, " 1482 "slot %d, index %d\n"), 1483 sblk, acc_type, bucket, slot, index)); 1484 1485 /* Copy entry immediately after response word */ 1486 memcpy(&result[1], tmp, 1487 soc_mem_entry_bytes(unit, EGR_VP_VLAN_MEMBERSHIPm)); 1488 1489 result[0] = 0; 1490 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 1491 genresp_v2->index = index; 1492 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1493 1494 return 0; 1495 } 1496 } 1497 } 1498 1499 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1500 (BSL_META_U(unit, 1501 "soc_internal_egr_vp_vlan_member_lkup: Not found\n"))); 1502 1503 result[0] = 0; 1504 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1505 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1506 return 0; 1507 } 1508 1509 int 1510 soc_internal_ing_dnat_address_type_hash(pcid_info_t *pcid_info, void *entry, 1511 int dual) 1512 { 1513 soc_reg_t reg; 1514 soc_field_t field; 1515 uint32 tmp[SOC_MAX_MEM_WORDS]; 1516 int hash_sel; 1517 uint8 key[8]; 1518 int index, bits; 1519 soc_block_t blk; 1520 uint8 acc_type; 1521 uint32 addr; 1522 1523 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1524 (BSL_META("ING_DNAT_ADDRESS_TYPE hash\n"))); 1525 1526 reg = ING_DNAT_ADDRESS_TYPE_HASH_CONTROLr; 1527 field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af; 1528 1529 addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0, 1530 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 1531 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp); 1532 hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field); 1533 1534 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1535 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 1536 1537 bits = soc_td2_ing_dnat_address_type_base_entry_to_key(pcid_info->unit, dual, 1538 entry, key); 1539 index = soc_td2_ing_dnat_address_type_hash(pcid_info->unit, hash_sel, bits, 1540 entry, key); 1541 1542 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1543 (BSL_META("index %d\n"), index)); 1544 1545 return index; 1546 } 1547 1548 void 1549 soc_internal_ing_dnat_address_type_dual_banks(pcid_info_t *pcid_info, 1550 uint8 banks, int *dual, 1551 int *slot_min, int *slot_max) 1552 { 1553 /* Dual hash always enabled for ING_DNAT_ADDRESS_TYPE */ 1554 *dual = TRUE; 1555 1556 if (*dual) { 1557 switch (banks) { 1558 case 0: 1559 return; /* Nothing to do here */ 1560 case 1: 1561 *slot_min = 4; 1562 *slot_max = 7; 1563 break; 1564 case 2: 1565 *slot_min = 0; 1566 *slot_max = 3; 1567 break; 1568 default: 1569 *slot_min = 0; 1570 *slot_max = -1; 1571 break; 1572 } 1573 } 1574 1575 return; 1576 } 1577 1578 int 1579 soc_internal_ing_dnat_address_type_ins(pcid_info_t *pcid_info, uint8 banks, 1580 void *entry, uint32 *result) 1581 { 1582 uint32 tmp[SOC_MAX_MEM_WORDS]; 1583 int index = 0, bucket, slot, free_index; 1584 int slot_min = 0, slot_max = 7, dual = FALSE; 1585 int unit = pcid_info->unit; 1586 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1587 int blk; 1588 soc_block_t sblk; 1589 uint8 acc_type; 1590 uint32 addr; 1591 1592 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1593 (BSL_META_U(unit, 1594 "ING_DNAT_ADDRESS_TYPE Insert\n"))); 1595 1596 bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, FALSE); 1597 1598 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1599 (BSL_META_U(unit, 1600 "bucket %d\n"), bucket)); 1601 1602 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 1603 soc_internal_ing_dnat_address_type_dual_banks(pcid_info, banks, &dual, 1604 &slot_min, &slot_max); 1605 } 1606 blk = SOC_MEM_BLOCK_ANY(unit, ING_DNAT_ADDRESS_TYPEm); 1607 sblk = SOC_BLOCK2SCH(unit, blk); 1608 1609 /* Check if it should overwrite an existing entry */ 1610 free_index = -1; 1611 for (slot = slot_min; slot <= slot_max; slot++) { 1612 if (dual && (slot == 4)) { 1613 bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, 1614 TRUE); 1615 } 1616 index = bucket * 8 + slot; 1617 addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index, 1618 &acc_type); 1619 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1620 if (soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf)) { 1621 if (soc_mem_compare_key(unit, ING_DNAT_ADDRESS_TYPEm, entry, tmp) 1622 == 0) { 1623 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1624 (BSL_META_U(unit, 1625 "write sblk %d acc_type %d bucket %d, " 1626 "slot %d, index %d\n"), 1627 sblk, acc_type, index / 8, index % 8, index)); 1628 1629 /* Overwrite the existing entry */ 1630 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1631 addr, entry); 1632 1633 /* Copy old entry immediately after response word */ 1634 memcpy(&result[1], tmp, 1635 soc_mem_entry_bytes(unit, ING_DNAT_ADDRESS_TYPEm)); 1636 1637 result[0] = 0; 1638 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 1639 genresp_v2->index = index; 1640 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1641 1642 return 0; 1643 } 1644 } else { 1645 if (free_index == -1) { 1646 free_index = index; 1647 } 1648 } 1649 } 1650 1651 /* Find first unused slot in bucket */ 1652 if (free_index != -1) { 1653 index = free_index; 1654 addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index, 1655 &acc_type); 1656 1657 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1658 (BSL_META_U(unit, 1659 "write sblk %d acc_type %d bucket %d, slot %d, " 1660 "index %d\n"), 1661 sblk, acc_type, index / 8, index % 8, index)); 1662 1663 /* Write the new entry */ 1664 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 1665 entry); 1666 1667 result[0] = 0; 1668 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 1669 genresp_v2->index = index; 1670 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1671 1672 return 0; 1673 } 1674 1675 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1676 (BSL_META_U(unit, 1677 "Bucket full\n"))); 1678 1679 result[0] = 0; 1680 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 1681 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1682 1683 return 0; 1684 } 1685 1686 int 1687 soc_internal_ing_dnat_address_type_del(pcid_info_t *pcid_info, uint8 banks, 1688 void *entry, uint32 *result) 1689 { 1690 uint32 tmp[SOC_MAX_MEM_WORDS]; 1691 int index = 0, bucket, slot; 1692 int slot_min = 0, slot_max = 7, dual = FALSE; 1693 int unit = pcid_info->unit; 1694 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1695 int blk; 1696 soc_block_t sblk; 1697 uint8 acc_type; 1698 uint32 addr; 1699 1700 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1701 (BSL_META_U(unit, 1702 "ING_DNAT_ADDRESS_TYPE Delete\n"))); 1703 1704 bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, FALSE); 1705 1706 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1707 (BSL_META_U(unit, 1708 "bucket %d\n"), bucket)); 1709 1710 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 1711 soc_internal_ing_dnat_address_type_dual_banks(pcid_info, banks, &dual, 1712 &slot_min, &slot_max); 1713 } 1714 blk = SOC_MEM_BLOCK_ANY(unit, ING_DNAT_ADDRESS_TYPEm); 1715 sblk = SOC_BLOCK2SCH(unit, blk); 1716 1717 /* Check if entry exists */ 1718 for (slot = slot_min; slot <= slot_max; slot++) { 1719 if (dual && (slot == 4)) { 1720 bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, 1721 TRUE); 1722 } 1723 index = bucket * 8 + slot; 1724 addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index, 1725 &acc_type); 1726 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1727 if (soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf)) { 1728 if (soc_mem_compare_key(unit, ING_DNAT_ADDRESS_TYPEm, entry, tmp) 1729 == 0) { 1730 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1731 (BSL_META_U(unit, 1732 "found sblk %d acc_type %d bucket %d, " 1733 "slot %d, index %d\n"), 1734 sblk, acc_type, bucket, slot, index)); 1735 1736 /* Copy entry immediately after response word */ 1737 memcpy(&result[1], tmp, 1738 soc_mem_entry_bytes(unit, ING_DNAT_ADDRESS_TYPEm)); 1739 1740 /* Invalidate entry */ 1741 soc_mem_field32_set(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf, 1742 0); 1743 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1744 addr, tmp); 1745 1746 result[0] = 0; 1747 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 1748 genresp_v2->index = index; 1749 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1750 1751 return 0; 1752 } 1753 } 1754 } 1755 1756 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1757 (BSL_META_U(unit, 1758 "soc_internal_ing_dnat_address_type_del: " 1759 "Not found\n"))); 1760 1761 result[0] = 0; 1762 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1763 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1764 return 0; 1765 } 1766 1767 int 1768 soc_internal_ing_dnat_address_type_lkup(pcid_info_t *pcid_info, uint8 banks, 1769 void *entry, uint32 *result) 1770 { 1771 uint32 tmp[SOC_MAX_MEM_WORDS]; 1772 int index = 0, bucket, slot; 1773 int slot_min = 0, slot_max = 7, dual = FALSE; 1774 int unit = pcid_info->unit; 1775 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1776 int blk; 1777 soc_block_t sblk; 1778 uint8 acc_type; 1779 uint32 addr; 1780 1781 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1782 (BSL_META_U(unit, 1783 "ING_DNAT_ADDRESS_TYPE Lookup\n"))); 1784 1785 bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, FALSE); 1786 1787 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1788 (BSL_META_U(unit, 1789 "bucket %d\n"), bucket)); 1790 1791 if (soc_feature(unit, soc_feature_dual_hash)) { 1792 soc_internal_ing_dnat_address_type_dual_banks(pcid_info, banks, &dual, 1793 &slot_min, &slot_max); 1794 } 1795 blk = SOC_MEM_BLOCK_ANY(unit, ING_DNAT_ADDRESS_TYPEm); 1796 sblk = SOC_BLOCK2SCH(unit, blk); 1797 1798 /* Check if entry exists */ 1799 for (slot = slot_min; slot <= slot_max; slot++) { 1800 if (dual && (slot == 4)) { 1801 bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, 1802 TRUE); 1803 } 1804 index = bucket * 8 + slot; 1805 addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index, 1806 &acc_type); 1807 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1808 if (soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf)) { 1809 if (soc_mem_compare_key(unit, ING_DNAT_ADDRESS_TYPEm, entry, tmp) 1810 == 0) { 1811 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1812 (BSL_META_U(unit, 1813 "found sblk %d acc_type %d bucket %d, " 1814 "slot %d, index %d\n"), 1815 sblk, acc_type, bucket, slot, index)); 1816 1817 /* Copy entry immediately after response word */ 1818 memcpy(&result[1], tmp, 1819 soc_mem_entry_bytes(unit, ING_DNAT_ADDRESS_TYPEm)); 1820 1821 result[0] = 0; 1822 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 1823 genresp_v2->index = index; 1824 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1825 1826 return 0; 1827 } 1828 } 1829 } 1830 1831 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1832 (BSL_META_U(unit, 1833 "soc_internal_ing_dnat_address_type_lkup: Not found\n"))); 1834 1835 result[0] = 0; 1836 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 1837 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 1838 return 0; 1839 } 1840 1841 int 1842 soc_internal_l2_endpoint_id_hash(pcid_info_t *pcid_info, void *entry, 1843 int dual) 1844 { 1845 soc_reg_t reg; 1846 soc_field_t field; 1847 uint32 tmp[SOC_MAX_MEM_WORDS]; 1848 int hash_sel; 1849 uint8 key[8]; 1850 int index, bits; 1851 soc_block_t blk; 1852 uint8 acc_type; 1853 uint32 addr; 1854 1855 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1856 (BSL_META("L2_ENDPOINT_ID hash\n"))); 1857 1858 reg = L2_ENDPOINT_ID_HASH_CONTROLr; 1859 field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af; 1860 1861 addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0, 1862 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 1863 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp); 1864 hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field); 1865 1866 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1867 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 1868 1869 bits = soc_td2_l2_endpoint_id_base_entry_to_key(pcid_info->unit, dual, 1870 entry, key); 1871 index = soc_td2_l2_endpoint_id_hash(pcid_info->unit, hash_sel, bits, entry, 1872 key); 1873 1874 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1875 (BSL_META("index %d\n"), index)); 1876 1877 return index; 1878 } 1879 1880 void 1881 soc_internal_l2_endpoint_id_dual_banks(pcid_info_t *pcid_info, uint8 banks, 1882 int *dual, int *slot_min, int *slot_max) 1883 { 1884 /* Dual hash always enabled for L2_ENDPOINT_ID */ 1885 *dual = TRUE; 1886 1887 if (*dual) { 1888 switch (banks) { 1889 case 0: 1890 return; /* Nothing to do here */ 1891 case 1: 1892 *slot_min = 4; 1893 *slot_max = 7; 1894 break; 1895 case 2: 1896 *slot_min = 0; 1897 *slot_max = 3; 1898 break; 1899 default: 1900 *slot_min = 0; 1901 *slot_max = -1; 1902 break; 1903 } 1904 } 1905 1906 return; 1907 } 1908 1909 int 1910 soc_internal_l2_endpoint_id_ins(pcid_info_t *pcid_info, uint8 banks, 1911 void *entry, uint32 *result) 1912 { 1913 uint32 tmp[SOC_MAX_MEM_WORDS]; 1914 int index = 0, bucket, slot, free_index; 1915 int slot_min = 0, slot_max = 7, dual = FALSE; 1916 int unit = pcid_info->unit; 1917 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 1918 int blk; 1919 soc_block_t sblk; 1920 uint8 acc_type; 1921 uint32 addr; 1922 1923 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1924 (BSL_META_U(unit, 1925 "L2_ENDPOINT_ID Insert\n"))); 1926 1927 bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, FALSE); 1928 1929 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1930 (BSL_META_U(unit, 1931 "bucket %d\n"), bucket)); 1932 1933 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 1934 soc_internal_l2_endpoint_id_dual_banks(pcid_info, banks, &dual, 1935 &slot_min, &slot_max); 1936 } 1937 blk = SOC_MEM_BLOCK_ANY(unit, L2_ENDPOINT_IDm); 1938 sblk = SOC_BLOCK2SCH(unit, blk); 1939 1940 /* Check if it should overwrite an existing entry */ 1941 free_index = -1; 1942 for (slot = slot_min; slot <= slot_max; slot++) { 1943 if (dual && (slot == 4)) { 1944 bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, TRUE); 1945 } 1946 index = bucket * 8 + slot; 1947 addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index, 1948 &acc_type); 1949 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 1950 if (soc_mem_field32_get(unit, L2_ENDPOINT_IDm, tmp, VALIDf)) { 1951 if (soc_mem_compare_key(unit, L2_ENDPOINT_IDm, entry, tmp) == 0) { 1952 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1953 (BSL_META_U(unit, 1954 "write sblk %d acc_type %d bucket %d, " 1955 "slot %d, index %d\n"), 1956 sblk, acc_type, index / 8, index % 8, index)); 1957 1958 /* Overwrite the existing entry */ 1959 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 1960 addr, entry); 1961 1962 /* Copy old entry immediately after response word */ 1963 memcpy(&result[1], tmp, 1964 soc_mem_entry_bytes(unit, L2_ENDPOINT_IDm)); 1965 1966 result[0] = 0; 1967 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 1968 genresp_v2->index = index; 1969 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 1970 1971 return 0; 1972 } 1973 } else { 1974 if (free_index == -1) { 1975 free_index = index; 1976 } 1977 } 1978 } 1979 1980 /* Find first unused slot in bucket */ 1981 if (free_index != -1) { 1982 index = free_index; 1983 addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index, 1984 &acc_type); 1985 1986 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1987 (BSL_META_U(unit, 1988 "write sblk %d acc_type %d bucket %d, slot %d, " 1989 "index %d\n"), 1990 sblk, acc_type, index / 8, index % 8, index)); 1991 1992 /* Write the new entry */ 1993 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 1994 entry); 1995 1996 result[0] = 0; 1997 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 1998 genresp_v2->index = index; 1999 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 2000 2001 return 0; 2002 } 2003 2004 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2005 (BSL_META_U(unit, 2006 "Bucket full\n"))); 2007 2008 result[0] = 0; 2009 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 2010 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 2011 2012 return 0; 2013 } 2014 2015 int 2016 soc_internal_l2_endpoint_id_del(pcid_info_t *pcid_info, uint8 banks, 2017 void *entry, uint32 *result) 2018 { 2019 uint32 tmp[SOC_MAX_MEM_WORDS]; 2020 int index = 0, bucket, slot; 2021 int slot_min = 0, slot_max = 7, dual = FALSE; 2022 int unit = pcid_info->unit; 2023 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 2024 int blk; 2025 soc_block_t sblk; 2026 uint8 acc_type; 2027 uint32 addr; 2028 2029 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2030 (BSL_META_U(unit, 2031 "L2_ENDPOINT_ID Delete\n"))); 2032 2033 bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, FALSE); 2034 2035 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2036 (BSL_META_U(unit, 2037 "bucket %d\n"), bucket)); 2038 2039 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 2040 soc_internal_l2_endpoint_id_dual_banks(pcid_info, banks, &dual, 2041 &slot_min, &slot_max); 2042 } 2043 blk = SOC_MEM_BLOCK_ANY(unit, L2_ENDPOINT_IDm); 2044 sblk = SOC_BLOCK2SCH(unit, blk); 2045 2046 /* Check if entry exists */ 2047 for (slot = slot_min; slot <= slot_max; slot++) { 2048 if (dual && (slot == 4)) { 2049 bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, TRUE); 2050 } 2051 index = bucket * 8 + slot; 2052 addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index, 2053 &acc_type); 2054 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 2055 if (soc_mem_field32_get(unit, L2_ENDPOINT_IDm, tmp, VALIDf)) { 2056 if (soc_mem_compare_key(unit, L2_ENDPOINT_IDm, entry, tmp) == 0) { 2057 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2058 (BSL_META_U(unit, 2059 "found sblk %d acc_type %d bucket %d, " 2060 "slot %d, index %d\n"), 2061 sblk, acc_type, bucket, slot, index)); 2062 2063 /* Copy entry immediately after response word */ 2064 memcpy(&result[1], tmp, 2065 soc_mem_entry_bytes(unit, L2_ENDPOINT_IDm)); 2066 2067 /* Invalidate entry */ 2068 soc_mem_field32_set(unit, L2_ENDPOINT_IDm, tmp, VALIDf, 0); 2069 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 2070 addr, tmp); 2071 2072 result[0] = 0; 2073 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 2074 genresp_v2->index = index; 2075 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 2076 2077 return 0; 2078 } 2079 } 2080 } 2081 2082 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2083 (BSL_META_U(unit, 2084 "soc_internal_l2_endpoint_id_del: " 2085 "Not found\n"))); 2086 2087 result[0] = 0; 2088 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 2089 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 2090 return 0; 2091 } 2092 2093 int 2094 soc_internal_l2_endpoint_id_lkup(pcid_info_t *pcid_info, uint8 banks, 2095 void *entry, uint32 *result) 2096 { 2097 uint32 tmp[SOC_MAX_MEM_WORDS]; 2098 int index = 0, bucket, slot; 2099 int slot_min = 0, slot_max = 7, dual = FALSE; 2100 int unit = pcid_info->unit; 2101 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 2102 int blk; 2103 soc_block_t sblk; 2104 uint8 acc_type; 2105 uint32 addr; 2106 2107 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2108 (BSL_META_U(unit, 2109 "L2_ENDPOINT_ID Lookup\n"))); 2110 2111 bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, FALSE); 2112 2113 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2114 (BSL_META_U(unit, 2115 "bucket %d\n"), bucket)); 2116 2117 if (soc_feature(unit, soc_feature_dual_hash)) { 2118 soc_internal_l2_endpoint_id_dual_banks(pcid_info, banks, &dual, 2119 &slot_min, &slot_max); 2120 } 2121 blk = SOC_MEM_BLOCK_ANY(unit, L2_ENDPOINT_IDm); 2122 sblk = SOC_BLOCK2SCH(unit, blk); 2123 2124 /* Check if entry exists */ 2125 for (slot = slot_min; slot <= slot_max; slot++) { 2126 if (dual && (slot == 4)) { 2127 bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, TRUE); 2128 } 2129 index = bucket * 8 + slot; 2130 addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index, 2131 &acc_type); 2132 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 2133 if (soc_mem_field32_get(unit, L2_ENDPOINT_IDm, tmp, VALIDf)) { 2134 if (soc_mem_compare_key(unit, L2_ENDPOINT_IDm, entry, tmp) 2135 == 0) { 2136 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2137 (BSL_META_U(unit, 2138 "found sblk %d acc_type %d bucket %d, " 2139 "slot %d, index %d\n"), 2140 sblk, acc_type, bucket, slot, index)); 2141 2142 /* Copy entry immediately after response word */ 2143 memcpy(&result[1], tmp, 2144 soc_mem_entry_bytes(unit, L2_ENDPOINT_IDm)); 2145 2146 result[0] = 0; 2147 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 2148 genresp_v2->index = index; 2149 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 2150 2151 return 0; 2152 } 2153 } 2154 } 2155 2156 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2157 (BSL_META_U(unit, 2158 "soc_internal_l2_endpoint_id_lkup: Not found\n"))); 2159 2160 result[0] = 0; 2161 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 2162 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 2163 return 0; 2164 } 2165 2166 int 2167 soc_internal_endpoint_queue_map_hash(pcid_info_t *pcid_info, void *entry, 2168 int dual) 2169 { 2170 soc_reg_t reg; 2171 soc_field_t field; 2172 uint32 tmp[SOC_MAX_MEM_WORDS]; 2173 int hash_sel; 2174 uint8 key[8]; 2175 int index, bits; 2176 soc_block_t blk; 2177 uint8 acc_type; 2178 uint32 addr; 2179 2180 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2181 (BSL_META("ENDPOINT_QUEUE_MAP hash\n"))); 2182 2183 reg = ENDPOINT_QUEUE_MAP_HASH_CONTROLr; 2184 field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af; 2185 2186 addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0, 2187 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type); 2188 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp); 2189 hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field); 2190 2191 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2192 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel)); 2193 2194 bits = soc_td2_endpoint_queue_map_base_entry_to_key(pcid_info->unit, dual, 2195 entry, key); 2196 index = soc_td2_endpoint_queue_map_hash(pcid_info->unit, hash_sel, bits, 2197 entry, key); 2198 2199 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2200 (BSL_META("index %d\n"), index)); 2201 2202 return index; 2203 } 2204 2205 void 2206 soc_internal_endpoint_queue_map_dual_banks(pcid_info_t *pcid_info, uint8 banks, 2207 int *dual, int *slot_min, 2208 int *slot_max) 2209 { 2210 /* Dual hash always enabled for ENDPOINT_QUEUE_MAP */ 2211 *dual = TRUE; 2212 2213 if (*dual) { 2214 switch (banks) { 2215 case 0: 2216 return; /* Nothing to do here */ 2217 case 1: 2218 *slot_min = 4; 2219 *slot_max = 7; 2220 break; 2221 case 2: 2222 *slot_min = 0; 2223 *slot_max = 3; 2224 break; 2225 default: 2226 *slot_min = 0; 2227 *slot_max = -1; 2228 break; 2229 } 2230 } 2231 2232 return; 2233 } 2234 2235 int 2236 soc_internal_endpoint_queue_map_ins(pcid_info_t *pcid_info, uint8 banks, 2237 void *entry, uint32 *result) 2238 { 2239 uint32 tmp[SOC_MAX_MEM_WORDS]; 2240 int index = 0, bucket, slot, free_index; 2241 int slot_min = 0, slot_max = 7, dual = FALSE; 2242 int unit = pcid_info->unit; 2243 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 2244 int blk; 2245 soc_block_t sblk; 2246 uint8 acc_type; 2247 uint32 addr; 2248 2249 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2250 (BSL_META_U(unit, 2251 "ENDPOINT_QUEUE_MAP Insert\n"))); 2252 2253 bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, FALSE); 2254 2255 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2256 (BSL_META_U(unit, 2257 "bucket %d\n"), bucket)); 2258 2259 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 2260 soc_internal_endpoint_queue_map_dual_banks(pcid_info, banks, &dual, 2261 &slot_min, &slot_max); 2262 } 2263 blk = SOC_MEM_BLOCK_ANY(unit, ENDPOINT_QUEUE_MAPm); 2264 sblk = SOC_BLOCK2SCH(unit, blk); 2265 2266 /* Check if it should overwrite an existing entry */ 2267 free_index = -1; 2268 for (slot = slot_min; slot <= slot_max; slot++) { 2269 if (dual && (slot == 4)) { 2270 bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, 2271 TRUE); 2272 } 2273 index = bucket * 8 + slot; 2274 addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index, 2275 &acc_type); 2276 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 2277 if (soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf)) { 2278 if (soc_mem_compare_key(unit, ENDPOINT_QUEUE_MAPm, entry, tmp) 2279 == 0) { 2280 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2281 (BSL_META_U(unit, 2282 "write sblk %d acc_type %d bucket %d, " 2283 "slot %d, index %d\n"), 2284 sblk, acc_type, index / 8, index % 8, index)); 2285 2286 /* Overwrite the existing entry */ 2287 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 2288 addr, entry); 2289 2290 /* Copy old entry immediately after response word */ 2291 memcpy(&result[1], tmp, 2292 soc_mem_entry_bytes(unit, ENDPOINT_QUEUE_MAPm)); 2293 2294 result[0] = 0; 2295 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 2296 genresp_v2->index = index; 2297 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 2298 2299 return 0; 2300 } 2301 } else { 2302 if (free_index == -1) { 2303 free_index = index; 2304 } 2305 } 2306 } 2307 2308 /* Find first unused slot in bucket */ 2309 if (free_index != -1) { 2310 index = free_index; 2311 addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index, 2312 &acc_type); 2313 2314 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2315 (BSL_META_U(unit, 2316 "write sblk %d acc_type %d bucket %d, slot %d, " 2317 "index %d\n"), 2318 sblk, acc_type, index / 8, index % 8, index)); 2319 2320 /* Write the new entry */ 2321 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 2322 entry); 2323 2324 result[0] = 0; 2325 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 2326 genresp_v2->index = index; 2327 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 2328 2329 return 0; 2330 } 2331 2332 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2333 (BSL_META_U(unit, 2334 "Bucket full\n"))); 2335 2336 result[0] = 0; 2337 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 2338 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 2339 2340 return 0; 2341 } 2342 2343 int 2344 soc_internal_endpoint_queue_map_del(pcid_info_t *pcid_info, uint8 banks, 2345 void *entry, uint32 *result) 2346 { 2347 uint32 tmp[SOC_MAX_MEM_WORDS]; 2348 int index = 0, bucket, slot; 2349 int slot_min = 0, slot_max = 7, dual = FALSE; 2350 int unit = pcid_info->unit; 2351 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 2352 int blk; 2353 soc_block_t sblk; 2354 uint8 acc_type; 2355 uint32 addr; 2356 2357 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2358 (BSL_META_U(unit, 2359 "ENDPOINT_QUEUE_MAP Delete\n"))); 2360 2361 bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, FALSE); 2362 2363 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2364 (BSL_META_U(unit, 2365 "bucket %d\n"), bucket)); 2366 2367 if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) { 2368 soc_internal_endpoint_queue_map_dual_banks(pcid_info, banks, &dual, 2369 &slot_min, &slot_max); 2370 } 2371 blk = SOC_MEM_BLOCK_ANY(unit, ENDPOINT_QUEUE_MAPm); 2372 sblk = SOC_BLOCK2SCH(unit, blk); 2373 2374 /* Check if entry exists */ 2375 for (slot = slot_min; slot <= slot_max; slot++) { 2376 if (dual && (slot == 4)) { 2377 bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, 2378 TRUE); 2379 } 2380 index = bucket * 8 + slot; 2381 addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index, 2382 &acc_type); 2383 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 2384 if (soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf)) { 2385 if (soc_mem_compare_key(unit, ENDPOINT_QUEUE_MAPm, entry, tmp) 2386 == 0) { 2387 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2388 (BSL_META_U(unit, 2389 "found sblk %d acc_type %d bucket %d, " 2390 "slot %d, index %d\n"), 2391 sblk, acc_type, bucket, slot, index)); 2392 2393 /* Copy entry immediately after response word */ 2394 memcpy(&result[1], tmp, 2395 soc_mem_entry_bytes(unit, ENDPOINT_QUEUE_MAPm)); 2396 2397 /* Invalidate entry */ 2398 soc_mem_field32_set(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf, 0); 2399 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 2400 addr, tmp); 2401 2402 result[0] = 0; 2403 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED; 2404 genresp_v2->index = index; 2405 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 2406 2407 return 0; 2408 } 2409 } 2410 } 2411 2412 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2413 (BSL_META_U(unit, 2414 "soc_internal_endpoint_queue_map_del: " 2415 "Not found\n"))); 2416 2417 result[0] = 0; 2418 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 2419 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 2420 return 0; 2421 } 2422 2423 int 2424 soc_internal_endpoint_queue_map_lkup(pcid_info_t *pcid_info, uint8 banks, 2425 void *entry, uint32 *result) 2426 { 2427 uint32 tmp[SOC_MAX_MEM_WORDS]; 2428 int index = 0, bucket, slot; 2429 int slot_min = 0, slot_max = 7, dual = FALSE; 2430 int unit = pcid_info->unit; 2431 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result; 2432 int blk; 2433 soc_block_t sblk; 2434 uint8 acc_type; 2435 uint32 addr; 2436 2437 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2438 (BSL_META_U(unit, 2439 "ENDPOINT_QUEUE_MAP Lookup\n"))); 2440 2441 bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, FALSE); 2442 2443 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2444 (BSL_META_U(unit, 2445 "bucket %d\n"), bucket)); 2446 2447 if (soc_feature(unit, soc_feature_dual_hash)) { 2448 soc_internal_endpoint_queue_map_dual_banks(pcid_info, banks, &dual, 2449 &slot_min, &slot_max); 2450 } 2451 blk = SOC_MEM_BLOCK_ANY(unit, ENDPOINT_QUEUE_MAPm); 2452 sblk = SOC_BLOCK2SCH(unit, blk); 2453 2454 /* Check if entry exists */ 2455 for (slot = slot_min; slot <= slot_max; slot++) { 2456 if (dual && (slot == 4)) { 2457 bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, 2458 TRUE); 2459 } 2460 index = bucket * 8 + slot; 2461 addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index, 2462 &acc_type); 2463 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp); 2464 if (soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf)) { 2465 if (soc_mem_compare_key(unit, ENDPOINT_QUEUE_MAPm, entry, tmp) 2466 == 0) { 2467 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2468 (BSL_META_U(unit, 2469 "found sblk %d acc_type %d bucket %d, " 2470 "slot %d, index %d\n"), 2471 sblk, acc_type, bucket, slot, index)); 2472 2473 /* Copy entry immediately after response word */ 2474 memcpy(&result[1], tmp, 2475 soc_mem_entry_bytes(unit, ENDPOINT_QUEUE_MAPm)); 2476 2477 result[0] = 0; 2478 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND; 2479 genresp_v2->index = index; 2480 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 2481 2482 return 0; 2483 } 2484 } 2485 } 2486 2487 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2488 (BSL_META_U(unit, 2489 "soc_internal_endpoint_queue_map_lkup: Not found\n"))); 2490 2491 result[0] = 0; 2492 genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 2493 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 2494 2495 return 0; 2496 } 2497 2498 #endif /* BCM_TRIDENT2_SUPPORT */ 2499 #endif /* BCM_TRX_SUPPORT */