mem.c (1190116B)
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 * SOC Memory (Table) Utilities 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <soc/mem.h> 14 #include <soc/cmic.h> 15 #include <soc/error.h> 16 #include <soc/register.h> 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <soc/enet.h> 20 #include <soc/hash.h> 21 #include <soc/l2x.h> 22 #include <soc/l3x.h> 23 #include <soc/lpm.h> 24 #include <soc/vlan.h> 25 #include <shared/fabric.h> 26 #ifdef BCM_CMICM_SUPPORT 27 #include <soc/cmicm.h> 28 #endif 29 #ifdef BCM_CMICX_SUPPORT 30 #include <soc/fifodma.h> 31 #endif 32 #ifdef BCM_SBUSDMA_SUPPORT 33 #include <soc/sbusdma.h> 34 #endif 35 #ifdef BCM_TRIUMPH3_SUPPORT 36 #include <soc/ism.h> 37 #include <soc/ism_hash.h> 38 #include <soc/triumph3.h> 39 #endif /* BCM_TRIUMPH3_SUPPORT */ 40 #if defined(BCM_HERCULES_SUPPORT) 41 #include <soc/hercules.h> 42 #endif 43 #if defined(BCM_TRIUMPH_SUPPORT) 44 #include <soc/triumph.h> 45 #include <soc/er_tcam.h> 46 #endif /* BCM_TRIUMPH_SUPPORT */ 47 #if defined(BCM_TRIUMPH2_SUPPORT) 48 #include <soc/triumph2.h> 49 #include <sal/core/dpc.h> 50 #endif /* BCM_TRIUMPH_SUPPORT */ 51 #if defined(BCM_TRIDENT_SUPPORT) 52 #include <soc/trident.h> 53 #endif /* BCM_TRIDENT_SUPPORT */ 54 #if defined(BCM_TRIDENT2_SUPPORT) 55 #include <soc/trident2.h> 56 #endif /* BCM_TRIDENT2_SUPPORT */ 57 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT) 58 #include <soc/katana.h> 59 #endif /* BCM_KATANA_SUPPORT */ 60 #if defined(BCM_HURRICANE2_SUPPORT) 61 #include <soc/hurricane2.h> 62 #endif /* BCM_HURRICANE2_SUPPORT */ 63 #if defined(BCM_ENDURO_SUPPORT) 64 #include <soc/enduro.h> 65 #endif /* BCM_ENDURO_SUPPORT */ 66 #if defined(BCM_MONTEREY_SUPPORT) 67 #include <soc/monterey.h> 68 #endif /* BCM_APACHE_SUPPORT */ 69 #if defined(BCM_APACHE_SUPPORT) 70 #include <soc/apache.h> 71 #endif /* BCM_APACHE_SUPPORT */ 72 #if defined(BCM_TOMAHAWK_SUPPORT) 73 #include <soc/tomahawk.h> 74 #endif /* BCM_TOMAHAWK_SUPPORT */ 75 #if defined(BCM_TOMAHAWK3_SUPPORT) 76 #include <soc/tomahawk3.h> 77 #endif /* BCM_TOMAHAWK3_SUPPORT */ 78 #if defined(BCM_TRIDENT3_SUPPORT) 79 #include <soc/trident3.h> 80 #endif /* BCM_TRIDENT3_SUPPORT */ 81 #if defined(BCM_HELIX5_SUPPORT) 82 #include <soc/helix5.h> 83 #endif /* BCM_HELIX5_SUPPORT */ 84 #if defined(BCM_PETRA_SUPPORT) 85 #include <soc/dpp/drv.h> 86 #endif /* BCM_PETRA_SUPPORT */ 87 #if defined(BCM_DFE_SUPPORT) 88 #include <soc/dfe/cmn/dfe_drv.h> 89 #endif /* BCM_DFE_SUPPORT */ 90 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 91 #include <soc/dcmn/dcmn_mem.h> 92 #endif 93 #ifdef BCM_PETRA_SUPPORT 94 #include <soc/dpp/drv.h> 95 #endif 96 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 97 #include <soc/sand/sand_mem.h> 98 #endif 99 #if defined(BCM_GREYHOUND_SUPPORT) 100 #include <soc/greyhound.h> 101 #endif /* BCM_GREYHOUND_SUPPORT */ 102 #if defined(BCM_KATANA2_SUPPORT) 103 #include <soc/katana2.h> 104 #endif /* BCM_KATANA2_SUPPORT */ 105 #if defined(BCM_SABER2_SUPPORT) 106 #include <soc/saber2.h> 107 #endif /* BCM_SABER2_SUPPORT */ 108 #if defined(BCM_HURRICANE3_SUPPORT) 109 #include <soc/hurricane3.h> 110 #endif /* BCM_HURRICANE3_SUPPORT */ 111 #if defined(BCM_GREYHOUND2_SUPPORT) 112 #include <soc/greyhound2.h> 113 #endif /* BCM_GREYHOUND2_SUPPORT */ 114 #include <soc/drv.h> 115 116 #ifdef CRASH_RECOVERY_SUPPORT 117 #include <soc/hwstate/hw_log.h> 118 #include <soc/dcmn/dcmn_crash_recovery.h> 119 #endif /* CRASH_RECOVERY_SUPPORT */ 120 121 #if defined(ALPM_ENABLE) 122 #include <soc/alpm.h> 123 #include <soc/esw/alpm_int.h> 124 #endif 125 126 #ifdef BCM_TRIDENT3_SUPPORT 127 #include <soc/esw/flow_db.h> 128 #endif 129 130 #ifdef BCM_SAND_SUPPORT 131 #include <soc/sand/sand_aux_access.h> 132 #endif 133 #ifdef BCM_DNX_SUPPORT 134 #include <soc/dnx/legacy/drv.h> 135 #endif 136 #include <soc/dnxc/multithread_analyzer.h> 137 138 #define LPM_INDEX_4K_ENTRIES 4096 139 #define LPM_INDEX_2K_ENTRIES 2048 140 #define LPM_INDEX_1K_ENTRIES 1024 141 142 #ifdef BCM_WARM_BOOT_SUPPORT 143 #define SOC_DEFIP_WARMBOOT_VERSION_1 SOC_SCACHE_VERSION(1,1) 144 #define SOC_DEFIP_WARMBOOT_DEFAULT_VERSION SOC_DEFIP_WARMBOOT_VERSION_1 145 #define SOC_OVERLAY_TCAM_WARMBOOT_VERSION_1 SOC_SCACHE_VERSION(1,1) 146 #define SOC_OVERLAY_TCAM_WARMBOOT_DEFAULT_VERSION \ 147 SOC_OVERLAY_TCAM_WARMBOOT_VERSION_1 148 #endif 149 150 #ifdef USE_VALGRIND_CLIENT_REQUESTS 151 #include "memcheck/memcheck.h" 152 #endif /* USE_VALGRIND_CLIENT_REQUESTS */ 153 154 #define KATANA_L2X_VIEW_ARRAY_MAX_INDEX 4 155 #define KATANA2_L2X_VIEW_ARRAY_MAX_INDEX 6 156 #define TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX 10 157 #define TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX 10 158 #define TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX 9 159 160 #ifdef BCM_PETRA_SUPPORT 161 /* read or write wide memory, supports ARAD only */ 162 int _soc_arad_mem_array_wide_access(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, int copyno, int index, void *entry_data, 163 unsigned operation) ;/* operation should be 1 for read and 0 for write */ 164 #endif 165 166 /* 167 * This function pointer must be initialized by the application. 168 * For the standard SDK this is done in diag_shell(), and 169 * the function will point to sal_config_set() by default. 170 */ 171 int (*soc_mem_config_set)(char *name, char *value); 172 173 #if defined(BCM_PETRA_SUPPORT) 174 uint32 _soc_mem_entry_multicast_null[SOC_MAX_MEM_WORDS] = {0x7fffffff, 0}; 175 uint32 _soc_mem_entry_jer_mcdb_null[SOC_MAX_MEM_WORDS] = {0xffffffff, 3}; 176 uint32 _soc_mem_entry_llr_llvp_null[SOC_MAX_MEM_WORDS] = {0x90}; 177 #endif /* BCM_PETRA_SUPPORT */ 178 179 #if defined(BCM_ESW_SUPPORT) || \ 180 defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) 181 182 /* extra delay for quickturn */ 183 uint32 soc_mem_fifo_delay_value = 15 * MILLISECOND_USEC; 184 185 #define _SOC_ENTRY_VALID_CHECK(unit, mem, valid_field) \ 186 if (SOC_MEM_FIELD_VALID(unit, mem, valid_field)) { \ 187 if (!soc_mem_field32_get(unit, mem, entry_data, valid_field)) { \ 188 return; \ 189 } \ 190 } 191 192 #define _SOC_ENTRY_PARITY_CLEAR(unit, mem, ecc_field) \ 193 if (SOC_MEM_FIELD_VALID(unit, mem, ecc_field)) { \ 194 soc_mem_field32_set(unit, mem, entry_data, ecc_field, 0); \ 195 soc_mem_field32_set(unit, mem, entry_data_cache, ecc_field, 0); \ 196 } 197 198 /* 199 * Empty (null) table entries 200 */ 201 uint32 _soc_mem_entry_null_zeroes[SOC_MAX_MEM_WORDS]; 202 /* First word f's, rest 0's */ 203 uint32 _soc_mem_entry_null_word0[SOC_MAX_MEM_WORDS] = { ~0, 0 }; 204 205 #define SOC_MEM_COMPARE_RETURN(a, b) { \ 206 if ((a) < (b)) { return -1; } \ 207 if ((a) > (b)) { return 1; } \ 208 } 209 #define CMIC_B0_DMA_READ_COMMAND (0x7) 210 #define CMIC_B0_DMA_WRITE_COMMAND (0x9) 211 212 #define _SOC_MEM_CHK_L2_MEM(mem) \ 213 (mem == L2Xm || mem == L2_ENTRY_1m || mem == L2_ENTRY_2m) 214 #define _SOC_MEM_CHK_L3_MEM(mem) \ 215 (mem == L3_ENTRY_ONLYm || mem == L3_ENTRY_IPV4_UNICASTm || \ 216 mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm || \ 217 mem == L3_ENTRY_IPV6_MULTICASTm || mem == L3_ENTRY_1m || \ 218 mem == L3_ENTRY_SINGLEm || mem == L3_ENTRY_DOUBLEm || mem == L3_ENTRY_QUADm || \ 219 mem == L3_ENTRY_2m || mem == L3_ENTRY_4m) 220 221 #if defined(BCM_TOMAHAWK_SUPPORT) 222 #define _SOC_MEM_CHK_FPEM_MEM(mem) \ 223 (mem == EXACT_MATCH_2m || \ 224 mem == EXACT_MATCH_2_PIPE0m || mem == EXACT_MATCH_2_PIPE1m || \ 225 mem == EXACT_MATCH_2_PIPE2m || mem == EXACT_MATCH_2_PIPE3m || \ 226 mem == EXACT_MATCH_4m || \ 227 mem == EXACT_MATCH_4_PIPE0m || mem == EXACT_MATCH_4_PIPE1m || \ 228 mem == EXACT_MATCH_4_PIPE2m || mem == EXACT_MATCH_4_PIPE3m) 229 #define _SOC_MEM_CHK_IFP_TCAM(mem) \ 230 (mem == IFP_TCAMm || \ 231 mem == IFP_TCAM_PIPE0m || mem == IFP_TCAM_PIPE1m || \ 232 mem == IFP_TCAM_PIPE2m || mem == IFP_TCAM_PIPE3m) 233 #define _SOC_MEM_CHK_IFP_TCAM_WIDE(mem) \ 234 (mem == IFP_TCAM_WIDEm || \ 235 mem == IFP_TCAM_WIDE_PIPE0m || mem == IFP_TCAM_WIDE_PIPE1m || \ 236 mem == IFP_TCAM_WIDE_PIPE2m || mem == IFP_TCAM_WIDE_PIPE3m) 237 #endif /* BCM_TOMAHAWK_SUPPORT */ 238 239 #define _SOC_MEM_CHK_EGR_IP_TUNNEL(mem) \ 240 (mem == EGR_IP_TUNNELm || mem == EGR_IP_TUNNEL_MPLSm || \ 241 mem == EGR_IP_TUNNEL_IPV6m) 242 #define _SOC_MEM_CHK_MPLS_MEM(mem) \ 243 (mem == MPLS_ENTRYm || mem == MPLS_ENTRY_1m || mem == MPLS_ENTRY_EXTDm) 244 #ifdef BCM_TRIDENT3_SUPPORT 245 #define _SOC_MEM_CHK_VLAN_XLATE(mem) \ 246 (mem == VLAN_XLATE_1_SINGLEm || mem == VLAN_XLATE_1_DOUBLEm || \ 247 mem == VLAN_XLATE_2_SINGLEm || mem == VLAN_XLATE_2_DOUBLEm) 248 #endif 249 /* Macro to swap name to the mapped-to (actually-used) mem state name */ 250 #define _SOC_MEM_REUSE_MEM_STATE(unit, mem) {\ 251 switch(mem) {\ 252 case VLAN_XLATE_1m: mem = VLAN_XLATEm; break;\ 253 case EP_VLAN_XLATE_1m: mem = EGR_VLAN_XLATEm; break;\ 254 case MPLS_ENTRY_1m: mem = MPLS_ENTRYm; break;\ 255 case VLAN_MACm: \ 256 if (SOC_IS_TRX(unit) && !soc_feature(unit, soc_feature_ism_memory)) {\ 257 mem = VLAN_XLATEm;\ 258 }\ 259 break;\ 260 case EGR_VLANm: \ 261 if (SOC_IS_KATANA2(unit)) {\ 262 mem = VLAN_TABm;\ 263 }\ 264 break;\ 265 default: break;\ 266 }\ 267 } 268 #define _SOC_MEM_SKIP_READING_MEM_TO_CACHE(unit, mem, skip) {\ 269 soc_mem_t skip_mem = mem;\ 270 skip = (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CACHABLE)? 0 : 1;\ 271 switch(mem) {\ 272 case RH_HGT_FLOWSETm:\ 273 case DLB_HGT_FLOWSETm:\ 274 case RH_HGT_FLOWSET_PIPE0m:\ 275 case RH_HGT_FLOWSET_PIPE1m:\ 276 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)) &&\ 277 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {\ 278 uint32 is_rh_hgt = 0;\ 279 uint32 rval;\ 280 READ_ENHANCED_HASHING_CONTROLr(unit, &rval);\ 281 is_rh_hgt = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, rval,\ 282 RH_HGT_ENABLEf);\ 283 skip_mem = (is_rh_hgt == 1)? DLB_HGT_FLOWSETm : RH_HGT_FLOWSETm;\ 284 skip = (skip_mem == mem)?1:0;\ 285 }\ 286 if (SOC_IS_TRIDENT3X(unit) &&\ 287 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROL_2r)) {\ 288 uint32 is_rh_dlb = 0;\ 289 uint32 is_hgt_lag = 0;\ 290 uint32 rval;\ 291 READ_ENHANCED_HASHING_CONTROL_2r(unit, &rval);\ 292 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\ 293 RH_DLB_SELECTIONf);\ 294 is_hgt_lag = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\ 295 HGT_LAG_FLOWSET_TABLE_CONFIGf);\ 296 skip = (is_rh_dlb == 0)? 1 :((is_hgt_lag == 0)? 1 : 0);\ 297 }\ 298 break;\ 299 case RH_LAG_FLOWSETm:\ 300 case RH_LAG_FLOWSET_PIPE0m:\ 301 case RH_LAG_FLOWSET_PIPE1m:\ 302 if (SOC_IS_TRIDENT3X(unit) &&\ 303 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROL_2r)) {\ 304 uint32 is_rh_dlb = 0;\ 305 uint32 is_hgt_lag = 0;\ 306 uint32 rval;\ 307 READ_ENHANCED_HASHING_CONTROL_2r(unit, &rval);\ 308 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\ 309 RH_DLB_SELECTIONf);\ 310 is_hgt_lag = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\ 311 HGT_LAG_FLOWSET_TABLE_CONFIGf);\ 312 skip = (is_rh_dlb == 0)? 1 :((is_hgt_lag == 1)? 1 : 0);\ 313 }\ 314 break;\ 315 case DLB_HGT_LAG_FLOWSETm:\ 316 case DLB_HGT_LAG_FLOWSET_PIPE0m:\ 317 case DLB_HGT_LAG_FLOWSET_PIPE1m:\ 318 if (SOC_IS_TRIDENT3X(unit) &&\ 319 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROL_2r)) {\ 320 uint32 is_rh_dlb = 0;\ 321 uint32 rval;\ 322 READ_ENHANCED_HASHING_CONTROL_2r(unit, &rval);\ 323 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\ 324 RH_DLB_SELECTIONf);\ 325 skip = (is_rh_dlb == 1)? 1 : 0;\ 326 }\ 327 break;\ 328 case RH_ECMP_FLOWSETm:\ 329 case RH_ECMP_FLOWSET_PIPE0m:\ 330 case RH_ECMP_FLOWSET_PIPE1m:\ 331 if (SOC_IS_TRIDENT3X(unit) &&\ 332 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {\ 333 uint32 is_rh_dlb = 0;\ 334 uint32 rval;\ 335 READ_ENHANCED_HASHING_CONTROLr(unit, &rval);\ 336 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, rval,\ 337 RH_DLB_SELECTIONf);\ 338 skip = (is_rh_dlb == 1)? 0 : 1;\ 339 }\ 340 break;\ 341 case DLB_ECMP_FLOWSETm:\ 342 case DLB_ECMP_FLOWSET_PIPE0m:\ 343 case DLB_ECMP_FLOWSET_PIPE1m:\ 344 case DLB_ECMP_FLOWSET_MEMBER_PIPE0m:\ 345 case DLB_ECMP_FLOWSET_MEMBER_PIPE1m:\ 346 case DLB_ECMP_FLOWSET_MEMBERm:\ 347 if (SOC_IS_TRIDENT3X(unit) &&\ 348 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {\ 349 uint32 is_rh_dlb = 0;\ 350 uint32 rval;\ 351 READ_ENHANCED_HASHING_CONTROLr(unit, &rval);\ 352 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, rval,\ 353 RH_DLB_SELECTIONf);\ 354 skip = (is_rh_dlb == 1)? 1 : 0;\ 355 }\ 356 break;\ 357 default:\ 358 break;\ 359 }\ 360 } 361 362 #ifdef BROADCOM_DEBUG 363 static uint32 _soc_dma_debug_enable[SOC_MAX_NUM_DEVICES] = {0}; 364 static uint32 _soc_dma_debug_op[SOC_MAX_NUM_DEVICES] = {0}; 365 #endif /* BROADCOM_DEBUG */ 366 367 /* Structure for hash bank info stored during each hash move */ 368 typedef struct _soc_hash_bank_info_s { 369 int num_banks; 370 int bank_nums[11]; 371 int banks; 372 uint32 numb; 373 } _soc_hash_bank_info_t; 374 375 #if defined(BCM_GREYHOUND2_SUPPORT) 376 STATIC int soc_mem_gh2_l2_sw_lookup( 377 int unit, 378 soc_mem_t mem, 379 int copyno, 380 int32 banks, 381 void *key, 382 void *result, 383 int *index_ptr); 384 #endif /* BCM_GREYHOUND2_SUPPORT */ 385 386 387 388 #ifdef BCM_SAND_SUPPORT 389 STATIC int _soc_mem_array_wide_read( 390 int unit, 391 uint32 flags, 392 soc_mem_t mem, 393 unsigned array_index, 394 int copyno, 395 int index, 396 void *entry_data) 397 { 398 int rv = SOC_E_UNAVAIL; 399 400 #ifdef BCM_PETRA_SUPPORT 401 if (SOC_IS_DPP(unit)) 402 { 403 if (SOC_IS_ARADPLUS_AND_BELOW(unit)) 404 { 405 SOC_DPP_ALLOW_WARMBOOT_WRITE(_soc_arad_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1), rv); 406 return rv; 407 } 408 else 409 { 410 SOC_DPP_ALLOW_WARMBOOT_WRITE(dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1), rv); 411 return rv; 412 } 413 } 414 #endif 415 416 #ifdef BCM_DFE_SUPPORT 417 if(SOC_IS_FE3200(unit)) 418 { 419 rv = dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1); 420 return rv; 421 } 422 #endif 423 424 #ifdef BCM_DNX_SUPPORT 425 if (SOC_IS_DNX(unit)) 426 { 427 SOC_DNX_ALLOW_WARMBOOT_WRITE(sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1), rv); 428 return rv; 429 } 430 #endif 431 432 #ifdef BCM_DNXF_SUPPORT 433 if (SOC_IS_DNXF(unit)) 434 { 435 rv = sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1); 436 return rv; 437 } 438 #endif 439 440 441 return rv; 442 } 443 444 445 446 STATIC int _soc_mem_array_wide_write( 447 int unit, 448 uint32 flags, 449 soc_mem_t mem, 450 unsigned array_index, 451 int copyno, 452 int index, 453 void *entry_data) 454 { 455 int rv = SOC_E_UNAVAIL;; 456 457 #ifdef BCM_PETRA_SUPPORT 458 if(SOC_IS_DPP(unit)) 459 { 460 if (SOC_IS_ARADPLUS_AND_BELOW(unit)) 461 { 462 SOC_DPP_ALLOW_WARMBOOT_WRITE(_soc_arad_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0), rv); 463 return rv; 464 } 465 else 466 { 467 SOC_DPP_ALLOW_WARMBOOT_WRITE(dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0), rv); 468 return rv; 469 } 470 } 471 #endif 472 473 #ifdef BCM_DFE_SUPPORT 474 if (SOC_IS_FE3200(unit)) 475 { 476 rv = dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0); 477 return rv; 478 } 479 #endif 480 481 #ifdef BCM_DNX_SUPPORT 482 if (SOC_IS_DNX(unit)) 483 { 484 SOC_DNX_ALLOW_WARMBOOT_WRITE(sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0), rv); 485 return rv; 486 } 487 #endif 488 489 #ifdef BCM_DNXF_SUPPORT 490 if (SOC_IS_DNXF(unit)) 491 { 492 rv = sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0); 493 return rv; 494 } 495 #endif 496 497 return rv; 498 } 499 500 #endif 501 502 503 504 #ifdef BCM_TRIDENT3_SUPPORT 505 /* 506 * Function: soc_mem_view_index_max 507 * Purpose: Find the max index (address range) in this memory view 508 * Parameters: 509 * unit - (IN) SOC unit number. 510 * mem - (IN) Memory view 511 * Returns: 512 * Returns the max index of this memory view 513 * Note: 514 * Parameter mem_view must be valid before calling this function 515 */ 516 int soc_mem_view_index_max(int unit, soc_mem_t mem_view) 517 { 518 soc_mem_t phy_mem = 0; 519 int index; 520 521 if (soc_feature(unit, soc_feature_flex_flow) && SOC_MEM_IS_VIEW(unit, mem_view)) { 522 (void)soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem); 523 index = (SOC_PERSIST(unit) ? SOP_MEM_STATE(unit, phy_mem).index_max : SOC_MEM_INFO(unit, phy_mem).index_max); 524 } else { 525 index = (SOC_PERSIST(unit) ? SOP_MEM_STATE(unit, mem_view).index_max : SOC_MEM_INFO(unit, mem_view).index_max); 526 } 527 return index; 528 } 529 530 /* 531 * Function: soc_mem_view_index_min 532 * Purpose: Find the min index (address range) in this memory view 533 * Parameters: 534 * unit - (IN) SOC unit number. 535 * mem - (IN) Memory view 536 * Returns: 537 * Returns the min index of this memory view 538 * Note: 539 * Parameter mem_view must be valid before calling this function 540 */ 541 int soc_mem_view_index_min(int unit, soc_mem_t mem_view) 542 { 543 soc_mem_t phy_mem = 0; 544 int index; 545 546 if (soc_feature(unit, soc_feature_flex_flow) && SOC_MEM_IS_VIEW(unit, mem_view)) { 547 (void)soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem); 548 index = SOC_MEM_INFO(unit, phy_mem).index_min; 549 } else { 550 index = SOC_MEM_INFO(unit, mem_view).index_min; 551 } 552 return index; 553 } 554 555 /* 556 * Function: soc_mem_view_index_count 557 * Purpose: Count the number of indexes (address range) in this memory view 558 * Parameters: 559 * unit - (IN) SOC unit number. 560 * mem - (IN) Memory view 561 * Returns: 562 * Count of number of memory indexes 563 * Note: 564 * Parameter mem_view must be valid before calling this function 565 */ 566 int soc_mem_view_index_count(int unit, soc_mem_t mem_view) 567 { 568 soc_mem_t phy_mem = 0; 569 int count; 570 571 if (soc_feature(unit, soc_feature_flex_flow) && SOC_MEM_IS_VIEW(unit, mem_view)) { 572 (void)soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem); 573 count = (soc_mem_index_max(unit, phy_mem) - soc_mem_index_min(unit, phy_mem) + 1); 574 } else { 575 count = (soc_mem_index_max(unit, mem_view) - soc_mem_index_min(unit, mem_view) + 1); 576 } 577 return count; 578 } 579 580 /* 581 * Function: 582 * soc_mem_view_entry_dump_common 583 * Purpose: 584 * Debug routine to dump a formatted table entry for memory views 585 * 586 * Note: Prefix != NULL : Dump chg command 587 * Prefix == NULL : Dump command 588 * (Actually should pass dump_chg flag but keeping for simplicity) 589 */ 590 STATIC void 591 _soc_mem_view_entry_dump_common(int unit, soc_mem_t mem_view_id, void *buf, char *prefix, int vertical, uint32 bsl_flags) 592 { 593 int i; 594 int rv; 595 uint32 field_id[100]; 596 uint32 cnt; 597 int field_type; 598 char dummy[]=""; 599 char *mem_prefix=dummy; 600 int first_print_flag=0; 601 602 #if !defined(SOC_NO_NAMES) 603 soc_flow_db_mem_view_field_info_t ff_info; 604 char *field_name; 605 uint32 *fval; 606 uint32 *nfval; 607 char *tmp; 608 uint32 *buf_ptr; 609 int alloc_size; 610 #endif 611 612 613 if (prefix != NULL) { 614 mem_prefix = prefix; 615 } 616 617 #if !defined(SOC_NO_NAMES) 618 alloc_size = (2*SOC_MAX_MEM_FIELD_WORDS) * sizeof(uint32) + 619 (SOC_MAX_MEM_FIELD_WORDS * 8) + 3; 620 buf_ptr = sal_alloc(alloc_size, "Temp. buffer for soc mem dump"); 621 sal_memset((void *)buf_ptr,0,alloc_size); 622 fval = buf_ptr; 623 nfval = buf_ptr + SOC_MAX_MEM_FIELD_WORDS; 624 tmp = (char *)(buf_ptr + 2 * SOC_MAX_MEM_FIELD_WORDS); 625 #endif 626 627 for (field_type = SOC_FLOW_DB_FIELD_TYPE_CONTROL; 628 field_type < SOC_FLOW_DB_FIELD_TYPE_MAX; field_type++) { 629 rv = soc_flow_db_mem_view_field_list_get(unit, mem_view_id, field_type, 100, field_id, &cnt); 630 if (SOC_SUCCESS(rv)) { 631 for (i = 0; i < cnt; i++) { 632 #if !defined(SOC_NO_NAMES) 633 sal_memset(fval, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 634 soc_mem_field_get(unit, mem_view_id, buf, field_id[i], fval); 635 636 if (mem_prefix == prefix) { 637 if (sal_memcmp(fval, nfval, SOC_MAX_MEM_FIELD_WORDS * 638 sizeof (uint32)) == 0) { 639 continue; 640 } 641 } 642 (void) soc_flow_db_mem_view_field_info_get(unit, mem_view_id, 643 field_id[i], &ff_info); 644 _shr_format_long_integer(tmp, fval, BITS2BYTES(ff_info.width)); 645 if (first_print_flag == 0) { 646 BSL_LOG(bsl_flags, (BSL_META_U(unit, "%s%s"), mem_prefix, "<")); 647 first_print_flag = 1; 648 } 649 if (field_type == SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY || 650 field_type == SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA || 651 field_type == SOC_FLOW_DB_FIELD_TYPE_DATA_FRAGMENT) { 652 (void) soc_flow_db_mem_view_field_name_get(unit, mem_view_id, 653 field_id[i], &field_name); 654 } 655 else { 656 field_name = soc_fieldnames[field_id[i]]; 657 } 658 if (vertical) { 659 BSL_LOG(bsl_flags, (BSL_META_U(unit, 660 "\n\t%30s: %s"), field_name, 661 tmp)); 662 } else { 663 BSL_LOG(bsl_flags, (BSL_META_U(unit, 664 "%s=%s%s"), field_name, 665 tmp, ",")); 666 } 667 #endif 668 } 669 } 670 } 671 #if !defined(SOC_NO_NAMES) 672 sal_free(buf_ptr); 673 #endif 674 675 if (first_print_flag == 1) { 676 BSL_LOG(bsl_flags, (BSL_META_U(unit, 677 "%s\n"), vertical ? "" : ">")); 678 } 679 } 680 #endif 681 682 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE 683 /* For JR2 emulator, not all memory exist */ 684 STATIC int _soc_jr2_is_2nd_core(int unit, soc_mem_t mem, int copyno) 685 { 686 uint32 block_type = SOC_BLOCK_TYPE(unit, SOC_MEM_BLOCK_ANY(unit, mem)); 687 688 if (copyno < 0) { 689 return 0; 690 } 691 692 switch(block_type) { 693 #ifdef JR2_REMOVE_ACCESS_TO_UNSUPPORTED_BLOCKS 694 case SOC_BLK_FSRD: 695 if (copyno > 2) { 696 return 1; 697 } 698 break; 699 case SOC_BLK_FMAC: 700 if (copyno > 5) { 701 return 1; 702 } 703 break; 704 case SOC_BLK_CDU: 705 if (copyno > 4) { 706 return 1; 707 } 708 break; 709 case SOC_BLK_CDMAC: 710 if (copyno > 11) { 711 return 1; 712 } 713 break; 714 case SOC_BLK_CDPORT: 715 if (copyno > 5) { 716 return 1; 717 } 718 break; 719 case SOC_BLK_DDHA: 720 case SOC_BLK_DDHB: 721 case SOC_BLK_MDB: 722 #endif /* JR2_REMOVE_ACCESS_TO_UNSUPPORTED_BLOCKS */ 723 case SOC_BLK_KAPS: 724 case SOC_BLK_IPPA: 725 case SOC_BLK_IPPB: 726 case SOC_BLK_IPPC: 727 case SOC_BLK_IPPD: 728 case SOC_BLK_IPPE: 729 case SOC_BLK_IPPF: 730 case SOC_BLK_CDUM: 731 case SOC_BLK_MACT: 732 case SOC_BLK_TCAM: 733 case SOC_BLK_IQM: 734 case SOC_BLK_ITPPD: 735 case SOC_BLK_ITPP: 736 case SOC_BLK_ETPPA: 737 case SOC_BLK_ETPPB: 738 case SOC_BLK_ETPPC: 739 case SOC_BLK_ERPP: 740 case SOC_BLK_EDB: 741 case SOC_BLK_DQM: 742 case SOC_BLK_CRPS: 743 case SOC_BLK_MRPS: 744 case SOC_BLK_EGQ: 745 case SOC_BLK_EPNI: 746 case SOC_BLK_EPRE: 747 case SOC_BLK_ECGM: 748 case SOC_BLK_CGM: 749 case SOC_BLK_FDR: 750 case SOC_BLK_IDB: 751 case SOC_BLK_MCP: 752 case SOC_BLK_OCB: 753 case SOC_BLK_ILE: 754 case SOC_BLK_SCH: 755 case SOC_BLK_IPT: 756 case SOC_BLK_IPS: 757 case SOC_BLK_IRE: 758 case SOC_BLK_NMG: 759 case SOC_BLK_EPS: 760 case SOC_BLK_FQP: 761 case SOC_BLK_RQP: 762 case SOC_BLK_PQP: 763 case SOC_BLK_SQM: 764 case SOC_BLK_SPB: 765 case SOC_BLK_DDP: 766 case SOC_BLK_PDM: 767 case SOC_BLK_BDM: 768 case SOC_BLK_SIF: 769 if (SOC_BLOCK_NUMBER(unit, copyno) > 0) { 770 return 1; 771 } 772 break; 773 case SOC_BLK_PEM: 774 if (SOC_BLOCK_NUMBER(unit, copyno) >= 4) { 775 return 1; 776 } 777 break; 778 default: 779 break; 780 } 781 782 return 0; 783 } 784 #endif /* defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE */ 785 786 /* Check a mem has mapped-to (actually-used) mem state name or not */ 787 int soc_mem_is_mapped_mem(int unit, soc_mem_t mem) 788 { 789 soc_mem_t mapped_mem = mem; 790 791 _SOC_MEM_REUSE_MEM_STATE(unit, mapped_mem); 792 793 if(mapped_mem == mem) { 794 return FALSE; 795 } else { 796 return TRUE; 797 } 798 799 } 800 /* Two memory share same physical memory space, but they can't exist at the same time */ 801 int soc_mem_is_shared_mem(int unit, soc_mem_t mem) 802 { 803 int skip = 0; 804 805 switch(mem) { 806 case DLB_HGT_FLOWSETm: 807 case DLB_HGT_FLOWSET_Xm: 808 case DLB_HGT_FLOWSET_Ym: 809 mem = DLB_HGT_FLOWSETm; 810 break; 811 case DLB_ECMP_FLOWSET_MEMBERm: 812 case DLB_ECMP_FLOWSET_MEMBER_PIPE0m: 813 case DLB_ECMP_FLOWSET_MEMBER_PIPE1m: 814 mem = DLB_ECMP_FLOWSET_MEMBERm; 815 break; 816 default: 817 break; 818 } 819 _SOC_MEM_SKIP_READING_MEM_TO_CACHE(unit, mem, skip); 820 if (skip == 1) { 821 return TRUE; 822 } else { 823 return FALSE; 824 } 825 } 826 827 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 828 int 829 soc_mem_is_cache_only(int unit, soc_mem_t mem) 830 { 831 832 if (soc_feature(unit, soc_feature_l3_ecmp_protected_access)) { 833 switch (mem) { 834 case L3_ECMPm: 835 case INITIAL_L3_ECMPm: 836 case L3_ECMP_COUNTm: 837 case INITIAL_L3_ECMP_GROUPm: 838 return TRUE; 839 default: 840 return FALSE; 841 } 842 } 843 844 return FALSE; 845 } 846 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 847 848 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 849 /* get the soc broadcast block from a block type */ 850 int soc_broadcast_block_get_from_type (int unit, int block_type) { 851 switch (block_type) { 852 case SOC_BLK_EGQ: 853 return SOC_INFO(unit).brdc_egq_block; 854 case SOC_BLK_IHB: 855 return SOC_INFO(unit).brdc_ihb_block; 856 case SOC_BLK_IHP: 857 return SOC_INFO(unit).brdc_ihp_block; 858 case SOC_BLK_IPS: 859 return SOC_INFO(unit).brdc_ips_block; 860 case SOC_BLK_IQM: 861 return SOC_INFO(unit).brdc_iqm_block; 862 case SOC_BLK_CGM: 863 return SOC_INFO(unit).brdc_cgm_block; 864 case SOC_BLK_SCH: 865 return SOC_INFO(unit).brdc_sch_block; 866 case SOC_BLK_EPNI: 867 return SOC_INFO(unit).brdc_epni_block; 868 case SOC_BLK_MRPS: 869 return SOC_INFO(unit).brdc_mrps_block; 870 case SOC_BLK_MTRPS_EM: 871 return SOC_INFO(unit).brdc_mtrps_em_block; 872 case SOC_BLK_IPSEC_SPU_WRAPPER_TOP: 873 return SOC_INFO(unit).brdc_ipsec_spu_wrapper_top_block; 874 case SOC_BLK_KAPS_BBS: 875 return SOC_INFO(unit).brdc_kaps_bbs_block; 876 877 default: 878 return 0; 879 } 880 } 881 882 /* get the soc broadcast block from of a memory */ 883 int soc_mem_broadcast_block_get(int unit, soc_mem_t mem){ 884 switch (SOC_BLOCK_TYPE(unit, SOC_MEM_BLOCK_ANY(unit, mem))) { 885 case SOC_BLK_EGQ: 886 return SOC_INFO(unit).brdc_egq_block; 887 case SOC_BLK_IHB: 888 return SOC_INFO(unit).brdc_ihb_block; 889 case SOC_BLK_IHP: 890 return SOC_INFO(unit).brdc_ihp_block; 891 case SOC_BLK_IPS: 892 return SOC_INFO(unit).brdc_ips_block; 893 case SOC_BLK_IQM: 894 return SOC_INFO(unit).brdc_iqm_block; 895 case SOC_BLK_CGM: 896 return SOC_INFO(unit).brdc_cgm_block; 897 case SOC_BLK_SCH: 898 return SOC_INFO(unit).brdc_sch_block; 899 case SOC_BLK_EPNI: 900 return SOC_INFO(unit).brdc_epni_block; 901 case SOC_BLK_MRPS: 902 return SOC_INFO(unit).brdc_mrps_block; 903 case SOC_BLK_MTRPS_EM: 904 return SOC_INFO(unit).brdc_mtrps_em_block; 905 case SOC_BLK_IPSEC_SPU_WRAPPER_TOP: 906 return SOC_INFO(unit).brdc_ipsec_spu_wrapper_top_block; 907 case SOC_BLK_KAPS_BBS: 908 return SOC_INFO(unit).brdc_kaps_bbs_block; 909 910 default: 911 return 0; 912 } 913 } 914 #endif /* BCM_PETRA_SUPPORT */ 915 916 /* Routine to check if this is the mem whose state is being (mapped-to) actually-used by others */ 917 int _SOC_MEM_IS_REUSED_MEM(int unit, soc_mem_t mem) {\ 918 switch(mem) {\ 919 case EGR_VLAN_XLATEm: return TRUE;\ 920 case MPLS_ENTRYm: return TRUE;\ 921 case VLAN_XLATEm:\ 922 if (SOC_IS_TRX(unit)) {\ 923 return TRUE;\ 924 }\ 925 break;\ 926 case VLAN_TABm:\ 927 if (SOC_IS_KATANA2(unit)) {\ 928 return TRUE;\ 929 }\ 930 break;\ 931 case RH_HGT_FLOWSETm:\ 932 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {\ 933 return TRUE;\ 934 }\ 935 break;\ 936 default: break;\ 937 }\ 938 return FALSE;\ 939 } 940 941 /* Handle reverse mem state mapping updates - one to one or one to many */ 942 943 /* DLB_HGT_FLOWSETm and RH_HGT_FLOWSETm share the same physical memory table, 944 if we write physical memory table according to format of DLB_HGT_FLOWSETm, and read the physical 945 memory according to format of RH_HGT_FLOWSETm, there will be a lot of SER error!*/ 946 #define _SOC_MEM_SYNC_MAPPED_MEM_STATES(unit, mem) {\ 947 switch(mem) {\ 948 case EGR_VLAN_XLATEm: \ 949 SOC_MEM_STATE(unit, EP_VLAN_XLATE_1m).cache[blk] = cache;\ 950 SOC_MEM_STATE(unit, EP_VLAN_XLATE_1m).vmap[blk] = vmap;\ 951 break;\ 952 case MPLS_ENTRYm: \ 953 SOC_MEM_STATE(unit, MPLS_ENTRY_1m).cache[blk] = cache;\ 954 SOC_MEM_STATE(unit, MPLS_ENTRY_1m).vmap[blk] = vmap;\ 955 break;\ 956 case VLAN_XLATEm: \ 957 if (SOC_IS_TRX(unit)) {\ 958 if (soc_feature(unit, soc_feature_ism_memory)) {\ 959 SOC_MEM_STATE(unit, VLAN_XLATE_1m).cache[blk] = cache;\ 960 SOC_MEM_STATE(unit, VLAN_XLATE_1m).vmap[blk] = vmap;\ 961 } else {\ 962 SOC_MEM_STATE(unit, VLAN_MACm).cache[blk] = cache;\ 963 SOC_MEM_STATE(unit, VLAN_MACm).vmap[blk] = vmap;\ 964 }\ 965 break;\ 966 }\ 967 case VLAN_TABm: \ 968 if (SOC_IS_KATANA2(unit)) { \ 969 int blk_new; \ 970 SOC_MEM_BLOCK_ITER(unit, EGR_VLANm, blk_new) {\ 971 SOC_MEM_STATE(unit, EGR_VLANm).cache[blk_new] = cache;\ 972 SOC_MEM_STATE(unit, EGR_VLANm).vmap[blk_new] = vmap;\ 973 break;\ 974 }\ 975 }\ 976 break;\ 977 default: break;\ 978 }\ 979 } 980 #ifdef BCM_TRIUMPH3_SUPPORT 981 #define _SOC_MEM_REPLACE_MEM(unit, mem) {\ 982 if (soc_feature(unit, soc_feature_ism_memory)) {\ 983 switch(mem) {\ 984 case VLAN_XLATE_1m: mem = VLAN_XLATEm; break;\ 985 case EP_VLAN_XLATE_1m: mem = EGR_VLAN_XLATEm; break;\ 986 case MPLS_ENTRY_1m: mem = MPLS_ENTRYm; break;\ 987 default: break;\ 988 }\ 989 }\ 990 } 991 #else 992 #define _SOC_MEM_REPLACE_MEM(unit, mem) 993 #endif /* BCM_TRIUMPH3_SUPPORT */ 994 995 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_SAND_SUPPORT) 996 soc_mem_t petra_mem_alias_to_orig(int unit, soc_mem_t mem) 997 { 998 soc_mem_t alias_mem; 999 1000 alias_mem = SOC_MEM_IS_VALID(unit, SOC_MEM_ALIAS_MAP(unit,mem)) ? SOC_MEM_ALIAS_MAP(unit,mem) : mem; 1001 1002 /* special memory with same physical address but not be marked alias */ 1003 switch (SOC_INFO(unit).chip_type) 1004 { 1005 case SOC_INFO_CHIP_TYPE_QUX: 1006 { 1007 switch (mem) 1008 { 1009 case IHB_FEC_SUPER_ENTRYm: 1010 alias_mem = IHB_FEC_ENTRYm; 1011 break; 1012 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m: 1013 alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm; 1014 break; 1015 case EPNI_PP_PCTm: 1016 alias_mem = EPNI_PACKETPROCESSING_PORT_CONFIGURATION_TABLEm; 1017 break; 1018 1019 default: 1020 break; 1021 } 1022 break; 1023 } 1024 1025 case SOC_INFO_CHIP_TYPE_QAX: 1026 { 1027 switch (mem) 1028 { 1029 case IHB_FEC_SUPER_ENTRYm: 1030 alias_mem = IHB_FEC_ENTRYm; 1031 break; 1032 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m: 1033 alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm; 1034 break; 1035 default: 1036 break; 1037 } 1038 break; 1039 } 1040 1041 case SOC_INFO_CHIP_TYPE_QMX: 1042 { 1043 switch (mem) 1044 { 1045 case MRPS_MCDA_PRFCFG_SHARING_DISm: 1046 case MRPS_MCDA_PRFCFG_SHARING_ENm: 1047 alias_mem = MRPS_MCDA_PRFCFG_1m; 1048 break; 1049 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m: 1050 alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm; 1051 break; 1052 default: 1053 break; 1054 } 1055 break; 1056 } 1057 1058 case SOC_INFO_CHIP_TYPE_JERICHO: 1059 { 1060 switch (mem) 1061 { 1062 case MRPS_MCDA_PRFCFG_SHARING_DISm: 1063 case MRPS_MCDA_PRFCFG_SHARING_ENm: 1064 alias_mem = MRPS_MCDA_PRFCFG_1m; 1065 break; 1066 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m: 1067 alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm; 1068 break; 1069 default: 1070 break; 1071 } 1072 break; 1073 } 1074 1075 case SOC_INFO_CHIP_TYPE_JERICHO_PLUS: 1076 { 1077 switch (mem) 1078 { 1079 case PPDB_B_LIF_TABLE_AC_2_EEIm: 1080 case PPDB_B_LIF_TABLE_AC_2_OUT_LIFm: 1081 case PPDB_B_LIF_TABLE_AC_MPm: 1082 case PPDB_B_LIF_TABLE_IP_TTm: 1083 case PPDB_B_LIF_TABLE_ISID_MPm: 1084 case PPDB_B_LIF_TABLE_ISID_P2Pm: 1085 case PPDB_B_LIF_TABLE_LABEL_PROTOCOL_OR_LSPm: 1086 case PPDB_B_LIF_TABLE_LABEL_PWE_MPm: 1087 case PPDB_B_LIF_TABLE_LABEL_PWE_P2Pm: 1088 case PPDB_B_LIF_TABLE_TRILLm: 1089 case PPDB_B_LIF_TABLE_DOUBLE_DATAm: 1090 alias_mem = PPDB_B_LIF_TABLEm; 1091 break; 1092 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m: 1093 alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm; 1094 break; 1095 case MRPS_MCDA_PRFCFG_SHARING_DISm: 1096 case MRPS_MCDA_PRFCFG_SHARING_ENm: 1097 alias_mem = MRPS_MCDA_PRFCFG_1m; 1098 break; 1099 default: 1100 break; 1101 } 1102 break; 1103 } 1104 1105 default: 1106 break; 1107 } 1108 1109 return alias_mem; 1110 } 1111 #endif 1112 1113 #ifdef BCM_ESW_SUPPORT 1114 #define HASH_MEM_OP_RETRY_COUNT 5 1115 #endif 1116 1117 int 1118 _soc_mem_cmp_word0(int unit, void *ent_a, void *ent_b) 1119 { 1120 COMPILER_REFERENCE(unit); 1121 1122 /* 1123 * Good for l3_def_ip_entry_t and l3_l3_entry_t. 1124 * The first uint32 (IP address) is the sort key. 1125 */ 1126 1127 SOC_MEM_COMPARE_RETURN(*(uint32 *)ent_a, *(uint32 *)ent_b); 1128 1129 return 0; 1130 } 1131 1132 int 1133 _soc_mem_cmp_undef(int unit, void *ent_a, void *ent_b) 1134 { 1135 COMPILER_REFERENCE(ent_a); 1136 COMPILER_REFERENCE(ent_b); 1137 1138 LOG_CLI((BSL_META_U(unit, 1139 "soc_mem_cmp: cannot compare entries of this type\n"))); 1140 1141 assert(0); 1142 1143 return 0; 1144 } 1145 1146 int 1147 _soc_mem_cmp_subport_id_to_sgpp_map(int unit, void *ent_a, void *ent_b) 1148 { 1149 uint32 val_a, val_b; 1150 1151 val_a = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_a, SUBPORT_ID_NAMESPACEf); 1152 val_b = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_b, SUBPORT_ID_NAMESPACEf); 1153 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1154 1155 val_a = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_a, SUBPORT_IDf); 1156 val_b = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_b, SUBPORT_IDf); 1157 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1158 1159 return 0; 1160 } 1161 1162 #ifdef BCM_XGS_SWITCH_SUPPORT 1163 1164 int 1165 _soc_mem_cmp_l2x(int unit, void *ent_a, void *ent_b) 1166 { 1167 sal_mac_addr_t mac_a, mac_b; 1168 vlan_id_t vlan_a, vlan_b; 1169 1170 vlan_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf); 1171 vlan_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf); 1172 SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b); 1173 1174 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1175 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1176 1177 return ENET_CMP_MACADDR(mac_a, mac_b); 1178 } 1179 1180 int 1181 _soc_mem_cmp_l2x_sync(int unit, void *ent_a, void *ent_b, int size, uint8 hit_bits) 1182 { 1183 l2x_entry_t *l2x1 = (l2x_entry_t *)ent_a; 1184 l2x_entry_t *l2x2 = (l2x_entry_t *)ent_b; 1185 1186 /* force bits that may be updated by HW to be the same */ 1187 if (SOC_IS_XGS3_SWITCH(unit) || SOC_IS_XGS3_FABRIC(unit)) { 1188 if (!(hit_bits & L2X_SHADOW_HIT_BITS)) { 1189 if (!(hit_bits & L2X_SHADOW_HIT_DST)) { 1190 soc_L2Xm_field32_set(unit, ent_a, HITDAf, 1191 soc_L2Xm_field32_get(unit, ent_b, 1192 HITDAf)); 1193 } 1194 if (!(hit_bits & L2X_SHADOW_HIT_SRC)) { 1195 soc_L2Xm_field32_set(unit, ent_a, HITSAf, 1196 soc_L2Xm_field32_get(unit, ent_b, 1197 HITSAf)); 1198 } 1199 } 1200 1201 if (SOC_MEM_FIELD_VALID(unit, L2Xm, LOCAL_SAf)) { 1202 soc_L2Xm_field32_set(unit, l2x1, LOCAL_SAf, 0); 1203 soc_L2Xm_field32_set(unit, l2x2, LOCAL_SAf, 0); 1204 } 1205 if (SOC_MEM_FIELD_VALID(unit, L2Xm, EVEN_PARITYf)) { 1206 soc_L2Xm_field32_set(unit, l2x1, EVEN_PARITYf, 0); 1207 soc_L2Xm_field32_set(unit, l2x2, EVEN_PARITYf, 0); 1208 } 1209 #if defined(BCM_FELIX1_SUPPORT) || defined(BCM_HELIX1_SUPPORT) 1210 if (SOC_MEM_FIELD_VALID(unit, L2Xm, ODD_PARITYf)) { 1211 soc_L2Xm_field32_set(unit, l2x1, ODD_PARITYf, 0); 1212 soc_L2Xm_field32_set(unit, l2x2, ODD_PARITYf, 0); 1213 } 1214 #endif 1215 } 1216 1217 return sal_memcmp(ent_a, ent_b, size); 1218 } 1219 1220 #ifdef BCM_TRIUMPH3_SUPPORT 1221 int 1222 _soc_mem_cmp_tr3_l2x_sync(int unit, void *ent_a, void *ent_b, uint8 hit_bits) 1223 { 1224 uint32 val; 1225 soc_mem_t mem_type = L2_ENTRY_1m; 1226 l2_entry_1_entry_t *l2_1_1, *l2_1_2; 1227 l2_entry_2_entry_t *l2_2_1, *l2_2_2; 1228 1229 val = soc_mem_field32_get(unit, L2_ENTRY_1m, (l2_entry_1_entry_t *)ent_a, 1230 KEY_TYPEf); 1231 if ((val == SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) || 1232 (val == SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) || 1233 (val == SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS)) { 1234 mem_type = L2_ENTRY_2m; 1235 } 1236 1237 if (mem_type == L2_ENTRY_1m) { 1238 l2_1_1 = (l2_entry_1_entry_t *)ent_a; 1239 l2_1_2 = (l2_entry_1_entry_t *)ent_b; 1240 if (!(hit_bits & L2X_SHADOW_HIT_BITS)) { 1241 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITSAf, 0); 1242 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITSAf, 0); 1243 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITDAf, 0); 1244 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITDAf, 0); 1245 } else { 1246 if (!(hit_bits & L2X_SHADOW_HIT_SRC)) { 1247 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITSAf, 0); 1248 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITSAf, 0); 1249 } 1250 if (!(hit_bits & L2X_SHADOW_HIT_DST)) { 1251 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITDAf, 0); 1252 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITDAf, 0); 1253 } 1254 } 1255 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, LOCAL_SAf, 0); 1256 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, LOCAL_SAf, 0); 1257 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, EVEN_PARITYf, 0); 1258 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, EVEN_PARITYf, 0); 1259 return sal_memcmp(ent_a, ent_b, sizeof(l2_entry_1_entry_t)); 1260 } else { 1261 l2_2_1 = (l2_entry_2_entry_t *)ent_a; 1262 l2_2_2 = (l2_entry_2_entry_t *)ent_b; 1263 if (!(hit_bits & L2X_SHADOW_HIT_BITS)) { 1264 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITSAf, 0); 1265 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITSAf, 0); 1266 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITDAf, 0); 1267 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITDAf, 0); 1268 } else { 1269 if (!(hit_bits & L2X_SHADOW_HIT_SRC)) { 1270 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITSAf, 0); 1271 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITSAf, 0); 1272 } 1273 if (!(hit_bits & L2X_SHADOW_HIT_DST)) { 1274 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITDAf, 0); 1275 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITDAf, 0); 1276 } 1277 } 1278 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, LOCAL_SAf, 0); 1279 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, LOCAL_SAf, 0); 1280 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, EVEN_PARITY_0f, 0); 1281 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, EVEN_PARITY_0f, 0); 1282 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, EVEN_PARITY_1f, 0); 1283 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, EVEN_PARITY_1f, 0); 1284 return sal_memcmp(ent_a, ent_b, sizeof(l2_entry_2_entry_t)); 1285 } 1286 } 1287 1288 int 1289 _soc_mem_cmp_tr3_ext_l2x_1_sync(int unit, void *ent_a, void *ent_b, 1290 uint8 hit_bits) 1291 { 1292 ext_l2_entry_1_entry_t *ext_l2_1_1, *ext_l2_1_2; 1293 ext_l2_1_1 = (ext_l2_entry_1_entry_t *)ent_a; 1294 ext_l2_1_2 = (ext_l2_entry_1_entry_t *)ent_b; 1295 if (!(hit_bits & L2X_SHADOW_HIT_BITS)) { 1296 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITSAf, 0); 1297 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITSAf, 0); 1298 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITDAf, 0); 1299 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITDAf, 0); 1300 } else { 1301 if (!(hit_bits & L2X_SHADOW_HIT_SRC)) { 1302 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITSAf, 0); 1303 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITSAf, 0); 1304 } 1305 if (!(hit_bits & L2X_SHADOW_HIT_DST)) { 1306 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITDAf, 0); 1307 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITDAf, 0); 1308 } 1309 } 1310 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, LOCAL_SAf, 0); 1311 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, LOCAL_SAf, 0); 1312 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, EVEN_PARITYf, 0); 1313 soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, EVEN_PARITYf, 0); 1314 return sal_memcmp(ent_a, ent_b, sizeof(ext_l2_entry_1_entry_t)); 1315 } 1316 1317 int 1318 _soc_mem_cmp_tr3_ext_l2x_2_sync(int unit, void *ent_a, void *ent_b, 1319 uint8 hit_bits) 1320 { 1321 ext_l2_entry_2_entry_t *ext_l2_2_1, *ext_l2_2_2; 1322 ext_l2_2_1 = (ext_l2_entry_2_entry_t *)ent_a; 1323 ext_l2_2_2 = (ext_l2_entry_2_entry_t *)ent_b; 1324 if (!(hit_bits & L2X_SHADOW_HIT_BITS)) { 1325 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITSAf, 0); 1326 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITSAf, 0); 1327 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITDAf, 0); 1328 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITDAf, 0); 1329 } else { 1330 if (!(hit_bits & L2X_SHADOW_HIT_SRC)) { 1331 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITSAf, 0); 1332 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITSAf, 0); 1333 } 1334 if (!(hit_bits & L2X_SHADOW_HIT_DST)) { 1335 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITDAf, 0); 1336 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITDAf, 0); 1337 } 1338 } 1339 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, LOCAL_SAf, 0); 1340 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, LOCAL_SAf, 0); 1341 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, EVEN_PARITYf, 0); 1342 soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, EVEN_PARITYf, 0); 1343 return sal_memcmp(ent_a, ent_b, sizeof(ext_l2_entry_2_entry_t)); 1344 } 1345 1346 int 1347 _soc_mem_cmp_tr3_l2x(int unit, void *ent_a, void *ent_b) 1348 { 1349 uint32 val_a, val_b; 1350 sal_mac_addr_t mac_a, mac_b; 1351 1352 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, KEY_TYPEf); 1353 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, KEY_TYPEf); 1354 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1355 1356 switch (val_a) { 1357 case SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE: /* BRIDGE */ 1358 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, L2__VLAN_IDf); 1359 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, L2__VLAN_IDf); 1360 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1361 1362 soc_L2_ENTRY_1m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a); 1363 soc_L2_ENTRY_1m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b); 1364 return ENET_CMP_MACADDR(mac_a, mac_b); 1365 1366 case SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE: /* BRIDGE */ 1367 val_a = soc_L2_ENTRY_2m_field32_get(unit, ent_a, L2__VLAN_IDf); 1368 val_b = soc_L2_ENTRY_2m_field32_get(unit, ent_b, L2__VLAN_IDf); 1369 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1370 1371 soc_L2_ENTRY_2m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a); 1372 soc_L2_ENTRY_2m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b); 1373 return ENET_CMP_MACADDR(mac_a, mac_b); 1374 1375 case SOC_MEM_KEY_L2_ENTRY_1_L2_VFI: /* VFI */ 1376 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, L2__VFIf); 1377 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, L2__VFIf); 1378 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1379 1380 soc_L2_ENTRY_1m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a); 1381 soc_L2_ENTRY_1m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b); 1382 return ENET_CMP_MACADDR(mac_a, mac_b); 1383 1384 case SOC_MEM_KEY_L2_ENTRY_2_L2_VFI: /* VFI */ 1385 val_a = soc_L2_ENTRY_2m_field32_get(unit, ent_a, L2__VFIf); 1386 val_b = soc_L2_ENTRY_2m_field32_get(unit, ent_b, L2__VFIf); 1387 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1388 1389 soc_L2_ENTRY_2m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a); 1390 soc_L2_ENTRY_2m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b); 1391 return ENET_CMP_MACADDR(mac_a, mac_b); 1392 1393 case SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT: /* SINGLE_CROSS_CONNECT */ 1394 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN__OVIDf); 1395 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN__OVIDf); 1396 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1397 return 0; 1398 1399 case SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT: /* DOUBLE_CROSS_CONNECT */ 1400 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN__OVIDf); 1401 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN__OVIDf); 1402 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1403 1404 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN__IVIDf); 1405 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN__IVIDf); 1406 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1407 return 0; 1408 1409 case SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF: /* VIF */ 1410 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VIF__NAMESPACEf); 1411 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VIF__NAMESPACEf); 1412 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1413 1414 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VIF__DST_VIFf); 1415 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VIF__DST_VIFf); 1416 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1417 1418 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VIF__Pf); 1419 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VIF__Pf); 1420 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1421 return 0; 1422 1423 case SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS: /* TRILL_NONUC_ACCESS */ 1424 val_a = soc_L2_ENTRY_2m_field32_get(unit, ent_a, 1425 L2__VLAN_IDf); 1426 val_b = soc_L2_ENTRY_2m_field32_get(unit, ent_b, 1427 L2__VLAN_IDf); 1428 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1429 1430 soc_L2_ENTRY_2m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, 1431 mac_a); 1432 soc_L2_ENTRY_2m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, 1433 mac_b); 1434 return ENET_CMP_MACADDR(mac_a, mac_b); 1435 1436 case SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG: /* TRILL_NONUC_NETWORK_LONG */ 1437 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, 1438 TRILL_NONUC_NETWORK_LONG__VLAN_IDf); 1439 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, 1440 TRILL_NONUC_NETWORK_LONG__VLAN_IDf); 1441 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1442 1443 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, 1444 TRILL_NONUC_NETWORK_LONG__TREE_IDf); 1445 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, 1446 TRILL_NONUC_NETWORK_LONG__TREE_IDf); 1447 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1448 1449 soc_L2_ENTRY_1m_mac_addr_get 1450 (unit, ent_a, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_a); 1451 soc_L2_ENTRY_1m_mac_addr_get 1452 (unit, ent_b, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_b); 1453 return ENET_CMP_MACADDR(mac_a, mac_b); 1454 1455 case SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT: /* TRILL_NONUC_NETWORK_SHORT */ 1456 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, 1457 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf); 1458 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, 1459 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf); 1460 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1461 1462 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, 1463 TRILL_NONUC_NETWORK_SHORT__TREE_IDf); 1464 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, 1465 TRILL_NONUC_NETWORK_SHORT__TREE_IDf); 1466 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1467 return 0; 1468 1469 case SOC_MEM_KEY_L2_ENTRY_1_BFD_BFD: /* BFD */ 1470 val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, BFD__YOUR_DISCRIMINATORf); 1471 val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, BFD__YOUR_DISCRIMINATORf); 1472 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1473 return 0; 1474 default: 1475 return 1; 1476 } 1477 } 1478 1479 int 1480 _soc_mem_cmp_tr3_ext_l2x(int unit, void *ent_a, void *ent_b) 1481 { 1482 uint32 val_a, val_b; 1483 sal_mac_addr_t mac_a, mac_b; 1484 1485 val_a = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_a, KEY_TYPEf); 1486 val_b = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_b, KEY_TYPEf); 1487 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1488 1489 if (val_a) { /* VFI */ 1490 val_a = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_a, VFIf); 1491 val_b = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_b, VFIf); 1492 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1493 1494 soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1495 soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1496 return ENET_CMP_MACADDR(mac_a, mac_b); 1497 } else { /* BRIDGE */ 1498 val_a = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN_IDf); 1499 val_b = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN_IDf); 1500 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1501 1502 soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1503 soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1504 return ENET_CMP_MACADDR(mac_a, mac_b); 1505 } 1506 } 1507 #endif /* BCM_TRIUMPH3_SUPPORT */ 1508 1509 #ifdef BCM_FIREBOLT_SUPPORT 1510 int 1511 _soc_mem_cmp_l2x2(int unit, void *ent_a, void *ent_b) 1512 { 1513 sal_mac_addr_t mac_a, mac_b; 1514 uint32 val_a, val_b; 1515 uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS] = {0}; 1516 uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS] = {0}; 1517 1518 #if defined(BCM_TOMAHAWK3_SUPPORT) 1519 if (SOC_IS_TOMAHAWK3(unit)) { 1520 val_a = soc_L2Xm_field32_get(unit, ent_a, KEY_TYPEf); 1521 val_b = soc_L2Xm_field32_get(unit, ent_b, KEY_TYPEf); 1522 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1523 1524 switch(val_a) { 1525 case TH3_L2_HASH_KEY_TYPE_BRIDGE: 1526 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf); 1527 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf); 1528 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1529 1530 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1531 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1532 return ENET_CMP_MACADDR(mac_a, mac_b); 1533 1534 case TH3_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT: 1535 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf); 1536 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf); 1537 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1538 return 0; 1539 1540 default: 1541 return 1; 1542 } 1543 } else 1544 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1545 1546 if ((SOC_IS_KATANA2(unit)) || (SOC_IS_SABER2(unit)) || 1547 (SOC_IS_KATANA(unit)) || (SOC_IS_HURRICANE3(unit)) || 1548 (SOC_IS_METROLITE(unit)) || (SOC_IS_GREYHOUND(unit)) || 1549 (SOC_IS_GREYHOUND2(unit))) { 1550 if (SOC_MEM_FIELD_VALID(unit, L2Xm, KEY_TYPEf)) { 1551 val_a = soc_L2Xm_field32_get(unit, ent_a, KEY_TYPEf); 1552 val_b = soc_L2Xm_field32_get(unit, ent_b, KEY_TYPEf); 1553 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1554 1555 switch (val_a) { 1556 case 0: /* BRIDGE */ 1557 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf); 1558 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf); 1559 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1560 1561 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1562 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1563 return ENET_CMP_MACADDR(mac_a, mac_b); 1564 1565 case 1: /* SINGLE_CROSS_CONNECT */ 1566 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) { 1567 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf); 1568 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf); 1569 } else { 1570 val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf); 1571 val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf); 1572 } 1573 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1574 1575 return 0; 1576 case 2: /* DOUBLE_CROSS_CONNECT */ 1577 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) { 1578 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf); 1579 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf); 1580 } else { 1581 val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf); 1582 val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf); 1583 } 1584 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1585 1586 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__IVIDf)) { 1587 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__IVIDf); 1588 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__IVIDf); 1589 } else { 1590 val_a = soc_L2Xm_field32_get(unit, ent_a, IVIDf); 1591 val_b = soc_L2Xm_field32_get(unit, ent_b, IVIDf); 1592 } 1593 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1594 1595 return 0; 1596 1597 case 3: /* VFI */ 1598 val_a = soc_L2Xm_field32_get(unit, ent_a, VFIf); 1599 val_b = soc_L2Xm_field32_get(unit, ent_b, VFIf); 1600 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1601 1602 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1603 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1604 return ENET_CMP_MACADDR(mac_a, mac_b); 1605 1606 case 4: /* BFD */ 1607 soc_L2Xm_field_get(unit, ent_a, BFD__KEYf, buf_a); 1608 soc_L2Xm_field_get(unit, ent_b, BFD__KEYf, buf_b); 1609 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 1610 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 1611 1612 return 0; 1613 1614 case 5: /* VIF */ 1615 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__NAMESPACEf); 1616 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__NAMESPACEf); 1617 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1618 1619 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__DST_VIFf); 1620 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__DST_VIFf); 1621 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1622 1623 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__Pf); 1624 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__Pf); 1625 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1626 1627 return 0; 1628 1629 case 6: /* PE_VID */ 1630 soc_L2Xm_field_get(unit, ent_a, PE_VID__KEYf, buf_a); 1631 soc_L2Xm_field_get(unit, ent_b, PE_VID__KEYf, buf_b); 1632 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 1633 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 1634 1635 return 0; 1636 #if defined(BCM_GREYHOUND2_SUPPORT) 1637 case 7: /* VFI Multicast */ 1638 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 1639 val_a = soc_L2Xm_field32_get(unit, ent_a, VFIf); 1640 val_b = soc_L2Xm_field32_get(unit, ent_b, VFIf); 1641 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1642 1643 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1644 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1645 return ENET_CMP_MACADDR(mac_a, mac_b); 1646 } 1647 #endif /* BCM_GREYHOUND2_SUPPORT */ 1648 default: 1649 return 1; 1650 } 1651 } 1652 } else { 1653 1654 if (SOC_MEM_FIELD_VALID(unit, L2Xm, KEY_TYPEf)) { 1655 val_a = soc_L2Xm_field32_get(unit, ent_a, KEY_TYPEf); 1656 val_b = soc_L2Xm_field32_get(unit, ent_b, KEY_TYPEf); 1657 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1658 1659 switch (val_a) { 1660 case 0: /* BRIDGE */ 1661 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf); 1662 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf); 1663 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1664 1665 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1666 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1667 return ENET_CMP_MACADDR(mac_a, mac_b); 1668 1669 case 1: /* SINGLE_CROSS_CONNECT */ 1670 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) { 1671 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf); 1672 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf); 1673 } else { 1674 val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf); 1675 val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf); 1676 } 1677 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1678 1679 return 0; 1680 case 2: /* DOUBLE_CROSS_CONNECT */ 1681 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) { 1682 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf); 1683 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf); 1684 } else { 1685 val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf); 1686 val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf); 1687 } 1688 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1689 1690 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__IVIDf)) { 1691 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__IVIDf); 1692 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__IVIDf); 1693 } else { 1694 val_a = soc_L2Xm_field32_get(unit, ent_a, IVIDf); 1695 val_b = soc_L2Xm_field32_get(unit, ent_b, IVIDf); 1696 } 1697 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1698 1699 return 0; 1700 1701 case 3: /* VFI */ 1702 val_a = soc_L2Xm_field32_get(unit, ent_a, VFIf); 1703 val_b = soc_L2Xm_field32_get(unit, ent_b, VFIf); 1704 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1705 1706 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1707 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1708 return ENET_CMP_MACADDR(mac_a, mac_b); 1709 1710 case 4: /* VIF */ 1711 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__NAMESPACEf); 1712 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__NAMESPACEf); 1713 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1714 1715 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__DST_VIFf); 1716 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__DST_VIFf); 1717 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1718 1719 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__Pf); 1720 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__Pf); 1721 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1722 1723 return 0; 1724 1725 case 5: /* TRILL_NONUC_ACCESS */ 1726 if (SOC_IS_TRIDENT(unit)) { 1727 val_a = soc_L2Xm_field32_get(unit, ent_a, 1728 TRILL_NONUC_ACCESS__VLAN_IDf); 1729 val_b = soc_L2Xm_field32_get(unit, ent_b, 1730 TRILL_NONUC_ACCESS__VLAN_IDf); 1731 } else { 1732 val_a = soc_L2Xm_field32_get(unit, ent_a, L2__VLAN_IDf); 1733 val_b = soc_L2Xm_field32_get(unit, ent_b, L2__VLAN_IDf); 1734 } 1735 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1736 1737 if (SOC_IS_TRIDENT(unit)) { 1738 soc_L2Xm_mac_addr_get(unit, ent_a, 1739 TRILL_NONUC_ACCESS__MAC_ADDRf, mac_a); 1740 soc_L2Xm_mac_addr_get(unit, ent_b, 1741 TRILL_NONUC_ACCESS__MAC_ADDRf, mac_b); 1742 } else { 1743 soc_L2Xm_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a); 1744 soc_L2Xm_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b); 1745 } 1746 return ENET_CMP_MACADDR(mac_a, mac_b); 1747 1748 case 6: /* TRILL_NONUC_NETWORK_LONG */ 1749 val_a = soc_L2Xm_field32_get(unit, ent_a, 1750 TRILL_NONUC_NETWORK_LONG__VLAN_IDf); 1751 val_b = soc_L2Xm_field32_get(unit, ent_b, 1752 TRILL_NONUC_NETWORK_LONG__VLAN_IDf); 1753 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1754 1755 val_a = soc_L2Xm_field32_get(unit, ent_a, 1756 TRILL_NONUC_NETWORK_LONG__TREE_IDf); 1757 val_b = soc_L2Xm_field32_get(unit, ent_b, 1758 TRILL_NONUC_NETWORK_LONG__TREE_IDf); 1759 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1760 1761 soc_L2Xm_mac_addr_get 1762 (unit, ent_a, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_a); 1763 soc_L2Xm_mac_addr_get 1764 (unit, ent_b, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_b); 1765 return ENET_CMP_MACADDR(mac_a, mac_b); 1766 1767 case 7: /* TRILL_NONUC_NETWORK_SHORT */ 1768 val_a = soc_L2Xm_field32_get(unit, ent_a, 1769 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf); 1770 val_b = soc_L2Xm_field32_get(unit, ent_b, 1771 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf); 1772 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1773 1774 val_a = soc_L2Xm_field32_get(unit, ent_a, 1775 TRILL_NONUC_NETWORK_SHORT__TREE_IDf); 1776 val_b = soc_L2Xm_field32_get(unit, ent_b, 1777 TRILL_NONUC_NETWORK_SHORT__TREE_IDf); 1778 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1779 1780 return 0; 1781 1782 case 8: /* BFD */ 1783 soc_L2Xm_field_get(unit, ent_a, BFD__KEYf, buf_a); 1784 soc_L2Xm_field_get(unit, ent_b, BFD__KEYf, buf_b); 1785 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 1786 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 1787 1788 return 0; 1789 1790 case 9: /* PE_VID */ 1791 soc_L2Xm_field_get(unit, ent_a, PE_VID__KEYf, buf_a); 1792 soc_L2Xm_field_get(unit, ent_b, PE_VID__KEYf, buf_b); 1793 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 1794 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 1795 1796 return 0; 1797 1798 case 10: /* FCOE_ZONE */ 1799 soc_L2Xm_field_get(unit, ent_a, FCOE_ZONE__KEYf, buf_a); 1800 soc_L2Xm_field_get(unit, ent_b, FCOE_ZONE__KEYf, buf_b); 1801 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 1802 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 1803 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 1804 1805 return 0; 1806 default: 1807 return 1; 1808 } 1809 } 1810 } 1811 1812 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf); 1813 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf); 1814 SOC_MEM_COMPARE_RETURN(val_a, val_b); 1815 1816 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 1817 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 1818 return ENET_CMP_MACADDR(mac_a, mac_b); 1819 } 1820 1821 #ifdef BCM_TRIDENT3_SUPPORT 1822 1823 STATIC int 1824 _soc_td3mem_cmp_l3x2_ip6mcast(int u, void *e_a, void *e_b) 1825 { 1826 uint32 type_a, type_b; 1827 uint32 a[SOC_MAX_MEM_FIELD_WORDS]; 1828 uint32 b[SOC_MAX_MEM_FIELD_WORDS]; 1829 int i; 1830 int ent_words; 1831 1832 type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, IPV6MC__VLAN_IDf); 1833 type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, IPV6MC__VLAN_IDf); 1834 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1835 1836 type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, IPV6MC__VRF_IDf); 1837 type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, IPV6MC__VRF_IDf); 1838 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1839 1840 type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, KEY_TYPEf); 1841 type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, KEY_TYPEf); 1842 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1843 1844 type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, DATA_TYPEf); 1845 type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, DATA_TYPEf); 1846 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1847 1848 soc_mem_field_get(u, L3_ENTRY_QUADm, 1849 e_a, IPV6MC__GROUP_IP_ADDR_UPR_56f, a); 1850 soc_mem_field_get(u, L3_ENTRY_QUADm, 1851 e_b, IPV6MC__GROUP_IP_ADDR_UPR_56f, b); 1852 ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm, 1853 IPV6MC__GROUP_IP_ADDR_UPR_56f) / 32; 1854 for (i = ent_words - 1; i >= 0; i--) { 1855 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 1856 } 1857 1858 soc_mem_field_get(u, L3_ENTRY_QUADm, 1859 e_a, IPV6MC__GROUP_IP_ADDR_LWR_64f, a); 1860 soc_mem_field_get(u, L3_ENTRY_QUADm, 1861 e_b, IPV6MC__GROUP_IP_ADDR_LWR_64f, b); 1862 ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm, 1863 IPV6MC__GROUP_IP_ADDR_LWR_64f) / 32; 1864 for (i = ent_words - 1; i >= 0; i--) { 1865 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 1866 } 1867 1868 soc_mem_field_get(u, L3_ENTRY_QUADm, 1869 e_a, IPV6MC__SOURCE_IP_ADDR_UPR_64f, a); 1870 soc_mem_field_get(u, L3_ENTRY_QUADm, 1871 e_b, IPV6MC__SOURCE_IP_ADDR_UPR_64f, b); 1872 ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm, 1873 IPV6MC__SOURCE_IP_ADDR_UPR_64f) / 32; 1874 for (i = ent_words - 1; i >= 0; i--) { 1875 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 1876 } 1877 1878 soc_mem_field_get(u, L3_ENTRY_QUADm, 1879 e_a, IPV6MC__SOURCE_IP_ADDR_BITS_63_32f, a); 1880 soc_mem_field_get(u, L3_ENTRY_QUADm, 1881 e_b, IPV6MC__SOURCE_IP_ADDR_BITS_63_32f, b); 1882 ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm, 1883 IPV6MC__SOURCE_IP_ADDR_BITS_63_32f) / 32; 1884 for (i = ent_words - 1; i >= 0; i--) { 1885 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 1886 } 1887 1888 soc_mem_field_get(u, L3_ENTRY_QUADm, 1889 e_a, IPV6MC__SOURCE_IP_ADDR_BITS_31_0f, a); 1890 soc_mem_field_get(u, L3_ENTRY_QUADm, 1891 e_b, IPV6MC__SOURCE_IP_ADDR_BITS_31_0f, b); 1892 ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm, 1893 IPV6MC__SOURCE_IP_ADDR_BITS_31_0f) / 32; 1894 for (i = ent_words - 1; i >= 0; i--) { 1895 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 1896 } 1897 1898 return(0); 1899 } 1900 1901 STATIC int 1902 _soc_td3mem_cmp_l3x2_ip4mcast(int unit, void *ent_a, void *ent_b) 1903 { 1904 uint32 type_a, type_b; 1905 ip_addr_t a, b; 1906 vlan_id_t vlan_a, vlan_b; 1907 1908 type_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__VRF_IDf); 1909 type_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__VRF_IDf); 1910 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1911 1912 type_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, KEY_TYPEf); 1913 type_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, KEY_TYPEf); 1914 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1915 1916 type_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, DATA_TYPEf); 1917 type_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, DATA_TYPEf); 1918 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1919 1920 a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__SOURCE_IP_ADDRf); 1921 b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__SOURCE_IP_ADDRf); 1922 SOC_MEM_COMPARE_RETURN(a, b); 1923 1924 a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__GROUP_IP_ADDRf); 1925 b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__GROUP_IP_ADDRf); 1926 SOC_MEM_COMPARE_RETURN(a, b); 1927 1928 vlan_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__VLAN_IDf); 1929 vlan_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__VLAN_IDf); 1930 SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b); 1931 1932 return(0); 1933 } 1934 1935 STATIC int 1936 _soc_td3mem_cmp_l3x2_ip6ucast(int u, void *e_a, void *e_b) 1937 { 1938 uint32 type_a, type_b; 1939 uint32 a[SOC_MAX_MEM_FIELD_WORDS]; 1940 uint32 b[SOC_MAX_MEM_FIELD_WORDS]; 1941 int i; 1942 int ent_words; 1943 1944 type_a = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_a, IPV6UC__VRF_IDf); 1945 type_b = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_b, IPV6UC__VRF_IDf); 1946 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1947 1948 type_a = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_a, KEY_TYPEf); 1949 type_b = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_b, KEY_TYPEf); 1950 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1951 1952 type_a = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_a, DATA_TYPEf); 1953 type_b = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_b, DATA_TYPEf); 1954 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1955 1956 soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_a, 1957 IPV6UC__IP_ADDR_UPR_64f, a); 1958 soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_b, 1959 IPV6UC__IP_ADDR_UPR_64f, b); 1960 ent_words = soc_mem_field_length(u, L3_ENTRY_DOUBLEm, 1961 IPV6UC__IP_ADDR_UPR_64f) / 32; 1962 for (i = ent_words - 1; i >= 0; i--) { 1963 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 1964 } 1965 1966 soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_a, 1967 IPV6UC__IP_ADDR_LWR_64f, a); 1968 soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_b, 1969 IPV6UC__IP_ADDR_LWR_64f, b); 1970 ent_words = soc_mem_field_length(u, L3_ENTRY_DOUBLEm, 1971 IPV6UC__IP_ADDR_LWR_64f) / 32; 1972 for (i = ent_words - 1; i >= 0; i--) { 1973 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 1974 } 1975 1976 return(0); 1977 } 1978 1979 STATIC int 1980 _soc_td3mem_cmp_l3x2_ip4ucast(int unit, void *ent_a, void *ent_b) 1981 { 1982 uint32 type_a, type_b; 1983 ip_addr_t a, b; 1984 1985 type_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, IPV4UC__VRF_IDf); 1986 type_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, IPV4UC__VRF_IDf); 1987 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1988 1989 type_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, KEY_TYPEf); 1990 type_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, KEY_TYPEf); 1991 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1992 1993 type_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, DATA_TYPEf); 1994 type_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, DATA_TYPEf); 1995 SOC_MEM_COMPARE_RETURN(type_a, type_b); 1996 1997 a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, IPV4UC__IP_ADDRf); 1998 b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, IPV4UC__IP_ADDRf); 1999 SOC_MEM_COMPARE_RETURN(a, b); 2000 2001 return(0); 2002 } 2003 2004 int 2005 _soc_td3mem_cmp_l3x2(int unit, void *ent_a, void *ent_b) 2006 { 2007 uint32 val_a, val_b; 2008 val_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, KEY_TYPEf); 2009 val_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, KEY_TYPEf); 2010 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2011 2012 switch (val_a) { 2013 case TD3_L3_HASH_KEY_TYPE_V4MC: 2014 return _soc_td3mem_cmp_l3x2_ip4mcast(unit, ent_a, ent_b); 2015 case TD3_L3_HASH_KEY_TYPE_V6MC: 2016 return _soc_td3mem_cmp_l3x2_ip6mcast(unit, ent_a, ent_b); 2017 case TD3_L3_HASH_KEY_TYPE_V4UC: 2018 return _soc_td3mem_cmp_l3x2_ip4ucast(unit, ent_a, ent_b); 2019 case TD3_L3_HASH_KEY_TYPE_V6UC: 2020 return _soc_td3mem_cmp_l3x2_ip6ucast(unit, ent_a, ent_b); 2021 2022 case TD3_L3_HASH_KEY_TYPE_TRILL: 2023 case TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 2024 case TD3_L3_HASH_KEY_TYPE_FCOE_HOST: 2025 case TD3_L3_HASH_KEY_TYPE_DST_NAT: 2026 case TD3_L3_HASH_KEY_TYPE_DST_NAPT: 2027 default: 2028 return 0; 2029 } 2030 return 1; 2031 } 2032 #endif /* BCM_TRIDENT3_SUPPORT */ 2033 2034 2035 int 2036 _soc_mem_cmp_l3x2(int unit, void *ent_a, void *ent_b) 2037 { 2038 uint32 val_a, val_b; 2039 2040 #ifdef BCM_TRIDENT3_SUPPORT 2041 if (SOC_IS_TRIDENT3X(unit)) { 2042 return(_soc_td3mem_cmp_l3x2(unit, ent_a, ent_b)); 2043 } 2044 #endif /* BCM_TRIDENT3_SUPPORT */ 2045 2046 if (!SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) { 2047 return 0; 2048 } 2049 2050 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, KEY_TYPEf); 2051 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, KEY_TYPEf); 2052 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2053 2054 #ifdef BCM_TRIDENT2_SUPPORT 2055 if (SOC_IS_TD2_TT2(unit)) { 2056 uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS]; 2057 uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS]; 2058 switch (val_a) { 2059 case TD2_L3_HASH_KEY_TYPE_V4UC: 2060 return _soc_mem_cmp_l3x2_ip4ucast(unit, ent_a, ent_b); 2061 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 2062 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2063 KEY_TYPE_1f); 2064 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2065 KEY_TYPE_1f); 2066 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2067 2068 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2069 IPV4UC_EXT__IP_ADDRf); 2070 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2071 IPV4UC_EXT__IP_ADDRf); 2072 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2073 2074 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2075 IPV4UC_EXT__VRF_IDf); 2076 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2077 IPV4UC_EXT__VRF_IDf); 2078 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2079 2080 return 0; 2081 case TD2_L3_HASH_KEY_TYPE_V4MC: 2082 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 2083 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 2084 return _soc_mem_cmp_l3x2_ip4mcast(unit, ent_a, ent_b); 2085 case TD2_L3_HASH_KEY_TYPE_V6UC: 2086 return _soc_mem_cmp_l3x2_ip6ucast(unit, ent_a, ent_b); 2087 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 2088 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a, 2089 KEY_TYPE_1f); 2090 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b, 2091 KEY_TYPE_1f); 2092 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2093 2094 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a, 2095 KEY_TYPE_2f); 2096 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b, 2097 KEY_TYPE_2f); 2098 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2099 2100 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a, 2101 KEY_TYPE_3f); 2102 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b, 2103 KEY_TYPE_3f); 2104 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2105 2106 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a, 2107 IPV6UC_EXT__IP_ADDR_LWR_64f, buf_a); 2108 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b, 2109 IPV6UC_EXT__IP_ADDR_LWR_64f, buf_b); 2110 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 2111 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 2112 2113 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a, 2114 IPV6UC_EXT__VRF_IDf); 2115 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b, 2116 IPV6UC_EXT__VRF_IDf); 2117 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2118 2119 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a, 2120 IPV6UC_EXT__IP_ADDR_UPR_64f, buf_a); 2121 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b, 2122 IPV6UC_EXT__IP_ADDR_UPR_64f, buf_b); 2123 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 2124 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 2125 2126 return 0; 2127 case TD2_L3_HASH_KEY_TYPE_V6MC: 2128 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 2129 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 2130 return _soc_mem_cmp_l3x2_ip6mcast(unit, ent_a, ent_b); 2131 2132 case TD2_L3_HASH_KEY_TYPE_TRILL: 2133 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2134 TRILL__INGRESS_RBRIDGE_NICKNAMEf); 2135 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2136 TRILL__INGRESS_RBRIDGE_NICKNAMEf); 2137 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2138 2139 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2140 TRILL__TREE_IDf); 2141 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2142 TRILL__TREE_IDf); 2143 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2144 2145 return 0; 2146 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 2147 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2148 FCOE__MASKED_D_IDf); 2149 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2150 FCOE__MASKED_D_IDf); 2151 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2152 2153 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2154 FCOE__VRF_IDf); 2155 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2156 FCOE__VRF_IDf); 2157 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2158 2159 return 0; 2160 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 2161 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2162 KEY_TYPE_1f); 2163 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2164 KEY_TYPE_1f); 2165 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2166 2167 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2168 FCOE_EXT__MASKED_D_IDf); 2169 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2170 FCOE_EXT__MASKED_D_IDf); 2171 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2172 2173 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2174 FCOE_EXT__VRF_IDf); 2175 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2176 FCOE_EXT__VRF_IDf); 2177 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2178 2179 return 0; 2180 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 2181 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2182 FCOE__D_IDf); 2183 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2184 FCOE__D_IDf); 2185 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2186 2187 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2188 FCOE__VRF_IDf); 2189 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2190 FCOE__VRF_IDf); 2191 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2192 2193 return 0; 2194 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 2195 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2196 KEY_TYPE_1f); 2197 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2198 KEY_TYPE_1f); 2199 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2200 2201 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2202 FCOE_EXT__D_IDf); 2203 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2204 FCOE_EXT__D_IDf); 2205 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2206 2207 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2208 FCOE_EXT__VRF_IDf); 2209 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2210 FCOE_EXT__VRF_IDf); 2211 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2212 2213 return 0; 2214 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 2215 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2216 FCOE__S_IDf); 2217 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2218 FCOE__S_IDf); 2219 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2220 2221 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a, 2222 FCOE__VRF_IDf); 2223 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b, 2224 FCOE__VRF_IDf); 2225 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2226 2227 return 0; 2228 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 2229 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2230 KEY_TYPE_1f); 2231 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2232 KEY_TYPE_1f); 2233 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2234 2235 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2236 FCOE_EXT__S_IDf); 2237 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2238 FCOE_EXT__S_IDf); 2239 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2240 2241 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2242 FCOE_EXT__VRF_IDf); 2243 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2244 FCOE_EXT__VRF_IDf); 2245 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2246 2247 return 0; 2248 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 2249 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2250 KEY_TYPE_1f); 2251 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2252 KEY_TYPE_1f); 2253 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2254 2255 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2256 NAT__VRF_IDf); 2257 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2258 NAT__VRF_IDf); 2259 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2260 2261 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2262 NAT__IP_ADDRf); 2263 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2264 NAT__IP_ADDRf); 2265 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2266 2267 return 0; 2268 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 2269 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2270 KEY_TYPE_1f); 2271 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2272 KEY_TYPE_1f); 2273 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2274 2275 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2276 NAT__VRF_IDf); 2277 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2278 NAT__VRF_IDf); 2279 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2280 2281 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2282 NAT__IP_ADDRf); 2283 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2284 NAT__IP_ADDRf); 2285 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2286 2287 val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a, 2288 NAT__L4_DEST_PORTf); 2289 val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b, 2290 NAT__L4_DEST_PORTf); 2291 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2292 2293 return 0; 2294 default: 2295 return 1; 2296 } 2297 } else 2298 #endif /* BCM_TRIDENT2_SUPPORT */ 2299 { 2300 switch (val_a) { 2301 case 0: /* IPV4_UNICAST */ 2302 return _soc_mem_cmp_l3x2_ip4ucast(unit, ent_a, ent_b); 2303 case 1: /* IPV4_MULTICAST */ 2304 return _soc_mem_cmp_l3x2_ip4mcast(unit, ent_a, ent_b); 2305 case 2: /* IPV6_UNICAST */ 2306 return _soc_mem_cmp_l3x2_ip6ucast(unit, ent_a, ent_b); 2307 case 3: /* IPV6_MULTICAST */ 2308 return _soc_mem_cmp_l3x2_ip6mcast(unit, ent_a, ent_b); 2309 case 4: /* CCM_LMEP */ 2310 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, LMEP__SGLPf); 2311 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, LMEP__SGLPf); 2312 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2313 2314 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, LMEP__VIDf); 2315 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, LMEP__VIDf); 2316 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2317 2318 return 0; 2319 case 5: /* CCM_RMEP */ 2320 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__SGLPf); 2321 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__SGLPf); 2322 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2323 2324 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__VIDf); 2325 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__VIDf); 2326 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2327 2328 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__MDLf); 2329 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__MDLf); 2330 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2331 2332 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__MEPIDf); 2333 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__MEPIDf); 2334 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2335 2336 return 0; 2337 case 6: /* TRILL */ 2338 val_a = soc_L3_ENTRY_ONLYm_field32_get 2339 (unit, ent_a, TRILL__INGRESS_RBRIDGE_NICKNAMEf); 2340 val_b = soc_L3_ENTRY_ONLYm_field32_get 2341 (unit, ent_b, TRILL__INGRESS_RBRIDGE_NICKNAMEf); 2342 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2343 2344 val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, TRILL__TREE_IDf); 2345 val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, TRILL__TREE_IDf); 2346 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2347 2348 return 0; 2349 default: 2350 return 1; 2351 } 2352 } 2353 } 2354 2355 int 2356 _soc_mem_cmp_l3x2_ip4ucast(int unit, void *ent_a, void *ent_b) 2357 { 2358 uint32 type_a, type_b; 2359 ip_addr_t ip_a, ip_b; 2360 2361 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_UNICASTm, VRF_IDf)) { 2362 type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, VRF_IDf); 2363 type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, VRF_IDf); 2364 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2365 } 2366 2367 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_UNICASTm, KEY_TYPEf)) { 2368 type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, KEY_TYPEf); 2369 type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, KEY_TYPEf); 2370 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2371 } else { 2372 type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, V6f); 2373 type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, V6f); 2374 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2375 2376 type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, IPMCf); 2377 type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, IPMCf); 2378 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2379 } 2380 2381 ip_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, IP_ADDRf); 2382 ip_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, IP_ADDRf); 2383 SOC_MEM_COMPARE_RETURN(ip_a, ip_b); 2384 2385 return(0); 2386 } 2387 2388 int 2389 _soc_mem_cmp_l3x2_ip4mcast(int unit, void *ent_a, void *ent_b) 2390 { 2391 uint32 type_a, type_b; 2392 ip_addr_t a, b; 2393 vlan_id_t vlan_a, vlan_b; 2394 2395 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_MULTICASTm, VRF_IDf)) { 2396 type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, VRF_IDf); 2397 type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, VRF_IDf); 2398 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2399 } 2400 #if defined(BCM_TRX_SUPPORT) 2401 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_MULTICASTm, KEY_TYPE_0f)) { 2402 type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, KEY_TYPE_0f); 2403 type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, KEY_TYPE_0f); 2404 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2405 2406 type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, KEY_TYPE_1f); 2407 type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, KEY_TYPE_1f); 2408 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2409 } else 2410 #endif /* BCM_TRX_SUPPORT */ 2411 { 2412 type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, V6f); 2413 type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, V6f); 2414 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2415 2416 type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, IPMCf); 2417 type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, IPMCf); 2418 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2419 } 2420 2421 a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, SOURCE_IP_ADDRf); 2422 b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, SOURCE_IP_ADDRf); 2423 SOC_MEM_COMPARE_RETURN(a, b); 2424 2425 a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, GROUP_IP_ADDRf); 2426 b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, GROUP_IP_ADDRf); 2427 SOC_MEM_COMPARE_RETURN(a, b); 2428 2429 vlan_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, VLAN_IDf); 2430 vlan_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, VLAN_IDf); 2431 SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b); 2432 2433 return(0); 2434 } 2435 2436 int 2437 _soc_mem_cmp_l3x2_ip6ucast(int unit, void *ent_a, void *ent_b) 2438 { 2439 uint32 type_a, type_b; 2440 uint32 a[SOC_MAX_MEM_FIELD_WORDS]; 2441 uint32 b[SOC_MAX_MEM_FIELD_WORDS]; 2442 int i; 2443 int ent_words; 2444 2445 #ifdef BCM_TRIUMPH_SUPPORT 2446 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, VRF_IDf)) { 2447 type_a = 2448 soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, VRF_IDf); 2449 type_b = 2450 soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, VRF_IDf); 2451 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2452 } else 2453 #endif 2454 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, VRF_ID_0f)) { 2455 type_a = 2456 soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, VRF_ID_0f); 2457 type_b = 2458 soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, VRF_ID_0f); 2459 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2460 } 2461 #if defined(BCM_TRX_SUPPORT) 2462 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, KEY_TYPE_0f)) { 2463 type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, KEY_TYPE_0f); 2464 type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, KEY_TYPE_0f); 2465 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2466 } else 2467 #endif /* BCM_TRX_SUPPORT */ 2468 { 2469 type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, V6_0f); 2470 type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, V6_0f); 2471 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2472 2473 type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, IPMC_0f); 2474 type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, IPMC_0f); 2475 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2476 } 2477 2478 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, VRF_ID_1f)) { 2479 type_a = 2480 soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, VRF_ID_1f); 2481 type_b = 2482 soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, VRF_ID_1f); 2483 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2484 } 2485 2486 #if defined(BCM_TRX_SUPPORT) 2487 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, KEY_TYPE_1f)) { 2488 type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, KEY_TYPE_1f); 2489 type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, KEY_TYPE_1f); 2490 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2491 } else 2492 #endif /* BCM_TRX_SUPPORT */ 2493 { 2494 type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, V6_1f); 2495 type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, V6_1f); 2496 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2497 2498 type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, IPMC_1f); 2499 type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, IPMC_1f); 2500 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2501 } 2502 2503 soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_a, IP_ADDR_UPR_64f, a); 2504 soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_b, IP_ADDR_UPR_64f, b); 2505 ent_words = soc_mem_field_length(unit, L3_ENTRY_IPV6_UNICASTm, 2506 IP_ADDR_UPR_64f) / 32; 2507 for (i = ent_words - 1; i >= 0; i--) { 2508 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 2509 } 2510 soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_a, IP_ADDR_LWR_64f, a); 2511 soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_b, IP_ADDR_LWR_64f, b); 2512 ent_words = soc_mem_field_length(unit, L3_ENTRY_IPV6_UNICASTm, 2513 IP_ADDR_LWR_64f) / 32; 2514 for (i = ent_words - 1; i >= 0; i--) { 2515 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 2516 } 2517 2518 return(0); 2519 } 2520 2521 int 2522 _soc_mem_cmp_l3x2_ip6mcast(int u, void *e_a, void *e_b) 2523 { 2524 uint32 type_a, type_b; 2525 vlan_id_t vlan_a, vlan_b; 2526 uint32 a[SOC_MAX_MEM_FIELD_WORDS]; 2527 uint32 b[SOC_MAX_MEM_FIELD_WORDS]; 2528 int i; 2529 int ent_words; 2530 2531 #ifdef BCM_TRIUMPH_SUPPORT 2532 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_IDf)) { 2533 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_IDf); 2534 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_IDf); 2535 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2536 } else 2537 #endif 2538 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_0f)) { 2539 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_0f); 2540 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_0f); 2541 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2542 } 2543 #if defined(BCM_TRX_SUPPORT) 2544 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_0f)) { 2545 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_0f); 2546 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_0f); 2547 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2548 } else 2549 #endif /* BCM_TRX_SUPPORT */ 2550 { 2551 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_0f); 2552 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_0f); 2553 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2554 2555 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_0f); 2556 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_0f); 2557 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2558 } 2559 2560 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_1f)) { 2561 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_1f); 2562 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_1f); 2563 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2564 } 2565 2566 #if defined(BCM_TRX_SUPPORT) 2567 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_1f)) { 2568 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_1f); 2569 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_1f); 2570 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2571 } else 2572 #endif /* BCM_TRX_SUPPORT */ 2573 { 2574 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_1f); 2575 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_1f); 2576 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2577 2578 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_1f); 2579 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_1f); 2580 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2581 } 2582 2583 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_2f)) { 2584 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_2f); 2585 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_2f); 2586 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2587 } 2588 2589 #if defined(BCM_TRX_SUPPORT) 2590 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_2f)) { 2591 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_2f); 2592 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_2f); 2593 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2594 } else 2595 #endif /* BCM_TRX_SUPPORT */ 2596 { 2597 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_2f); 2598 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_2f); 2599 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2600 2601 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_2f); 2602 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_2f); 2603 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2604 } 2605 2606 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_3f)) { 2607 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_3f); 2608 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_3f); 2609 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2610 } 2611 2612 #if defined(BCM_TRX_SUPPORT) 2613 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_3f)) { 2614 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_3f); 2615 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_3f); 2616 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2617 } else 2618 #endif /* BCM_TRX_SUPPORT */ 2619 { 2620 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_3f); 2621 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_3f); 2622 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2623 2624 type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_3f); 2625 type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_3f); 2626 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2627 } 2628 2629 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2630 e_a, SOURCE_IP_ADDR_UPR_64f, a); 2631 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2632 e_b, SOURCE_IP_ADDR_UPR_64f, b); 2633 ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm, 2634 SOURCE_IP_ADDR_UPR_64f) / 32; 2635 for (i = ent_words - 1; i >= 0; i--) { 2636 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 2637 } 2638 2639 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2640 e_a, SOURCE_IP_ADDR_LWR_64f, a); 2641 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2642 e_b, SOURCE_IP_ADDR_LWR_64f, b); 2643 ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm, 2644 SOURCE_IP_ADDR_LWR_64f) / 32; 2645 for (i = ent_words - 1; i >= 0; i--) { 2646 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 2647 } 2648 2649 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2650 e_a, GROUP_IP_ADDR_UPR_56f, a); 2651 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2652 e_b, GROUP_IP_ADDR_UPR_56f, b); 2653 ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm, 2654 GROUP_IP_ADDR_UPR_56f) / 32; 2655 for (i = ent_words - 1; i >= 0; i--) { 2656 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 2657 } 2658 2659 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2660 e_a, GROUP_IP_ADDR_LWR_64f, a); 2661 soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm, 2662 e_b, GROUP_IP_ADDR_LWR_64f, b); 2663 ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm, 2664 GROUP_IP_ADDR_LWR_64f) / 32; 2665 for (i = ent_words - 1; i >= 0; i--) { 2666 SOC_MEM_COMPARE_RETURN(a[i], b[i]); 2667 } 2668 2669 #ifdef BCM_TRIUMPH_SUPPORT 2670 if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VLAN_IDf)) { 2671 vlan_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VLAN_IDf); 2672 vlan_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VLAN_IDf); 2673 SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b); 2674 } else 2675 #endif 2676 { 2677 vlan_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VLAN_ID_0f); 2678 vlan_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VLAN_ID_0f); 2679 SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b); 2680 } 2681 2682 return(0); 2683 } 2684 2685 /* 2686 * Compares both mask and address. Not a masked compare. 2687 */ 2688 int 2689 _soc_mem_cmp_lpm(int u, void *e_a, void *e_b) 2690 { 2691 uint32 a; 2692 uint32 b; 2693 soc_mem_t mem = L3_DEFIPm; 2694 2695 a = soc_mem_field32_get(u, mem, e_a, VALID1f); 2696 b = soc_mem_field32_get(u, mem, e_b, VALID1f); 2697 2698 if (a && b) { 2699 a = soc_mem_field32_get(u, mem, e_a, MASK1f); 2700 b = soc_mem_field32_get(u, mem, e_b, MASK1f); 2701 SOC_MEM_COMPARE_RETURN(a, b); 2702 2703 a = soc_mem_field32_get(u, mem, e_a, IP_ADDR1f); 2704 b = soc_mem_field32_get(u, mem, e_b, IP_ADDR1f); 2705 SOC_MEM_COMPARE_RETURN(a, b); 2706 2707 if (SOC_MEM_FIELD_VALID(u, mem, VRF_ID_1f)) { 2708 a = soc_mem_field32_get(u, mem, e_a, VRF_ID_1f); 2709 b = soc_mem_field32_get(u, mem, e_b, VRF_ID_1f); 2710 SOC_MEM_COMPARE_RETURN(a, b); 2711 } 2712 2713 a = soc_mem_field32_get(u, mem, e_a, MODE1f); 2714 b = soc_mem_field32_get(u, mem, e_b, MODE1f); 2715 SOC_MEM_COMPARE_RETURN(a, b); 2716 2717 if (a == 0) { 2718 return(0); /* IPV4 entry */ 2719 } 2720 } 2721 2722 a = soc_mem_field32_get(u, mem, e_a, VALID0f); 2723 b = soc_mem_field32_get(u, mem, e_b, VALID0f); 2724 2725 if (a && b) { 2726 a = soc_mem_field32_get(u, mem, e_a, MASK0f); 2727 b = soc_mem_field32_get(u, mem, e_b, MASK0f); 2728 SOC_MEM_COMPARE_RETURN(a, b); 2729 2730 a = soc_mem_field32_get(u, mem, e_a, IP_ADDR0f); 2731 b = soc_mem_field32_get(u, mem, e_b, IP_ADDR0f); 2732 SOC_MEM_COMPARE_RETURN(a, b); 2733 2734 if (SOC_MEM_FIELD_VALID(u, mem, VRF_ID_0f)) { 2735 a = soc_mem_field32_get(u, mem, e_a, VRF_ID_0f); 2736 b = soc_mem_field32_get(u, mem, e_b, VRF_ID_0f); 2737 SOC_MEM_COMPARE_RETURN(a, b); 2738 } 2739 2740 a = soc_mem_field32_get(u, mem, e_a, MODE0f); 2741 b = soc_mem_field32_get(u, mem, e_b, MODE0f); 2742 SOC_MEM_COMPARE_RETURN(a, b); 2743 if (a == 0) { 2744 return(0); /* IPV4 entry */ 2745 } 2746 } 2747 2748 a = soc_mem_field32_get(u, mem, e_a, VALID1f); 2749 b = soc_mem_field32_get(u, mem, e_b, VALID1f); 2750 SOC_MEM_COMPARE_RETURN(a, b); 2751 a = soc_mem_field32_get(u, mem, e_a, VALID0f); 2752 b = soc_mem_field32_get(u, mem, e_b, VALID0f); 2753 SOC_MEM_COMPARE_RETURN(a, b); 2754 2755 return (0); 2756 } 2757 2758 #endif /* BCM_FIREBOLT_SUPPORT */ 2759 2760 #ifdef BCM_XGS3_SWITCH_SUPPORT 2761 int 2762 _soc_mem_cmp_vlan_mac(int unit, void *ent_a, void *ent_b) 2763 { 2764 sal_mac_addr_t mac_a, mac_b; 2765 2766 soc_VLAN_MACm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a); 2767 soc_VLAN_MACm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b); 2768 2769 return ENET_CMP_MACADDR(mac_a, mac_b); 2770 } 2771 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 2772 2773 #ifdef BCM_TRX_SUPPORT 2774 int 2775 _soc_mem_cmp_vlan_mac_tr(int unit, void *ent_a, void *ent_b) 2776 { 2777 soc_mem_t mem; 2778 sal_mac_addr_t mac_a, mac_b; 2779 uint32 type_a, type_b; 2780 #ifdef BCM_TRIDENT2_SUPPORT 2781 uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS]; 2782 sal_memset(key_a, 0, sizeof(key_a)); 2783 sal_memset(key_b, 0, sizeof(key_b)); 2784 #endif 2785 2786 mem = VLAN_MACm; 2787 2788 #if defined(BCM_TRIDENT3_SUPPORT) 2789 if (soc_mem_is_valid(unit, VLAN_XLATE_2_DOUBLEm)) { 2790 mem = VLAN_XLATE_2_DOUBLEm; 2791 } 2792 #endif /* BCM_TRIDENT3_SUPPORT */ 2793 2794 type_a = soc_mem_field32_get(unit, mem, ent_a, KEY_TYPEf); 2795 type_b = soc_mem_field32_get(unit, mem, ent_b, KEY_TYPEf); 2796 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2797 2798 switch (type_a) { 2799 case 3: /* VLAN_MAC */ 2800 #ifdef BCM_TRIDENT2_SUPPORT 2801 if (SOC_IS_TD2_TT2(unit)) { 2802 #if defined(BCM_TRIDENT3_SUPPORT) 2803 if (mem == VLAN_XLATE_2_DOUBLEm) { 2804 soc_mem_field_get(unit, mem, ent_a, MAC__KEY_0f, key_a); 2805 soc_mem_field_get(unit, mem, ent_b, MAC__KEY_0f, key_b); 2806 } else 2807 #endif 2808 { 2809 soc_mem_field_get(unit, mem, ent_a, MAC__KEYf, key_a); 2810 soc_mem_field_get(unit, mem, ent_b, MAC__KEYf, key_b); 2811 } 2812 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2813 } else 2814 #endif 2815 { 2816 soc_mem_mac_addr_get(unit, mem, ent_a, MAC_ADDRf, mac_a); 2817 soc_mem_mac_addr_get(unit, mem, ent_b, MAC_ADDRf, mac_b); 2818 return ENET_CMP_MACADDR(mac_a, mac_b); 2819 } 2820 #ifdef BCM_TRIUMPH2_SUPPORT 2821 case 7: /* HPAE (MAC_IP_BIND) */ 2822 #ifdef BCM_TRIDENT2_SUPPORT 2823 if (SOC_IS_TD2_TT2(unit)) { 2824 #if defined(BCM_TRIDENT3_SUPPORT) 2825 if (mem == VLAN_XLATE_2_DOUBLEm) { 2826 soc_mem_field_get(unit, mem, ent_a, MAC_IP_BIND__KEY_0f, key_a); 2827 soc_mem_field_get(unit, mem, ent_b, MAC_IP_BIND__KEY_0f, key_b); 2828 } else 2829 #endif 2830 { 2831 soc_mem_field_get(unit, mem, ent_a, MAC_IP_BIND__KEYf, key_a); 2832 soc_mem_field_get(unit, mem, ent_b, MAC_IP_BIND__KEYf, key_b); 2833 } 2834 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2835 } else 2836 #endif 2837 { 2838 type_a = soc_mem_field32_get(unit, mem, ent_a, MAC_IP_BIND__SIPf); 2839 type_b = soc_mem_field32_get(unit, mem, ent_b, MAC_IP_BIND__SIPf); 2840 SOC_MEM_COMPARE_RETURN(type_a, type_b); 2841 2842 return 0; 2843 } 2844 #endif /* BCM_TRIUMPH2_SUPPORT */ 2845 #ifdef BCM_TRIDENT2_SUPPORT 2846 case 14: 2847 if (SOC_IS_TD2_TT2(unit)) { 2848 sal_memset(key_a, 0, sizeof(key_a)); 2849 sal_memset(key_b, 0, sizeof(key_b)); 2850 #if defined(BCM_TRIDENT3_SUPPORT) 2851 if (mem == VLAN_XLATE_2_DOUBLEm) { 2852 soc_mem_field_get(unit, mem, ent_a, MAC_PORT__KEY_0f, key_a); 2853 soc_mem_field_get(unit, mem, ent_b, MAC_PORT__KEY_0f, key_b); 2854 } else 2855 #endif 2856 { 2857 soc_mem_field_get(unit, mem, ent_a, MAC_PORT__KEYf, key_a); 2858 soc_mem_field_get(unit, mem, ent_b, MAC_PORT__KEYf, key_b); 2859 } 2860 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2861 } 2862 #endif 2863 default: 2864 return 1; 2865 } 2866 } 2867 2868 int 2869 _soc_mem_cmp_vlan_xlate_tr(int unit, void *ent_a, void *ent_b) 2870 { 2871 uint32 val_a, val_b; 2872 soc_mem_t vlan_xlate_mem = VLAN_XLATEm; 2873 2874 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 2875 uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS]; 2876 sal_memset(key_a, 0, sizeof(key_a)); 2877 sal_memset(key_b, 0, sizeof(key_b)); 2878 #endif 2879 #if defined(BCM_TRIUMPH3_SUPPORT) 2880 if (SOC_IS_TRIUMPH3(unit)) { 2881 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, VALID_0f, &val_a); 2882 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, VALID_0f, &val_b); 2883 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2884 2885 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, KEY_TYPE_0f, &val_a); 2886 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, KEY_TYPE_0f, &val_b); 2887 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2888 2889 switch (val_a) { 2890 case TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID: 2891 case TR3_VLXLT_X_HASH_KEY_TYPE_OVID: 2892 case TR3_VLXLT_X_HASH_KEY_TYPE_IVID: 2893 case TR3_VLXLT_X_HASH_KEY_TYPE_OTAG: 2894 case TR3_VLXLT_X_HASH_KEY_TYPE_ITAG: 2895 case TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI: 2896 case TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID_SVP: 2897 case TR3_VLXLT_X_HASH_KEY_TYPE_OVID_SVP: 2898 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, VALID_1f, &val_a); 2899 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, VALID_1f, &val_b); 2900 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2901 2902 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, KEY_TYPE_1f, &val_a); 2903 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, KEY_TYPE_1f, &val_b); 2904 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2905 2906 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, XLATE__KEY_0f, key_a); 2907 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, XLATE__KEY_0f, key_b); 2908 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2909 case TR3_VLXLT_HASH_KEY_TYPE_IVID_OVID: 2910 case TR3_VLXLT_HASH_KEY_TYPE_OVID: 2911 case TR3_VLXLT_HASH_KEY_TYPE_IVID: 2912 case TR3_VLXLT_HASH_KEY_TYPE_OTAG: 2913 case TR3_VLXLT_HASH_KEY_TYPE_ITAG: 2914 case TR3_VLXLT_HASH_KEY_TYPE_PRI_CFI: 2915 case TR3_VLXLT_HASH_KEY_TYPE_IVID_OVID_SVP: 2916 case TR3_VLXLT_HASH_KEY_TYPE_OVID_SVP: 2917 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, XLATE__KEYf, key_a); 2918 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, XLATE__KEYf, key_b); 2919 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2920 case TR3_VLXLT_HASH_KEY_TYPE_VLAN_MAC: 2921 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, VLAN_MAC__KEYf, key_a); 2922 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, VLAN_MAC__KEYf, key_b); 2923 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2924 case TR3_VLXLT_HASH_KEY_TYPE_VIF: 2925 case TR3_VLXLT_HASH_KEY_TYPE_VIF_VLAN: 2926 case TR3_VLXLT_HASH_KEY_TYPE_VIF_CVLAN: 2927 case TR3_VLXLT_HASH_KEY_TYPE_VIF_OTAG: 2928 case TR3_VLXLT_HASH_KEY_TYPE_VIF_ITAG: 2929 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, VIF__KEYf, key_a); 2930 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, VIF__KEYf, key_b); 2931 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2932 case TR3_VLXLT_HASH_KEY_TYPE_L2GRE_DIP: 2933 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, L2GRE_DIP__KEYf, key_a); 2934 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, L2GRE_DIP__KEYf, key_b); 2935 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2936 case TR3_VLXLT_HASH_KEY_TYPE_HPAE: 2937 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, VALID_1f, &val_a); 2938 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, VALID_1f, &val_b); 2939 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2940 2941 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, KEY_TYPE_1f, &val_a); 2942 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, KEY_TYPE_1f, &val_b); 2943 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2944 2945 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, MAC_IP_BIND__KEY_0f, key_a); 2946 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, MAC_IP_BIND__KEY_0f, key_b); 2947 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2948 default: 2949 return 1; 2950 } 2951 } 2952 #endif 2953 #if defined(BCM_TRIDENT3_SUPPORT) 2954 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 2955 vlan_xlate_mem = VLAN_XLATE_1_DOUBLEm; 2956 } 2957 #endif /* BCM_TRIDENT3_SUPPORT */ 2958 val_a = soc_mem_field32_get(unit, vlan_xlate_mem, ent_a, KEY_TYPEf); 2959 val_b = soc_mem_field32_get(unit, vlan_xlate_mem, ent_b, KEY_TYPEf); 2960 SOC_MEM_COMPARE_RETURN(val_a, val_b); 2961 #if defined(BCM_TRIDENT2_SUPPORT) 2962 if (SOC_IS_TD2_TT2(unit)) { 2963 #if defined(BCM_TRIDENT3_SUPPORT) 2964 if (vlan_xlate_mem == VLAN_XLATE_1_DOUBLEm) { 2965 switch (val_a) { 2966 case TD3_VLXLT_HASH_KEY_TYPE_IVID_OVID: 2967 case TD3_VLXLT_HASH_KEY_TYPE_OTAG: 2968 case TD3_VLXLT_HASH_KEY_TYPE_ITAG: 2969 case TD3_VLXLT_HASH_KEY_TYPE_OVID: 2970 case TD3_VLXLT_HASH_KEY_TYPE_IVID: 2971 case TD3_VLXLT_HASH_KEY_TYPE_PRI_CFI: 2972 case TD3_VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN: 2973 case TD3_VLXLT_HASH_KEY_TYPE_IVID_VSAN: 2974 case TD3_VLXLT_HASH_KEY_TYPE_OVID_VSAN: 2975 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, XLATE__KEY_0f, key_a); 2976 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, XLATE__KEY_0f, key_b); 2977 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2978 2979 case TD3_VLXLT_HASH_KEY_TYPE_VIF: 2980 case TD3_VLXLT_HASH_KEY_TYPE_VIF_VLAN: 2981 case TD3_VLXLT_HASH_KEY_TYPE_VIF_CVLAN: 2982 case TD3_VLXLT_HASH_KEY_TYPE_VIF_OTAG: 2983 case TD3_VLXLT_HASH_KEY_TYPE_VIF_ITAG: 2984 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VIF__KEY_0f, key_a); 2985 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VIF__KEY_0f, key_b); 2986 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2987 2988 case TD3_VLXLT_HASH_KEY_TYPE_L2GRE_DIP: 2989 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, L2GRE_DIP__KEY_0f, key_a); 2990 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, L2GRE_DIP__KEY_0f, key_b); 2991 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2992 2993 case TD3_VLXLT_HASH_KEY_TYPE_VXLAN_DIP: 2994 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VXLAN_DIP__KEY_0f, key_a); 2995 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VXLAN_DIP__KEY_0f, key_b); 2996 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 2997 2998 /* VLAN_MAC table */ 2999 case TD3_VLXLT_HASH_KEY_TYPE_VLAN_MAC: 3000 case TD3_VLXLT_HASH_KEY_TYPE_HPAE: 3001 case TD3_VLXLT_HASH_KEY_TYPE_VLAN_MAC_PORT: 3002 return _soc_mem_cmp_vlan_mac_tr(unit, ent_a, ent_b); 3003 3004 default: 3005 return 1; 3006 } 3007 } else 3008 #endif /* BCM_TRIDENT3_SUPPORT */ 3009 { 3010 switch (val_a) { 3011 case TD2_VLXLT_HASH_KEY_TYPE_IVID_OVID: 3012 case TD2_VLXLT_HASH_KEY_TYPE_OTAG: 3013 case TD2_VLXLT_HASH_KEY_TYPE_ITAG: 3014 case TD2_VLXLT_HASH_KEY_TYPE_OVID: 3015 case TD2_VLXLT_HASH_KEY_TYPE_IVID: 3016 case TD2_VLXLT_HASH_KEY_TYPE_PRI_CFI: 3017 case TD2_VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN: 3018 case TD2_VLXLT_HASH_KEY_TYPE_IVID_VSAN: 3019 case TD2_VLXLT_HASH_KEY_TYPE_OVID_VSAN: 3020 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, XLATE__KEYf, key_a); 3021 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, XLATE__KEYf, key_b); 3022 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3023 3024 case TD2_VLXLT_HASH_KEY_TYPE_VIF: 3025 case TD2_VLXLT_HASH_KEY_TYPE_VIF_VLAN: 3026 case TD2_VLXLT_HASH_KEY_TYPE_VIF_CVLAN: 3027 case TD2_VLXLT_HASH_KEY_TYPE_VIF_OTAG: 3028 case TD2_VLXLT_HASH_KEY_TYPE_VIF_ITAG: 3029 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VIF__KEYf, key_a); 3030 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VIF__KEYf, key_b); 3031 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3032 3033 case TD2_VLXLT_HASH_KEY_TYPE_L2GRE_DIP: 3034 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, L2GRE_DIP__KEYf, key_a); 3035 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, L2GRE_DIP__KEYf, key_b); 3036 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3037 3038 case TD2_VLXLT_HASH_KEY_TYPE_VXLAN_DIP: 3039 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VXLAN_DIP__KEYf, key_a); 3040 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VXLAN_DIP__KEYf, key_b); 3041 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3042 3043 /* VLAN_MAC table */ 3044 case TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC: 3045 case TD2_VLXLT_HASH_KEY_TYPE_HPAE: 3046 case TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC_PORT: 3047 return _soc_mem_cmp_vlan_mac_tr(unit, ent_a, ent_b); 3048 3049 default: 3050 return 1; 3051 } 3052 } 3053 } else 3054 #endif 3055 { 3056 switch (val_a) { 3057 case 3: /* VLAN_MAC */ 3058 case 7: /* HPAE (MAC_IP_BIND) */ 3059 return _soc_mem_cmp_vlan_mac_tr(unit, ent_a, ent_b); 3060 3061 case 0: /* IVID_OVID */ 3062 case 1: /* OTAG */ 3063 case 2: /* ITAG */ 3064 case 4: /* OVID */ 3065 case 5: /* IVID */ 3066 case 6: /* PRI_CFI */ 3067 val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, GLPf); 3068 val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, GLPf); 3069 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3070 3071 val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, INCOMING_VIDSf); 3072 val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, INCOMING_VIDSf); 3073 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3074 3075 return 0; 3076 3077 case 9: /* VIF_VLAN */ 3078 val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, VIF__VLANf); 3079 val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, VIF__VLANf); 3080 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3081 /* fall through to case for VIF */ 3082 3083 case 8: /* VIF */ 3084 val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, VIF__GLPf); 3085 val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, VIF__GLPf); 3086 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3087 3088 val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, VIF__SRC_VIFf); 3089 val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, VIF__SRC_VIFf); 3090 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3091 3092 return 0; 3093 3094 default: 3095 return 1; 3096 } 3097 } 3098 } 3099 3100 int 3101 _soc_mem_cmp_egr_vlan_xlate_tr(int unit, void *ent_a, void *ent_b) 3102 { 3103 sal_mac_addr_t mac_a, mac_b; 3104 uint32 val_a, val_b; 3105 #if defined(BCM_TRIDENT2_SUPPORT) 3106 uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS]; 3107 sal_memset(key_a, 0, sizeof(key_a)); 3108 sal_memset(key_b, 0, sizeof(key_b)); 3109 #endif 3110 if (SOC_MEM_FIELD_VALID(unit, EGR_VLAN_XLATEm, ENTRY_TYPEf)) { 3111 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, ENTRY_TYPEf); 3112 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, ENTRY_TYPEf); 3113 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3114 3115 switch (val_a) { 3116 case 0: /* VLAN_XLATE */ 3117 case 1: /* VLAN_XLATE_DVP */ 3118 case 2: /* VLAN_XLATE_WLAN */ 3119 #if defined(BCM_TRIDENT2_SUPPORT) 3120 if (SOC_IS_TD2_TT2(unit)) { 3121 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, XLATE__KEYf, key_a); 3122 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, XLATE__KEYf, key_b); 3123 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3124 } else 3125 #endif 3126 if (SOC_IS_TD_TT(unit)) { 3127 val_a = soc_EGR_VLAN_XLATEm_field32_get 3128 (unit, ent_a, DST_MODIDf); 3129 val_b = soc_EGR_VLAN_XLATEm_field32_get 3130 (unit, ent_b, DST_MODIDf); 3131 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3132 3133 val_a = soc_EGR_VLAN_XLATEm_field32_get 3134 (unit, ent_a, DST_PORTf); 3135 val_b = soc_EGR_VLAN_XLATEm_field32_get 3136 (unit, ent_b, DST_PORTf); 3137 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3138 } else if (SOC_MEM_FIELD_VALID(unit, EGR_VLAN_XLATEm, DVPf)) { 3139 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, DVPf); 3140 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, DVPf); 3141 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3142 } else { 3143 val_a = soc_EGR_VLAN_XLATEm_field32_get 3144 (unit, ent_a, PORT_GROUP_IDf); 3145 val_b = soc_EGR_VLAN_XLATEm_field32_get 3146 (unit, ent_b, PORT_GROUP_IDf); 3147 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3148 } 3149 3150 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, OVIDf); 3151 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, OVIDf); 3152 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3153 3154 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, IVIDf); 3155 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, IVIDf); 3156 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3157 3158 return 0; 3159 3160 case 3: /* ISID_XLATE */ 3161 case 4: /* ISID_DVP_XLATE */ 3162 val_a = soc_EGR_VLAN_XLATEm_field32_get 3163 (unit, ent_a, MIM_ISID__VFIf); 3164 val_b = soc_EGR_VLAN_XLATEm_field32_get 3165 (unit, ent_b, MIM_ISID__VFIf); 3166 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3167 3168 val_a = soc_EGR_VLAN_XLATEm_field32_get 3169 (unit, ent_a, MIM_ISID__DVPf); 3170 val_b = soc_EGR_VLAN_XLATEm_field32_get 3171 (unit, ent_b, MIM_ISID__DVPf); 3172 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3173 3174 return 0; 3175 3176 case 5: /* WLAN_SVP_TUNNEL */ 3177 case 6: /* WLAN_SVP_BSSID */ 3178 #if defined(BCM_TRIDENT2_SUPPORT) 3179 if (SOC_IS_TD2_TT2(unit)) { 3180 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, L2GRE_VFI__KEYf, key_a); 3181 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, L2GRE_VFI__KEYf, key_b); 3182 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3183 } else 3184 #endif 3185 { 3186 val_a = soc_EGR_VLAN_XLATEm_field32_get 3187 (unit, ent_a, WLAN_SVP__RIDf); 3188 val_b = soc_EGR_VLAN_XLATEm_field32_get 3189 (unit, ent_b, WLAN_SVP__RIDf); 3190 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3191 3192 soc_mem_mac_addr_get 3193 (unit, EGR_VLAN_XLATEm, ent_a, WLAN_SVP__BSSIDf, mac_a); 3194 soc_mem_mac_addr_get 3195 (unit, EGR_VLAN_XLATEm, ent_b, WLAN_SVP__BSSIDf, mac_b); 3196 return ENET_CMP_MACADDR(mac_a, mac_b); 3197 } 3198 case 7: /* WLAN_SVP_BSSID_RID */ 3199 #if defined(BCM_TRIDENT2_SUPPORT) 3200 if (SOC_IS_TD2_TT2(unit)) { 3201 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, XLATE__KEYf, key_a); 3202 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, XLATE__KEYf, key_b); 3203 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3204 } else 3205 #endif 3206 { 3207 val_a = soc_EGR_VLAN_XLATEm_field32_get 3208 (unit, ent_a, WLAN_SVP__RIDf); 3209 val_b = soc_EGR_VLAN_XLATEm_field32_get 3210 (unit, ent_b, WLAN_SVP__RIDf); 3211 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3212 3213 soc_mem_mac_addr_get 3214 (unit, EGR_VLAN_XLATEm, ent_a, WLAN_SVP__BSSIDf, mac_a); 3215 soc_mem_mac_addr_get 3216 (unit, EGR_VLAN_XLATEm, ent_b, WLAN_SVP__BSSIDf, mac_b); 3217 return ENET_CMP_MACADDR(mac_a, mac_b); 3218 } 3219 #ifdef BCM_TRIDENT2_SUPPORT 3220 case 8: 3221 case 9: 3222 if (SOC_IS_TD2_TT2(unit)) { 3223 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, VXLAN_VFI__KEYf, key_a); 3224 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, VXLAN_VFI__KEYf, key_b); 3225 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3226 } 3227 #endif 3228 default: 3229 return 1; 3230 } 3231 } 3232 3233 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, PORT_GROUP_IDf); 3234 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, PORT_GROUP_IDf); 3235 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3236 3237 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, IVIDf); 3238 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, IVIDf); 3239 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3240 3241 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, OVIDf); 3242 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, OVIDf); 3243 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3244 3245 return 0; 3246 } 3247 3248 #ifdef BCM_TRIUMPH_SUPPORT 3249 int 3250 _soc_mem_cmp_mpls_entry_tr(int unit, void *ent_a, void *ent_b) 3251 { 3252 uint32 val_a = 0, val_b = 0; 3253 soc_mem_t mem; 3254 /* Used for non-MPLS key types */ 3255 sal_mac_addr_t mac_a, mac_b; 3256 #if defined(BCM_TRIDENT2_SUPPORT) 3257 uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS]; 3258 sal_memset(key_a, 0, sizeof(key_a)); 3259 sal_memset(key_b, 0, sizeof(key_b)); 3260 #endif 3261 3262 mem = SOC_IS_TOMAHAWK3(unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm; 3263 3264 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 3265 #if defined(BCM_TOMAHAWK3_SUPPORT) 3266 if (SOC_IS_TOMAHAWK3(unit)) { 3267 val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, KEY_TYPEf); 3268 val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, KEY_TYPEf); 3269 } else 3270 #endif 3271 { 3272 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, KEY_TYPEf); 3273 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, KEY_TYPEf); 3274 } 3275 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3276 3277 #if defined(BCM_TOMAHAWK3_SUPPORT) 3278 if (SOC_IS_TOMAHAWK3(unit)) { 3279 switch (val_a) { 3280 case 0: /* MPLS */ 3281 val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, PORT_NUMf); 3282 val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, PORT_NUMf); 3283 3284 /* Note: MODULE_IDf is absent in TH3's MPLS_ENTRY_SINGLE */ 3285 3286 val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, Tf); 3287 val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, Tf); 3288 3289 val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, MPLS_LABELf); 3290 val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, MPLS_LABELf); 3291 return 0; 3292 3293 default: 3294 return 1; 3295 } 3296 } 3297 #endif /* BCM_TOMAHAWK3_SUPPORT */ 3298 3299 switch (val_a) { 3300 case 0: /* MPLS */ 3301 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, PORT_NUMf); 3302 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, PORT_NUMf); 3303 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3304 3305 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MODULE_IDf); 3306 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MODULE_IDf); 3307 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3308 3309 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, Tf); 3310 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, Tf); 3311 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3312 3313 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MPLS_LABELf); 3314 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MPLS_LABELf); 3315 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3316 3317 return 0; 3318 case 1: /* MIM_NVP */ 3319 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_NVP__BVIDf); 3320 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_NVP__BVIDf); 3321 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3322 3323 soc_mem_mac_addr_get 3324 (unit, MPLS_ENTRYm, ent_a, MIM_NVP__BMACSAf, mac_a); 3325 soc_mem_mac_addr_get 3326 (unit, MPLS_ENTRYm, ent_b, MIM_NVP__BMACSAf, mac_b); 3327 return ENET_CMP_MACADDR(mac_a, mac_b); 3328 3329 case 2: /* MIM_ISID */ 3330 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_ISID__ISIDf); 3331 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_ISID__ISIDf); 3332 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3333 3334 return 0; 3335 3336 case 3: /* MIM_ISID_SVP */ 3337 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_ISID__ISIDf); 3338 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_ISID__ISIDf); 3339 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3340 3341 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_ISID__SVPf); 3342 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_ISID__SVPf); 3343 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3344 3345 return 0; 3346 3347 case 4: /* WLAN_MAC */ 3348 #if defined(BCM_TRIDENT2_SUPPORT) 3349 if (SOC_IS_TD2_TT2(unit)) { 3350 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, L2GRE_VPNID__KEYf, key_a); 3351 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, L2GRE_VPNID__KEYf, key_b); 3352 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3353 } else 3354 #endif 3355 { 3356 soc_mem_mac_addr_get 3357 (unit, MPLS_ENTRYm, ent_a, WLAN_MAC__MAC_ADDRf, mac_a); 3358 soc_mem_mac_addr_get 3359 (unit, MPLS_ENTRYm, ent_b, WLAN_MAC__MAC_ADDRf, mac_b); 3360 return ENET_CMP_MACADDR(mac_a, mac_b); 3361 } 3362 3363 case 5: /* TRILL */ 3364 val_a = soc_MPLS_ENTRYm_field32_get 3365 (unit, ent_a, TRILL__RBRIDGE_NICKNAMEf); 3366 val_b = soc_MPLS_ENTRYm_field32_get 3367 (unit, ent_b, TRILL__RBRIDGE_NICKNAMEf); 3368 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3369 3370 return 0; 3371 #if defined(BCM_TRIDENT2_SUPPORT) 3372 case 6: 3373 if (SOC_IS_TD2_TT2(unit)) { 3374 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, L2GRE_SIP__KEYf, key_a); 3375 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, L2GRE_SIP__KEYf, key_b); 3376 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3377 } 3378 return 1; 3379 case 7: 3380 if (SOC_IS_TD2_TT2(unit)) { 3381 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, L2GRE_VPNID__KEYf, key_a); 3382 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, L2GRE_VPNID__KEYf, key_b); 3383 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3384 } 3385 return 1; 3386 case 8: 3387 if (SOC_IS_TD2_TT2(unit)) { 3388 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, VXLAN_SIP__KEYf, key_a); 3389 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, VXLAN_SIP__KEYf, key_b); 3390 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3391 } 3392 return 1; 3393 case 9: 3394 case 10: 3395 if (SOC_IS_TD2_TT2(unit)) { 3396 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, VXLAN_VN_ID__KEYf, key_a); 3397 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, VXLAN_VN_ID__KEYf, key_b); 3398 return sal_memcmp(key_a, key_b, (sizeof(key_a))); 3399 } 3400 return 1; 3401 #endif 3402 default: 3403 return 1; 3404 } 3405 } 3406 3407 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, PORT_NUMf); 3408 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, PORT_NUMf); 3409 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3410 3411 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MODULE_IDf); 3412 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MODULE_IDf); 3413 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3414 3415 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, Tf); 3416 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, Tf); 3417 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3418 3419 val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MPLS_LABELf); 3420 val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MPLS_LABELf); 3421 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3422 3423 return 0; 3424 } 3425 #endif /* BCM_TRIUMPH_SUPPORT */ 3426 3427 STATIC void 3428 _soc_mem_write_range_cache_update(int unit, 3429 soc_mem_t mem, unsigned array_index, 3430 int copyno, int no_cache, 3431 int index_min, int index_max, void *buffer) 3432 { 3433 uint32 *cache; 3434 uint32 entry_dw; 3435 int mem_array_vmap_offset, mem_array_cache_offset; 3436 int i; 3437 uint8 *vmap; 3438 int indices_reversed = (index_max < index_min); 3439 int effective_min = indices_reversed ? index_max : index_min; 3440 int effective_max = indices_reversed ? index_min : index_max; 3441 int index_limit = indices_reversed ? (index_min - 1) : (index_max + 1); 3442 3443 entry_dw = soc_mem_entry_words(unit, mem); 3444 #ifdef BCM_DNX_SUPPORT 3445 mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ? 3446 ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) : 3447 (array_index * soc_mem_index_count(unit, mem)); 3448 #else 3449 mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem); 3450 #endif 3451 mem_array_cache_offset = mem_array_vmap_offset * entry_dw; 3452 3453 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 3454 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 3455 sal_memcpy(cache + mem_array_cache_offset + effective_min * entry_dw, 3456 buffer, (effective_max - effective_min + 1) * entry_dw * 4); 3457 3458 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 3459 for (i = index_min; i != index_limit; indices_reversed ? i-- : i++) { 3460 CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i); 3461 } 3462 } 3463 3464 } 3465 3466 3467 /* 3468 * Function: _soc_mem_aggr_cache_update 3469 * 3470 * Purpose: If this mem view has several physical copies, 3471 * it needs to be updated accordingly. 3472 * 3473 * Returns: None 3474 */ 3475 STATIC void 3476 _soc_mem_aggr_cache_update(int unit, soc_mem_t mem, 3477 int blk, int no_cache, 3478 int index_min, int index_max, 3479 int array_index, void *entry_data) 3480 { 3481 3482 /* 3483 * There are 3 physical copies of MODPORT_MAP. 3484 * Writing this table writes all three physical copies. 3485 * The copies are MODPORT_MAP_SW, MODPORT_MAP_IM, MODPORT_MAP_EM. 3486 */ 3487 if (soc_mem_is_aggr(unit, mem) && mem == MODPORT_MAPm) { 3488 if (soc_mem_is_valid(unit, MODPORT_MAP_SWm)) { 3489 _soc_mem_write_range_cache_update(unit, MODPORT_MAP_SWm, 3490 array_index, blk, no_cache, 3491 index_min, index_max, entry_data); 3492 } 3493 if (soc_mem_is_valid(unit, MODPORT_MAP_IMm)) { 3494 _soc_mem_write_range_cache_update(unit, MODPORT_MAP_IMm, 3495 array_index, blk, no_cache, 3496 index_min, index_max, entry_data); 3497 } 3498 if (soc_mem_is_valid(unit, MODPORT_MAP_EMm)) { 3499 _soc_mem_write_range_cache_update(unit, MODPORT_MAP_EMm, 3500 array_index, blk, no_cache, 3501 index_min, index_max, entry_data); 3502 } 3503 } 3504 3505 } 3506 3507 3508 #endif /* BCM_TRX_SUPPORT */ 3509 3510 #ifdef BCM_TRIDENT2_SUPPORT 3511 int 3512 _soc_mem_cmp_ing_vp_vlan_membership(int unit, void *ent_a, void *ent_b) 3513 { 3514 uint32 val_a, val_b; 3515 3516 val_a = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_a, VLANf); 3517 val_b = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_b, VLANf); 3518 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3519 3520 val_a = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_a, VPf); 3521 val_b = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_b, VPf); 3522 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3523 3524 return 0; 3525 } 3526 3527 int 3528 _soc_mem_cmp_egr_vp_vlan_membership(int unit, void *ent_a, void *ent_b) 3529 { 3530 uint32 val_a, val_b; 3531 3532 val_a = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_a, VLANf); 3533 val_b = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_b, VLANf); 3534 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3535 3536 val_a = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_a, VPf); 3537 val_b = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_b, VPf); 3538 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3539 3540 return 0; 3541 } 3542 3543 int 3544 _soc_mem_cmp_ing_dnat_address_type(int unit, void *ent_a, void *ent_b) 3545 { 3546 uint32 val_a, val_b; 3547 3548 val_a = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_a, 3549 DEST_IPV4_ADDRf); 3550 val_b = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_b, 3551 DEST_IPV4_ADDRf); 3552 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3553 3554 val_a = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_a, VRFf); 3555 val_b = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_b, VRFf); 3556 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3557 3558 return 0; 3559 } 3560 3561 int 3562 _soc_mem_cmp_l2_endpoint_id(int unit, void *ent_a, void *ent_b) 3563 { 3564 sal_mac_addr_t mac_a, mac_b; 3565 uint32 val_a, val_b; 3566 3567 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, KEY_TYPEf); 3568 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, KEY_TYPEf); 3569 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3570 3571 switch (val_a) { 3572 case TD2_L2_HASH_KEY_TYPE_BRIDGE: 3573 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, 3574 L2__VLAN_IDf); 3575 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, 3576 L2__VLAN_IDf); 3577 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3578 3579 soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_a, L2__MAC_ADDRf, 3580 mac_a); 3581 soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_b, L2__MAC_ADDRf, 3582 mac_b); 3583 return ENET_CMP_MACADDR(mac_a, mac_b); 3584 3585 case TD2_L2_HASH_KEY_TYPE_VFI: 3586 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, L2__VFIf); 3587 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, L2__VFIf); 3588 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3589 3590 soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_a, L2__MAC_ADDRf, 3591 mac_a); 3592 soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_b, L2__MAC_ADDRf, 3593 mac_b); 3594 return ENET_CMP_MACADDR(mac_a, mac_b); 3595 3596 case TD2_L2_HASH_KEY_TYPE_VIF: 3597 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, 3598 VIF__NAMESPACEf); 3599 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, 3600 VIF__NAMESPACEf); 3601 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3602 3603 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, 3604 VIF__DST_VIFf); 3605 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, 3606 VIF__DST_VIFf); 3607 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3608 3609 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, VIF__Pf); 3610 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, VIF__Pf); 3611 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3612 3613 return 0; 3614 3615 case TD2_L2_HASH_KEY_TYPE_PE_VID: 3616 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, 3617 PE_VID__NAMESPACEf); 3618 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, 3619 PE_VID__NAMESPACEf); 3620 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3621 3622 val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, 3623 PE_VID__ETAG_VIDf); 3624 val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, 3625 PE_VID__ETAG_VIDf); 3626 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3627 3628 return 0; 3629 3630 default: 3631 return 1; 3632 } 3633 3634 return 0; 3635 } 3636 3637 int 3638 _soc_mem_cmp_endpoint_queue_map(int unit, void *ent_a, void *ent_b) 3639 { 3640 uint32 val_a, val_b; 3641 3642 val_a = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_a, KEY_TYPEf); 3643 val_b = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_b, KEY_TYPEf); 3644 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3645 3646 switch (val_a) { 3647 case 0: /* endpoint queueing */ 3648 val_a = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_a, 3649 EH_QUEUE_TAGf); 3650 val_b = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_b, 3651 EH_QUEUE_TAGf); 3652 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3653 3654 val_a = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_a, 3655 DEST_PORTf); 3656 val_b = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_b, 3657 DEST_PORTf); 3658 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3659 3660 return 0; 3661 3662 default: 3663 return 1; 3664 } 3665 3666 return 0; 3667 } 3668 #endif /* BCM_TRIDENT2_SUPPORT */ 3669 3670 #ifdef BCM_TOMAHAWK_SUPPORT 3671 int 3672 _soc_mem_cmp_exact_match(int unit, void *ent_a, void *ent_b) 3673 { 3674 uint32 val_a, val_b; 3675 uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS]; 3676 uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS]; 3677 soc_mem_t mem_2 = EXACT_MATCH_2m; 3678 soc_mem_t mem_4 = EXACT_MATCH_4m; 3679 3680 #ifdef BCM_TOMAHAWK3_SUPPORT 3681 if(SOC_IS_TOMAHAWK3(unit)) { 3682 val_a = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_a, KEY_TYPEf); 3683 val_b = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_b, KEY_TYPEf); 3684 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3685 3686 switch (val_a) { 3687 case TH3_FPEM_HASH_KEY_TYPE_128B: 3688 soc_mem_field_get( 3689 unit, EXACT_MATCH_2m, ent_a, MODE128__KEY_0_ONLYf, 3690 buf_a); 3691 soc_mem_field_get( 3692 unit, EXACT_MATCH_2m, ent_b, MODE128__KEY_0_ONLYf, 3693 buf_b); 3694 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3695 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3696 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3697 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3698 3699 val_a = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_a, 3700 MODE128__KEY_1_ONLYf); 3701 val_b = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_b, 3702 MODE128__KEY_1_ONLYf); 3703 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3704 3705 return 0; 3706 3707 case TH3_FPEM_HASH_KEY_TYPE_160B: 3708 soc_mem_field_get( 3709 unit, EXACT_MATCH_2m, ent_a, MODE160__KEY_0_ONLYf, 3710 buf_a); 3711 soc_mem_field_get( 3712 unit, EXACT_MATCH_2m, ent_b, MODE160__KEY_0_ONLYf, 3713 buf_b); 3714 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3715 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3716 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3717 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3718 3719 soc_mem_field_get( 3720 unit, EXACT_MATCH_2m, ent_a, MODE160__KEY_1_ONLYf, 3721 buf_a); 3722 soc_mem_field_get( 3723 unit, EXACT_MATCH_2m, ent_b, MODE160__KEY_1_ONLYf, 3724 buf_b); 3725 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3726 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3727 3728 return 0; 3729 3730 case TH3_FPEM_HASH_KEY_TYPE_320B: 3731 soc_mem_field_get( 3732 unit, EXACT_MATCH_4m, ent_a, MODE320__KEY_0_ONLYf, 3733 buf_a); 3734 soc_mem_field_get( 3735 unit, EXACT_MATCH_4m, ent_b, MODE320__KEY_0_ONLYf, 3736 buf_b); 3737 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3738 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3739 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3740 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3741 3742 soc_mem_field_get( 3743 unit, EXACT_MATCH_4m, ent_a, MODE320__KEY_1_ONLYf, 3744 buf_a); 3745 soc_mem_field_get( 3746 unit, EXACT_MATCH_4m, ent_b, MODE320__KEY_1_ONLYf, 3747 buf_b); 3748 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3749 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3750 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3751 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3752 3753 soc_mem_field_get( 3754 unit, EXACT_MATCH_4m, ent_a, MODE320__KEY_2_ONLYf, 3755 buf_a); 3756 soc_mem_field_get( 3757 unit, EXACT_MATCH_4m, ent_b, MODE320__KEY_2_ONLYf, 3758 buf_b); 3759 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3760 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3761 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3762 3763 return 0; 3764 3765 default: 3766 return 1; 3767 } 3768 return 0; 3769 } 3770 #endif /* BCM_TOMAHAWK3_SUPPORT */ 3771 3772 #ifdef BCM_TRIDENT3_SUPPORT 3773 if (SOC_IS_TRIDENT3X(unit)) { 3774 val_a = soc_mem_field32_get(unit, mem_2, ent_a, KEY_TYPEf); 3775 val_b = soc_mem_field32_get(unit, mem_2, ent_b, KEY_TYPEf); 3776 } else 3777 #endif 3778 { 3779 val_a = soc_mem_field32_get(unit, mem_2, ent_a, KEY_TYPE_0f); 3780 val_b = soc_mem_field32_get(unit, mem_2, ent_b, KEY_TYPE_0f); 3781 } 3782 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3783 3784 switch (val_a) { 3785 case TH_FPEM_HASH_KEY_TYPE_128B: 3786 soc_mem_field_get(unit, mem_2, ent_a, MODE128__KEY_0_ONLYf, 3787 buf_a); 3788 soc_mem_field_get(unit, mem_2, ent_b, MODE128__KEY_0_ONLYf, 3789 buf_b); 3790 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3791 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3792 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3793 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3794 3795 val_a = soc_mem_field32_get(unit, mem_2, ent_a, 3796 MODE128__KEY_1_ONLYf); 3797 val_b = soc_mem_field32_get(unit, mem_2, ent_b, 3798 MODE128__KEY_1_ONLYf); 3799 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3800 3801 return 0; 3802 3803 case TH_FPEM_HASH_KEY_TYPE_160B: 3804 soc_mem_field_get(unit, mem_2, ent_a, MODE160__KEY_0_ONLYf, 3805 buf_a); 3806 soc_mem_field_get(unit, mem_2, ent_b, MODE160__KEY_0_ONLYf, 3807 buf_b); 3808 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3809 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3810 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3811 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3812 3813 soc_mem_field_get(unit, mem_2, ent_a, MODE160__KEY_1_ONLYf, 3814 buf_a); 3815 soc_mem_field_get(unit, mem_2, ent_b, MODE160__KEY_1_ONLYf, 3816 buf_b); 3817 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3818 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3819 3820 return 0; 3821 3822 case TH_FPEM_HASH_KEY_TYPE_320B: 3823 soc_mem_field_get(unit, mem_4, ent_a, MODE320__KEY_0_ONLYf, 3824 buf_a); 3825 soc_mem_field_get(unit, mem_4, ent_b, MODE320__KEY_0_ONLYf, 3826 buf_b); 3827 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3828 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3829 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3830 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3831 3832 soc_mem_field_get(unit, mem_4, ent_a, MODE320__KEY_1_ONLYf, 3833 buf_a); 3834 soc_mem_field_get(unit, mem_4, ent_b, MODE320__KEY_1_ONLYf, 3835 buf_b); 3836 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3837 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3838 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3839 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3840 3841 soc_mem_field_get(unit, mem_4, ent_a, MODE320__KEY_2_ONLYf, 3842 buf_a); 3843 soc_mem_field_get(unit, mem_4, ent_b, MODE320__KEY_2_ONLYf, 3844 buf_b); 3845 SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]); 3846 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 3847 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 3848 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 3849 3850 val_a = soc_mem_field32_get(unit, mem_4, ent_a, 3851 MODE320__KEY_3_ONLYf); 3852 val_b = soc_mem_field32_get(unit, mem_4, ent_b, 3853 MODE320__KEY_3_ONLYf); 3854 SOC_MEM_COMPARE_RETURN(val_a, val_b); 3855 3856 return 0; 3857 3858 default: 3859 return 1; 3860 } 3861 3862 return 0; 3863 } 3864 #endif /* BCM_TOMAHAWK_SUPPORT */ 3865 3866 int 3867 _soc_mem_cmp_ft_key_double(int unit, void *ent_a, void *ent_b) 3868 { 3869 3870 3871 return 0; 3872 } 3873 3874 int 3875 _soc_mem_cmp_ft_key_single(int unit, void *ent_a, void *ent_b) 3876 { 3877 3878 3879 return 0; 3880 } 3881 3882 /* 3883 * This function caches the info needed by the L3 key comparison, below. 3884 */ 3885 int 3886 _soc_mem_cmp_l3x_sync(int unit) 3887 { 3888 return SOC_E_NONE; 3889 } 3890 3891 int 3892 _soc_mem_cmp_l3x_set(int unit, uint32 ipmc_config) 3893 { 3894 return SOC_E_NONE; 3895 } 3896 3897 int 3898 _soc_mem_cmp_l3x(int unit, void *ent_a, void *ent_b) 3899 { 3900 return 0; 3901 } 3902 3903 /* 3904 * Function: 3905 * soc_mem_index_limit 3906 * Purpose: 3907 * Returns the maximum possible index for any dynamically extendable memory 3908 */ 3909 int 3910 soc_mem_index_limit(int unit, soc_mem_t mem) 3911 { 3912 _SOC_MEM_REPLACE_MEM(unit, mem); 3913 3914 return soc_mem_index_count(unit, mem); 3915 } 3916 3917 #endif /* BCM_XGS_SWITCH_SUPPORT */ 3918 3919 /* 3920 * Function: 3921 * soc_mem_index_last 3922 * Purpose: 3923 * Compute the highest index currently occupied in a sorted table 3924 */ 3925 3926 int 3927 soc_mem_index_last(int unit, soc_mem_t mem, int copyno) 3928 { 3929 assert(SOC_MEM_IS_VALID(unit, mem)); 3930 assert(soc_attached(unit)); 3931 assert(soc_mem_is_sorted(unit,mem)); 3932 3933 if (copyno == MEM_BLOCK_ANY) { 3934 /* coverity[overrun-local : FALSE] */ 3935 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 3936 } 3937 3938 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 3939 /* coverity[overrun-local : FALSE] */ 3940 return (SOC_MEM_INFO(unit, mem).index_min + 3941 SOP_MEM_STATE(unit, mem).count[copyno] - 1); 3942 } 3943 3944 3945 /* 3946 * Function: 3947 * soc_mem_entry_dump 3948 * Purpose: 3949 * Debug routine to dump a formatted table entry. 3950 * 3951 * Note: Prefix != NULL : Dump chg command 3952 * Prefix == NULL : Dump command 3953 * (Actually should pass dump_chg flag but keeping for simplicity) 3954 */ 3955 STATIC void 3956 _soc_mem_entry_dump_common(int unit, soc_mem_t mem, void *buf, char *prefix, int vertical, char *field_names, uint32 bsl_flags) 3957 { 3958 soc_mem_info_t *memp; 3959 char dummy[]=""; 3960 char *mem_prefix=dummy; 3961 int first_print_flag=0; 3962 3963 #if !defined(SOC_NO_NAMES) 3964 int f; 3965 soc_field_info_t *fieldp; 3966 char temp_field_name[80]; 3967 uint32 default_type = 0; 3968 uint32 key_type = 0; 3969 uint32 *fval; 3970 uint32 *nfval; 3971 char *tmp; 3972 uint32 *buf_ptr; 3973 int alloc_size; 3974 char *split = NULL; 3975 char *save_str = NULL; 3976 char *dup_field_names = NULL; 3977 uint8 match_found = 0; 3978 uint32 dup_fld_names_len = 0; 3979 uint32 temp_fld_name_len = 0; 3980 #endif 3981 3982 memp = &SOC_MEM_INFO(unit, mem); 3983 if (prefix != NULL) { 3984 mem_prefix = prefix; 3985 } 3986 3987 if (!SOC_MEM_IS_VALID(unit, mem)) { 3988 BSL_LOG(bsl_flags, (BSL_META_U(unit, 3989 "<%s:%d>Memory not valid for unit\n"),mem_prefix,mem)); 3990 return; 3991 } 3992 #if !defined(SOC_NO_NAMES) 3993 alloc_size = (2*SOC_MAX_MEM_FIELD_WORDS) * sizeof(uint32) + 3994 (SOC_MAX_MEM_FIELD_WORDS * 8) + 3; 3995 buf_ptr = sal_alloc(alloc_size, "Temp. buffer for _soc_mem_entry_dump_common"); 3996 sal_memset((void *)buf_ptr,0,alloc_size); 3997 fval = buf_ptr; 3998 nfval = buf_ptr + SOC_MAX_MEM_FIELD_WORDS; 3999 tmp = (char *)(buf_ptr + 2 * SOC_MAX_MEM_FIELD_WORDS); 4000 4001 if ((memp->flags & SOC_MEM_FLAG_MULTIVIEW) 4002 #if defined(BCM_SAND_SUPPORT) 4003 && (!SOC_IS_SAND(unit)) 4004 #endif 4005 ) { 4006 #ifdef KEY_TYPEf 4007 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 4008 soc_mem_field_get(unit, mem, buf, KEY_TYPEf, &key_type); 4009 } else if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPE_0f)) { 4010 soc_mem_field_get(unit, mem, buf, KEY_TYPE_0f, &key_type); 4011 } else if (SOC_MEM_FIELD_VALID(unit, mem, VP_TYPEf)) { 4012 soc_mem_field_get(unit, mem, buf, VP_TYPEf, &key_type); 4013 } else if (SOC_MEM_FIELD_VALID(unit, mem, ENTRY_TYPEf)) { 4014 soc_mem_field_get(unit, mem, buf, ENTRY_TYPEf, &key_type); 4015 } else if (SOC_MEM_FIELD_VALID(unit, mem, MODEf)) { 4016 soc_mem_field_get(unit, mem, buf, MODEf, &key_type); 4017 } else if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 4018 soc_mem_field_get(unit, mem, buf, DATA_TYPEf, &key_type); 4019 } 4020 #endif 4021 default_type = 0; 4022 #if defined(BCM_TRIUMPH2_SUPPORT) 4023 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 4024 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || 4025 SOC_IS_HURRICANE(unit) || SOC_IS_TD_TT(unit) || 4026 SOC_IS_KATANA(unit)) { 4027 if((mem == VLAN_MACm) || 4028 (mem == L3_ENTRY_IPV4_MULTICASTm) || 4029 (mem == L3_ENTRY_IPV6_UNICASTm) || 4030 (mem == L3_ENTRY_IPV6_MULTICASTm) || 4031 (mem == EXACT_MATCH_4m) || 4032 (mem == EXACT_MATCH_4_ENTRY_ONLYm)) { 4033 default_type = key_type; 4034 } 4035 } 4036 #endif /* BCM_TRIUMPH2_SUPPORT */ 4037 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 4038 if ((mem == L2_BULK_MATCH_MASKm) || 4039 (mem == L2_BULK_REPLACE_MASKm)) { 4040 if (SOC_IS_KATANA(unit) && 4041 (key_type > KATANA_L2X_VIEW_ARRAY_MAX_INDEX)) { 4042 key_type = KATANA_L2X_VIEW_ARRAY_MAX_INDEX; 4043 } else if (SOC_IS_KATANA2(unit) && 4044 (key_type > KATANA2_L2X_VIEW_ARRAY_MAX_INDEX)) { 4045 key_type = KATANA2_L2X_VIEW_ARRAY_MAX_INDEX; 4046 } else if (SOC_IS_TRIDENT2(unit) && 4047 (key_type > TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX)) { 4048 key_type = TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX; 4049 } else if ((SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit)) && 4050 (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) { 4051 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX; 4052 } 4053 } 4054 #endif 4055 4056 #ifdef BCM_TOMAHAWK_SUPPORT 4057 if (mem == L2_BULKm) { 4058 if (SOC_IS_TOMAHAWKX(unit) && 4059 (key_type > TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX)) { 4060 key_type = TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX; 4061 } else if ((SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TRIDENT3X(unit)) && 4062 (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) { 4063 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX; 4064 } 4065 } 4066 #endif 4067 4068 #ifdef BCM_TRIDENT3_SUPPORT 4069 if (mem == L2Xm || mem == L2_ENTRY_SINGLEm || mem == L2_ENTRY_ONLY_SINGLEm) { 4070 if (SOC_IS_TRIDENT3X(unit) && 4071 (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) { 4072 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX; 4073 } 4074 } 4075 #endif 4076 4077 #ifdef BCM_TRIDENT2_SUPPORT 4078 if (mem == L2_LEARN_INSERT_FAILUREm) { 4079 if (SOC_IS_TRIDENT2(unit) && 4080 (key_type > TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX)) { 4081 key_type = TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX; 4082 } if ((SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TITAN2PLUS(unit) || 4083 SOC_IS_TRIDENT3X(unit)) && 4084 (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) { 4085 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX; 4086 } else if (SOC_IS_TOMAHAWKX(unit) && 4087 (key_type > TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX)) { 4088 key_type = TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX; 4089 } 4090 } 4091 #endif 4092 4093 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 4094 4095 if ((mem == L3_TUNNELm) || (mem == L3_TUNNEL_ONLYm)) { 4096 if (SOC_IS_KATANA2(unit) || 4097 SOC_IS_APACHE(unit)) { 4098 key_type++; 4099 } 4100 } 4101 #endif 4102 4103 #if defined(BCM_TRIUMPH3_SUPPORT) 4104 if (SOC_IS_TRIUMPH3(unit)) { 4105 if (mem == L3_TUNNELm) { 4106 if (key_type == 1) { 4107 /* 4108 * In TR3 reg file, field names are defined for 4109 * "IP" view which is common for IPv6 & IPv4. 4110 * So, IPv6 (key type 1) entries use same field 4111 * names as those of IPv4 (keytype 0) entries 4112 */ 4113 key_type = 0; 4114 } 4115 } 4116 } 4117 #endif /* BCM_TRIUMPH3_SUPPORT */ 4118 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 4119 if (SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit)) { 4120 if ((mem == L3_TUNNELm) || (mem == L3_TUNNEL_ONLYm)) { 4121 if ((key_type == 0) || (key_type == 1)) { 4122 /* 4123 * In TH2 reg file, field names are defined for 4124 * "IP" view which is common for IPv6 & IPv4. 4125 * So, IPv6 (key type 1) entries use same field 4126 * names as those of IPv4 (keytype 0) entries 4127 */ 4128 key_type = 0; 4129 } else { 4130 key_type++; 4131 } 4132 } 4133 } 4134 #endif 4135 4136 #if defined(BCM_GREYHOUND2_SUPPORT) 4137 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 4138 if (mem == L2Xm) { 4139 if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) { 4140 key_type = GH2_L2_HASH_KEY_TYPE_VFI; 4141 } 4142 } 4143 } 4144 #endif /* BCM_GREYHOUND2_SUPPORT */ 4145 4146 if ((key_type >= *memp->views_num) || 4147 (sal_strlen(memp->views[key_type]) == 0)) { 4148 BSL_LOG(bsl_flags, (BSL_META_U(unit, 4149 "<Wrong Key_type %d>\n"),key_type)); 4150 sal_free(buf_ptr); 4151 return; 4152 } 4153 } 4154 4155 if (NULL != field_names) { 4156 dup_fld_names_len = sal_strlen(field_names) + 1; 4157 dup_field_names = sal_alloc(dup_fld_names_len, "DupFieldNames"); 4158 if (NULL == dup_field_names) { 4159 BSL_LOG(bsl_flags, (BSL_META_U(unit, "<Memory alloc failure>\n"))); 4160 sal_free(buf_ptr); 4161 return; 4162 } 4163 } 4164 4165 for (f = memp->nFields - 1; f >= 0; f--) { 4166 fieldp = &memp->fields[f]; 4167 if ((memp->flags & SOC_MEM_FLAG_MULTIVIEW) 4168 #if defined(BCM_SAND_SUPPORT) 4169 && (!SOC_IS_SAND(unit)) 4170 #endif 4171 ) { 4172 if (!(strstr(soc_fieldnames[fieldp->field], memp->views[key_type]) || 4173 (strcmp(memp->views[key_type], memp->views[default_type]) == 0 4174 && !strstr(soc_fieldnames[fieldp->field], ":")) || 4175 (fieldp->flags & SOCF_GLOBAL))) { 4176 continue; 4177 } 4178 } 4179 if (field_names != NULL) { 4180 save_str = NULL; 4181 match_found = 0; 4182 4183 sal_memset(temp_field_name, 0x0, sizeof(temp_field_name)); 4184 sal_strncpy(temp_field_name, 4185 soc_fieldnames[fieldp->field], sizeof(temp_field_name) - 1); 4186 temp_fld_name_len = sal_strlen(temp_field_name); 4187 sal_strncpy(dup_field_names, field_names, dup_fld_names_len); 4188 4189 split = sal_strtok_r(dup_field_names, ",", &save_str); 4190 while (split) { 4191 4192 /* Firstly, check if the field names are matching */ 4193 if (!sal_strncmp(temp_field_name, split, temp_fld_name_len)) { 4194 /* Secondly, check if the field name lengths are same */ 4195 if (temp_fld_name_len == sal_strlen(split)) { 4196 match_found = 1; 4197 break; 4198 } 4199 } 4200 split = sal_strtok_r(NULL, ",", &save_str); 4201 } 4202 4203 if (!match_found) { 4204 continue; 4205 } 4206 } 4207 4208 sal_memset(fval, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 4209 soc_mem_field_get(unit, mem, buf, fieldp->field, fval); 4210 if (mem_prefix == prefix) { 4211 if (sal_memcmp(fval, nfval, SOC_MAX_MEM_FIELD_WORDS * 4212 sizeof (uint32)) == 0) { 4213 continue; 4214 } 4215 } 4216 if (first_print_flag == 0) { 4217 BSL_LOG(bsl_flags, (BSL_META_U(unit, 4218 "%s%s"), mem_prefix, vertical ? "" : "<")); 4219 first_print_flag=1; 4220 } 4221 if (vertical) { 4222 _shr_format_long_integer(tmp, fval, BITS2BYTES(fieldp->len)); 4223 BSL_LOG(bsl_flags, (BSL_META_U(unit, 4224 "\n\t%30s: %s"), soc_fieldnames[fieldp->field], tmp)); 4225 } else { 4226 _shr_format_long_integer(tmp, fval, BITS2BYTES(fieldp->len)); 4227 BSL_LOG(bsl_flags, (BSL_META_U(unit, 4228 "%s=%s%s"), soc_fieldnames[fieldp->field], 4229 tmp, f > 0 ? "," : "")); 4230 } 4231 } 4232 4233 if (NULL != dup_field_names) { 4234 sal_free(dup_field_names); 4235 } 4236 sal_free(buf_ptr); 4237 #endif 4238 if (first_print_flag == 1) { 4239 BSL_LOG(bsl_flags, (BSL_META_U(unit, 4240 "%s\n"), vertical ? "" : ">")); 4241 } 4242 } 4243 4244 STATIC void 4245 soc_mem_entry_dump_common(int unit, soc_mem_t mem, void *buf, char *prefix, int vertical, char *field_names, uint32 bsl_flags) 4246 { 4247 #ifdef BCM_TRIDENT3_SUPPORT 4248 int rv; 4249 soc_mem_t mem_view_id; 4250 soc_mem_t flex_mem; 4251 uint32 data_type = 0; 4252 uint32 key_type = 0; 4253 soc_flow_db_ctrl_field_t ctrl_field[2]; 4254 int num_ctrl_fields = 0; 4255 #endif 4256 4257 /* call memory view entry dump for all flex views */ 4258 #ifdef BCM_TRIDENT3_SUPPORT 4259 if (soc_feature(unit, soc_feature_flex_flow)) { 4260 if (mem == L2Xm || mem == L2_ENTRY_SINGLEm || 4261 mem == L2_ENTRY_ONLY_SINGLEm) { 4262 flex_mem = L2_ENTRY_SINGLEm; /* flex L2 memory name */ 4263 } else { 4264 flex_mem = mem; 4265 } 4266 if (SOC_MEM_FIELD_VALID(unit, flex_mem, DATA_TYPE0f)) { 4267 data_type = soc_mem_field32_get(unit, flex_mem, buf, DATA_TYPE0f); 4268 } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, DATA_TYPEf)) { 4269 data_type = soc_mem_field32_get(unit, flex_mem, buf, DATA_TYPEf); 4270 } 4271 if (SOC_MEM_FIELD_VALID(unit, flex_mem, KEY_TYPE0f)) { 4272 key_type = soc_mem_field32_get(unit, flex_mem, buf, KEY_TYPE0f); 4273 } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, KEY_TYPEf)) { 4274 key_type = soc_mem_field32_get(unit, flex_mem, buf, KEY_TYPEf); 4275 } 4276 if (SOC_MEM_FIELD_VALID(unit, flex_mem, FLOW_SELECT_CTRL_IDf)) { 4277 ctrl_field[num_ctrl_fields].field_id = FLOW_SELECT_CTRL_IDf; 4278 ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 4279 flex_mem, buf, FLOW_SELECT_CTRL_IDf); 4280 num_ctrl_fields++; 4281 } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, FLEX__FLOW_SELECT_CTRL_IDf)) { 4282 ctrl_field[num_ctrl_fields].field_id = FLOW_SELECT_CTRL_IDf; 4283 ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 4284 flex_mem, buf, FLEX__FLOW_SELECT_CTRL_IDf); 4285 num_ctrl_fields++; 4286 } 4287 4288 if (SOC_MEM_FIELD_VALID(unit, flex_mem, EDIT_CTRL_IDf)) { 4289 ctrl_field[num_ctrl_fields].field_id = EDIT_CTRL_IDf; 4290 ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 4291 flex_mem, buf, EDIT_CTRL_IDf); 4292 num_ctrl_fields++; 4293 } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, FLEX__EDIT_CTRL_IDf)) { 4294 ctrl_field[num_ctrl_fields].field_id = EDIT_CTRL_IDf; 4295 ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 4296 flex_mem, buf, FLEX__EDIT_CTRL_IDf); 4297 num_ctrl_fields++; 4298 } 4299 4300 if (!key_type) { 4301 rv = soc_flow_db_mem_to_view_id_get (unit, flex_mem, 4302 SOC_FLOW_DB_KEY_TYPE_INVALID, data_type, 4303 num_ctrl_fields, 4304 num_ctrl_fields? ctrl_field: NULL, 4305 (uint32 *)&mem_view_id); 4306 } else { 4307 rv = soc_flow_db_mem_to_view_id_get (unit, flex_mem, key_type, 4308 data_type, 4309 num_ctrl_fields, 4310 num_ctrl_fields? ctrl_field: NULL, 4311 (uint32 *)&mem_view_id); 4312 } 4313 4314 if (SOC_SUCCESS(rv)) { 4315 if (soc_flow_db_mem_view_is_valid(unit, mem_view_id)) { 4316 _soc_mem_view_entry_dump_common(unit, mem_view_id, buf, prefix, vertical, bsl_flags); 4317 return; 4318 } 4319 } 4320 } 4321 #endif 4322 /* default memory entry dump for all fixed memory views */ 4323 _soc_mem_entry_dump_common(unit, mem, buf, prefix, vertical, field_names, bsl_flags); 4324 } 4325 4326 void 4327 soc_mem_entry_dump_fields(int unit, soc_mem_t mem, void *buf, char *field_names) 4328 { 4329 soc_mem_entry_dump_common(unit, mem, buf, NULL, 0, field_names, BSL_LSS_CLI); 4330 } 4331 void 4332 soc_mem_entry_dump(int unit, soc_mem_t mem, void *buf, uint32 bsl_flags) 4333 { 4334 soc_mem_entry_dump_common(unit, mem, buf, NULL, 0, NULL, bsl_flags); 4335 } 4336 void 4337 soc_mem_entry_dump_vertical(int unit, soc_mem_t mem, void *buf) 4338 { 4339 soc_mem_entry_dump_common(unit, mem, buf, NULL, 1, NULL, BSL_LSS_CLI); 4340 } 4341 void 4342 soc_mem_entry_dump_if_changed(int unit, soc_mem_t mem, void *buf, char *prefix) 4343 { 4344 soc_mem_entry_dump_common(unit, mem, buf, prefix, 0, NULL, BSL_LSS_CLI); 4345 } 4346 void 4347 soc_mem_entry_dump_if_changed_fields(int unit, soc_mem_t mem, void *buf, 4348 char *prefix, char *field_names) 4349 { 4350 soc_mem_entry_dump_common(unit, mem, buf, prefix, 0, field_names, BSL_LSS_CLI); 4351 } 4352 4353 /************************************************************************/ 4354 /* Routines for configuring the table memory caches */ 4355 /************************************************************************/ 4356 4357 /* 4358 * Function: 4359 * soc_mem_cache_get 4360 * Purpose: 4361 * Return whether or not caching is enabled for a specified memory 4362 * or memories 4363 */ 4364 4365 int 4366 soc_mem_cache_get(int unit, soc_mem_t mem, int copyno) 4367 { 4368 int rv; 4369 4370 assert(SOC_UNIT_VALID(unit)); 4371 _SOC_MEM_REUSE_MEM_STATE(unit, mem); 4372 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 4373 assert(SOC_MEM_IS_VALID(unit, mem)); 4374 4375 if (!soc_mem_is_cachable(unit, mem) || SOC_MEM_TEST_SKIP_CACHE(unit)) { 4376 return FALSE; 4377 } 4378 4379 MEM_LOCK(unit, mem); 4380 4381 if (copyno == SOC_BLOCK_ALL) { 4382 rv = TRUE; 4383 SOC_MEM_BLOCK_ITER(unit, mem, copyno) { 4384 rv = (rv && (SOC_MEM_STATE(unit, mem).cache[copyno] != NULL)); 4385 } 4386 } else { 4387 rv = (SOC_MEM_STATE(unit, mem).cache[copyno] != NULL); 4388 } 4389 4390 MEM_UNLOCK(unit, mem); 4391 4392 return rv; 4393 } 4394 4395 #if defined(BCM_TOMAHAWK_SUPPORT) 4396 void 4397 _soc_mem_fpem_entry_cache_entry_validate(int unit, soc_mem_t mem, uint32 *entry, 4398 uint8 *vmap, int *index) 4399 { 4400 int vldf = VALID_0f; 4401 int keyf = KEY_TYPE_0f; 4402 4403 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 4404 if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) { 4405 vldf = BASE_VALID_0f; 4406 keyf = KEY_TYPEf; 4407 } 4408 #endif /* BCM_TRIDENT3_SUPPORT or BCM_TOMAHAWK3_SUPPORT */ 4409 switch (mem) { 4410 case EXACT_MATCH_2m: 4411 case EXACT_MATCH_2_PIPE0m: 4412 case EXACT_MATCH_2_PIPE1m: 4413 case EXACT_MATCH_2_PIPE2m: 4414 case EXACT_MATCH_2_PIPE3m: 4415 if (!soc_mem_field32_get(unit, EXACT_MATCH_2m, entry, 4416 vldf)) { 4417 CACHE_VMAP_CLR(vmap, *index); 4418 break; 4419 } 4420 switch(soc_mem_field32_get(unit, EXACT_MATCH_2m, entry, keyf)) { 4421 case TH_FPEM_HASH_KEY_TYPE_320B: 4422 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4423 CACHE_VMAP_CLR(vmap, *index); 4424 break; 4425 case TH_FPEM_HASH_KEY_TYPE_128B: 4426 case TH_FPEM_HASH_KEY_TYPE_160B: 4427 /* let vmap bit remain set */ 4428 break; 4429 default: /* illegal key_type */ 4430 CACHE_VMAP_CLR(vmap, *index); 4431 break; 4432 } 4433 break; 4434 4435 case EXACT_MATCH_4m: 4436 case EXACT_MATCH_4_PIPE0m: 4437 case EXACT_MATCH_4_PIPE1m: 4438 case EXACT_MATCH_4_PIPE2m: 4439 case EXACT_MATCH_4_PIPE3m: 4440 if (!soc_mem_field32_get(unit, EXACT_MATCH_4m, entry, 4441 vldf)) { 4442 CACHE_VMAP_CLR(vmap, *index); 4443 break; 4444 } 4445 if (TH_FPEM_HASH_KEY_TYPE_320B != 4446 soc_mem_field32_get(unit, EXACT_MATCH_4m, entry, 4447 keyf)) { 4448 CACHE_VMAP_CLR(vmap, *index); 4449 } 4450 break; 4451 4452 default: 4453 break; 4454 } 4455 } 4456 #endif /* BCM_TOMAHAWK_SUPPORT */ 4457 4458 void 4459 _soc_mem_l3_entry_cache_entry_validate(int unit, soc_mem_t mem, uint32 *entry, 4460 uint8 *vmap, int *index) 4461 { 4462 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) { 4463 #ifdef BCM_TRIDENT2_SUPPORT 4464 if (SOC_IS_TD2_TT2(unit)) { 4465 #ifdef BCM_TOMAHAWK_SUPPORT 4466 if (SOC_IS_TOMAHAWKX(unit)) { 4467 switch (mem) { 4468 case L3_ENTRY_ONLYm: 4469 case L3_ENTRY_IPV4_UNICASTm: 4470 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4471 CACHE_VMAP_CLR(vmap, *index); 4472 break; 4473 } 4474 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4475 case TH_L3_HASH_KEY_TYPE_V4MC: 4476 case TH_L3_HASH_KEY_TYPE_V4UC_EXT: 4477 case TH_L3_HASH_KEY_TYPE_DST_NAT: 4478 case TH_L3_HASH_KEY_TYPE_DST_NAPT: 4479 case TH_L3_HASH_KEY_TYPE_V6UC: 4480 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4481 CACHE_VMAP_CLR(vmap, *index); 4482 break; 4483 case TH_L3_HASH_KEY_TYPE_V6MC: 4484 case TH_L3_HASH_KEY_TYPE_V6UC_EXT: 4485 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4486 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4487 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4488 CACHE_VMAP_CLR(vmap, *index); 4489 break; 4490 case TH_L3_HASH_KEY_TYPE_V4UC: 4491 case TH_L3_HASH_KEY_TYPE_TRILL: 4492 /* let vmap bit remain set */ 4493 break; 4494 default: /* illegal key_type */ 4495 CACHE_VMAP_CLR(vmap, *index); 4496 break; 4497 } 4498 break; 4499 case L3_ENTRY_IPV4_MULTICASTm: 4500 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4501 CACHE_VMAP_CLR(vmap, *index); 4502 break; 4503 } 4504 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4505 case TH_L3_HASH_KEY_TYPE_V4UC: 4506 case TH_L3_HASH_KEY_TYPE_TRILL: 4507 case TH_L3_HASH_KEY_TYPE_V6UC: 4508 CACHE_VMAP_CLR(vmap, *index); 4509 break; 4510 case TH_L3_HASH_KEY_TYPE_V6MC: 4511 case TH_L3_HASH_KEY_TYPE_V6UC_EXT: 4512 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4513 CACHE_VMAP_CLR(vmap, *index); 4514 break; 4515 case TH_L3_HASH_KEY_TYPE_V4MC: 4516 case TH_L3_HASH_KEY_TYPE_V4UC_EXT: 4517 case TH_L3_HASH_KEY_TYPE_DST_NAT: 4518 case TH_L3_HASH_KEY_TYPE_DST_NAPT: 4519 /* let vmap bit remain set */ 4520 break; 4521 default: /* illegal key_type */ 4522 CACHE_VMAP_CLR(vmap, *index); 4523 break; 4524 } 4525 break; 4526 case L3_ENTRY_IPV6_UNICASTm: 4527 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4528 CACHE_VMAP_CLR(vmap, *index); 4529 break; 4530 } 4531 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4532 case TH_L3_HASH_KEY_TYPE_V4UC: 4533 case TH_L3_HASH_KEY_TYPE_TRILL: 4534 case TH_L3_HASH_KEY_TYPE_V4MC: 4535 case TH_L3_HASH_KEY_TYPE_V4UC_EXT: 4536 case TH_L3_HASH_KEY_TYPE_DST_NAT: 4537 case TH_L3_HASH_KEY_TYPE_DST_NAPT: 4538 CACHE_VMAP_CLR(vmap, *index); 4539 break; 4540 case TH_L3_HASH_KEY_TYPE_V6MC: 4541 case TH_L3_HASH_KEY_TYPE_V6UC_EXT: 4542 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4543 CACHE_VMAP_CLR(vmap, *index); 4544 break; 4545 case TH_L3_HASH_KEY_TYPE_V6UC: 4546 /* let vmap bit remain set */ 4547 break; 4548 default: /* illegal key_type */ 4549 CACHE_VMAP_CLR(vmap, *index); 4550 break; 4551 } 4552 break; 4553 case L3_ENTRY_IPV6_MULTICASTm: 4554 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4555 CACHE_VMAP_CLR(vmap, *index); 4556 break; 4557 } 4558 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4559 case TH_L3_HASH_KEY_TYPE_V6MC: 4560 case TH_L3_HASH_KEY_TYPE_V6UC_EXT: 4561 break; 4562 default: 4563 CACHE_VMAP_CLR(vmap, *index); 4564 break; 4565 } 4566 break; 4567 default: 4568 break; 4569 } 4570 } else 4571 #endif /* BCM_TOMAHAWK_SUPPORT */ 4572 { 4573 switch (mem) { 4574 case L3_ENTRY_ONLYm: 4575 case L3_ENTRY_IPV4_UNICASTm: 4576 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4577 CACHE_VMAP_CLR(vmap, *index); 4578 break; 4579 } 4580 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4581 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 4582 case TD2_L3_HASH_KEY_TYPE_V4MC: 4583 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 4584 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 4585 case TD2_L3_HASH_KEY_TYPE_V6UC: 4586 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 4587 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 4588 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 4589 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 4590 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 4591 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4592 CACHE_VMAP_CLR(vmap, *index); 4593 break; 4594 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 4595 case TD2_L3_HASH_KEY_TYPE_V6MC: 4596 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 4597 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 4598 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4599 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4600 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4601 CACHE_VMAP_CLR(vmap, *index); 4602 break; 4603 case TD2_L3_HASH_KEY_TYPE_V4UC: 4604 case TD2_L3_HASH_KEY_TYPE_TRILL: 4605 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 4606 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 4607 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 4608 /* let vmap bit remain set */ 4609 break; 4610 default: /* illegal key_type */ 4611 CACHE_VMAP_CLR(vmap, *index); 4612 break; 4613 } 4614 break; 4615 case L3_ENTRY_IPV4_MULTICASTm: 4616 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4617 CACHE_VMAP_CLR(vmap, *index); 4618 break; 4619 } 4620 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4621 case TD2_L3_HASH_KEY_TYPE_V4UC: 4622 case TD2_L3_HASH_KEY_TYPE_TRILL: 4623 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 4624 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 4625 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 4626 case TD2_L3_HASH_KEY_TYPE_V6UC: 4627 CACHE_VMAP_CLR(vmap, *index); 4628 break; 4629 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 4630 case TD2_L3_HASH_KEY_TYPE_V6MC: 4631 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 4632 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 4633 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4634 CACHE_VMAP_CLR(vmap, *index); 4635 break; 4636 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 4637 case TD2_L3_HASH_KEY_TYPE_V4MC: 4638 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 4639 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 4640 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 4641 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 4642 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 4643 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 4644 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 4645 /* let vmap bit remain set */ 4646 break; 4647 default: /* illegal key_type */ 4648 CACHE_VMAP_CLR(vmap, *index); 4649 break; 4650 } 4651 break; 4652 case L3_ENTRY_IPV6_UNICASTm: 4653 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4654 CACHE_VMAP_CLR(vmap, *index); 4655 break; 4656 } 4657 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4658 case TD2_L3_HASH_KEY_TYPE_V4UC: 4659 case TD2_L3_HASH_KEY_TYPE_TRILL: 4660 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 4661 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 4662 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 4663 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 4664 case TD2_L3_HASH_KEY_TYPE_V4MC: 4665 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 4666 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 4667 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 4668 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 4669 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 4670 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 4671 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 4672 CACHE_VMAP_CLR(vmap, *index); 4673 break; 4674 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 4675 case TD2_L3_HASH_KEY_TYPE_V6MC: 4676 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 4677 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 4678 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4679 CACHE_VMAP_CLR(vmap, *index); 4680 break; 4681 case TD2_L3_HASH_KEY_TYPE_V6UC: 4682 /* let vmap bit remain set */ 4683 break; 4684 default: /* illegal key_type */ 4685 CACHE_VMAP_CLR(vmap, *index); 4686 break; 4687 } 4688 break; 4689 case L3_ENTRY_IPV6_MULTICASTm: 4690 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4691 CACHE_VMAP_CLR(vmap, *index); 4692 break; 4693 } 4694 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4695 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 4696 case TD2_L3_HASH_KEY_TYPE_V6MC: 4697 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 4698 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 4699 /* let vmap bit remain set */ 4700 break; 4701 default: 4702 CACHE_VMAP_CLR(vmap, *index); 4703 break; 4704 } 4705 break; 4706 default: 4707 break; 4708 } 4709 } 4710 } else 4711 #endif /* BCM_TRIDENT2_SUPPORT */ 4712 { 4713 switch (mem) { 4714 case L3_ENTRY_ONLYm: 4715 case L3_ENTRY_IPV4_UNICASTm: 4716 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4717 CACHE_VMAP_CLR(vmap, *index); 4718 break; 4719 } 4720 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4721 case TR_L3_HASH_KEY_TYPE_V4MC: 4722 case TR_L3_HASH_KEY_TYPE_V6UC: 4723 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4724 CACHE_VMAP_CLR(vmap, *index); 4725 break; 4726 case TR_L3_HASH_KEY_TYPE_V6MC: 4727 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4728 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4729 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4730 CACHE_VMAP_CLR(vmap, *index); 4731 break; 4732 default: 4733 break; 4734 } 4735 break; 4736 case L3_ENTRY_IPV4_MULTICASTm: 4737 case L3_ENTRY_IPV6_UNICASTm: 4738 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4739 CACHE_VMAP_CLR(vmap, *index); 4740 break; 4741 } 4742 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4743 case TR_L3_HASH_KEY_TYPE_V4UC: 4744 case TR_L3_HASH_KEY_TYPE_LMEP: 4745 case TR_L3_HASH_KEY_TYPE_RMEP: 4746 case TR_L3_HASH_KEY_TYPE_TRILL: 4747 CACHE_VMAP_CLR(vmap, *index); 4748 break; 4749 case TR_L3_HASH_KEY_TYPE_V4MC: 4750 if (mem == L3_ENTRY_IPV6_UNICASTm) { 4751 CACHE_VMAP_CLR(vmap, *index); 4752 } 4753 break; 4754 case TR_L3_HASH_KEY_TYPE_V6UC: 4755 if (mem == L3_ENTRY_IPV4_MULTICASTm) { 4756 CACHE_VMAP_CLR(vmap, *index); 4757 } 4758 break; 4759 case TR_L3_HASH_KEY_TYPE_V6MC: 4760 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4761 CACHE_VMAP_CLR(vmap, *index); 4762 break; 4763 default: 4764 break; 4765 } 4766 break; 4767 case L3_ENTRY_IPV6_MULTICASTm: 4768 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) { 4769 CACHE_VMAP_CLR(vmap, *index); 4770 break; 4771 } 4772 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) { 4773 case TR_L3_HASH_KEY_TYPE_V6MC: 4774 break; 4775 default: 4776 CACHE_VMAP_CLR(vmap, *index); 4777 break; 4778 } 4779 break; 4780 default: 4781 break; 4782 } 4783 } 4784 } 4785 #ifdef BCM_TRIUMPH3_SUPPORT 4786 else if (SOC_MEM_IS_VALID(unit, L3_ENTRY_1m)) { 4787 switch (mem) { 4788 case L3_ENTRY_1m: 4789 if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) { 4790 CACHE_VMAP_CLR(vmap, *index); 4791 break; 4792 } 4793 switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPEf)) { 4794 case SOC_MEM_VIEW_L3_ENTRY_2_IPV4UC: 4795 case SOC_MEM_VIEW_L3_ENTRY_2_IPV4MC: 4796 case SOC_MEM_VIEW_L3_ENTRY_2_IPV6UC: 4797 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4798 CACHE_VMAP_CLR(vmap, *index); 4799 break; 4800 case SOC_MEM_VIEW_L3_ENTRY_4_IPV6UC: 4801 case SOC_MEM_VIEW_L3_ENTRY_4_IPV6MC: 4802 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4803 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4804 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4805 CACHE_VMAP_CLR(vmap, *index); 4806 break; 4807 default: 4808 break; 4809 } 4810 break; 4811 case L3_ENTRY_2m: 4812 if (!soc_mem_field32_get(unit, mem, entry, VALID_0f)) { 4813 CACHE_VMAP_CLR(vmap, *index); 4814 break; 4815 } 4816 switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f)) { 4817 case SOC_MEM_VIEW_L3_ENTRY_2_IPV4UC: 4818 case SOC_MEM_VIEW_L3_ENTRY_2_IPV4MC: 4819 case SOC_MEM_VIEW_L3_ENTRY_2_IPV6UC: 4820 CACHE_VMAP_CLR(vmap, *index); 4821 break; 4822 case SOC_MEM_VIEW_L3_ENTRY_4_IPV6UC: 4823 case SOC_MEM_VIEW_L3_ENTRY_4_IPV6MC: 4824 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4825 CACHE_VMAP_CLR(vmap, *index); 4826 break; 4827 default: 4828 break; 4829 } 4830 break; 4831 case L3_ENTRY_4m: 4832 if (!soc_mem_field32_get(unit, mem, entry, VALID_0f)) { 4833 CACHE_VMAP_CLR(vmap, *index); 4834 break; 4835 } 4836 switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f)) { 4837 case SOC_MEM_VIEW_L3_ENTRY_4_IPV6UC: 4838 case SOC_MEM_VIEW_L3_ENTRY_4_IPV6MC: 4839 break; 4840 default: 4841 CACHE_VMAP_CLR(vmap, *index); 4842 break; 4843 } 4844 break; 4845 default: 4846 break; 4847 } 4848 } 4849 #endif /* BCM_TRIUMPH3_SUPPORT */ 4850 #ifdef BCM_TOMAHAWK3_SUPPORT 4851 else if (SOC_IS_TOMAHAWK3(unit)) { 4852 switch (mem) { 4853 case L3_ENTRY_SINGLEm: 4854 case L3_ENTRY_ONLY_SINGLEm: 4855 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, BASE_VALIDf)) { 4856 CACHE_VMAP_CLR(vmap, *index); 4857 break; 4858 } 4859 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, KEY_TYPEf)) { 4860 case TH3_L3_HASH_KEY_TYPE_V4MC: 4861 case TH3_L3_HASH_KEY_TYPE_V6UC: 4862 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4863 CACHE_VMAP_CLR(vmap, *index); 4864 break; 4865 case TH3_L3_HASH_KEY_TYPE_V6MC: 4866 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4867 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4868 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4869 CACHE_VMAP_CLR(vmap, *index); 4870 break; 4871 case TH3_L3_HASH_KEY_TYPE_V4UC: 4872 /* let vmap bit remain set */ 4873 break; 4874 default: /* illegal key_type */ 4875 CACHE_VMAP_CLR(vmap, *index); 4876 break; 4877 } 4878 break; 4879 case L3_ENTRY_DOUBLEm: 4880 case L3_ENTRY_ONLY_DOUBLEm: 4881 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, BASE_VALID_0f)) { 4882 CACHE_VMAP_CLR(vmap, *index); 4883 break; 4884 } 4885 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, KEY_TYPEf)) { 4886 case TH3_L3_HASH_KEY_TYPE_V4UC: 4887 CACHE_VMAP_CLR(vmap, *index); 4888 break; 4889 case TH3_L3_HASH_KEY_TYPE_V6MC: 4890 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4891 CACHE_VMAP_CLR(vmap, *index); 4892 break; 4893 case TH3_L3_HASH_KEY_TYPE_V4MC: 4894 case TH3_L3_HASH_KEY_TYPE_V6UC: 4895 /* let vmap bit remain set */ 4896 break; 4897 default: /* illegal key_type */ 4898 CACHE_VMAP_CLR(vmap, *index); 4899 break; 4900 } 4901 break; 4902 case L3_ENTRY_QUADm: 4903 case L3_ENTRY_ONLY_QUADm: 4904 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, BASE_VALID_0f)) { 4905 CACHE_VMAP_CLR(vmap, *index); 4906 break; 4907 } 4908 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, KEY_TYPEf)) { 4909 case TH3_L3_HASH_KEY_TYPE_V6MC: 4910 break; 4911 default: 4912 CACHE_VMAP_CLR(vmap, *index); 4913 break; 4914 } 4915 break; 4916 default: 4917 break; 4918 } 4919 } 4920 #endif 4921 #ifdef BCM_TRIDENT3_SUPPORT 4922 else if (SOC_MEM_IS_VALID(unit, L3_ENTRY_ONLY_SINGLEm) || 4923 SOC_MEM_IS_VALID(unit, L3_ENTRY_ONLY_DOUBLEm) || 4924 SOC_MEM_IS_VALID(unit, L3_ENTRY_ONLY_QUADm)) { 4925 if (SOC_IS_TRIDENT3X(unit)) { 4926 switch (mem) { 4927 case L3_ENTRY_ONLY_SINGLEm: 4928 case L3_ENTRY_SINGLEm: 4929 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, BASE_VALIDf)) { 4930 CACHE_VMAP_CLR(vmap, *index); 4931 break; 4932 } 4933 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, KEY_TYPEf)) { 4934 case TD3_L3_HASH_KEY_TYPE_V4MC: 4935 case TD3_L3_HASH_KEY_TYPE_V6UC: 4936 case TD3_L3_HASH_KEY_TYPE_L2_IPV4_MULTICAST: 4937 case TD3_L3_HASH_KEY_TYPE_L2VP_IPV4_MULTICAST: 4938 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4939 CACHE_VMAP_CLR(vmap, *index); 4940 break; 4941 case TD3_L3_HASH_KEY_TYPE_V6MC: 4942 case TD3_L3_HASH_KEY_TYPE_L2_IPV6_MULTICAST: 4943 case TD3_L3_HASH_KEY_TYPE_L2VP_IPV6_MULTICAST: 4944 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4945 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4946 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4947 CACHE_VMAP_CLR(vmap, *index); 4948 break; 4949 case TD3_L3_HASH_KEY_TYPE_V4UC: 4950 case TD3_L3_HASH_KEY_TYPE_TRILL: 4951 /* let vmap bit remain set */ 4952 break; 4953 default: /* illegal key_type */ 4954 CACHE_VMAP_CLR(vmap, *index); 4955 break; 4956 } 4957 break; 4958 case L3_ENTRY_ONLY_DOUBLEm: 4959 case L3_ENTRY_DOUBLEm: 4960 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, BASE_VALID_0f)) { 4961 CACHE_VMAP_CLR(vmap, *index); 4962 break; 4963 } 4964 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, KEY_TYPEf)) { 4965 case TD3_L3_HASH_KEY_TYPE_V4UC: 4966 case TD3_L3_HASH_KEY_TYPE_TRILL: 4967 CACHE_VMAP_CLR(vmap, *index); 4968 break; 4969 case TD3_L3_HASH_KEY_TYPE_V6MC: 4970 case TD3_L3_HASH_KEY_TYPE_L2_IPV6_MULTICAST: 4971 case TD3_L3_HASH_KEY_TYPE_L2VP_IPV6_MULTICAST: 4972 CACHE_VMAP_CLR(vmap, *index); *index += 1; 4973 CACHE_VMAP_CLR(vmap, *index); 4974 break; 4975 case TD3_L3_HASH_KEY_TYPE_V4MC: 4976 case TD3_L3_HASH_KEY_TYPE_V6UC: 4977 case TD3_L3_HASH_KEY_TYPE_L2_IPV4_MULTICAST: 4978 case TD3_L3_HASH_KEY_TYPE_L2VP_IPV4_MULTICAST: 4979 /* let vmap bit remain set */ 4980 break; 4981 default: /* illegal key_type */ 4982 CACHE_VMAP_CLR(vmap, *index); 4983 break; 4984 } 4985 break; 4986 case L3_ENTRY_ONLY_QUADm: 4987 case L3_ENTRY_QUADm: 4988 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, BASE_VALID_0f)) { 4989 CACHE_VMAP_CLR(vmap, *index); 4990 break; 4991 } 4992 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, KEY_TYPEf)) { 4993 case TD3_L3_HASH_KEY_TYPE_V6MC: 4994 case TD3_L3_HASH_KEY_TYPE_L2_IPV6_MULTICAST: 4995 case TD3_L3_HASH_KEY_TYPE_L2VP_IPV6_MULTICAST: 4996 /* let vmap bit remain set */ 4997 break; 4998 default: /* illegal key_type */ 4999 CACHE_VMAP_CLR(vmap, *index); 5000 break; 5001 } 5002 break; 5003 default: 5004 break; 5005 } 5006 } 5007 } 5008 #endif 5009 } 5010 5011 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 5012 #ifdef BCM_WARM_BOOT_SUPPORT 5013 int 5014 soc_mem_block_count(int unit, soc_mem_t mem, int *count) 5015 { 5016 int blk_count = 0, blk; 5017 5018 if (NULL == count) { 5019 return SOC_E_PARAM; 5020 } 5021 5022 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 5023 blk_count++; 5024 } 5025 5026 *count = blk_count; 5027 return SOC_E_NONE; 5028 } 5029 5030 int 5031 soc_control_overlay_tcam_scache_init(int unit, int blk_num) 5032 { 5033 soc_scache_handle_t scache_handle; 5034 uint8 *overlay_tcam_scache_ptr; 5035 int rv; 5036 int stable_size, index_count = 0; 5037 int alloc_sz; 5038 int create = SOC_WARM_BOOT(unit) ? FALSE : TRUE; 5039 5040 if (SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) { 5041 index_count = soc_mem_index_count(unit, FP_GLOBAL_MASK_TCAMm); 5042 alloc_sz = SHR_BITALLOCSIZE(index_count) * blk_num; 5043 } else { 5044 return SOC_E_UNAVAIL; 5045 } 5046 5047 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 5048 if (!stable_size) { 5049 /* If stable not allocated, just return */ 5050 return SOC_E_NONE; 5051 } 5052 SOC_SCACHE_ALIGN_SIZE(alloc_sz); 5053 5054 alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE; 5055 5056 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 5057 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 5058 SOC_SCACHE_SOC_OVERLAY_TCAM_HANDLE, 0); 5059 /* Get the pointer for the Level 2 cache */ 5060 rv = soc_extended_scache_ptr_get(unit, scache_handle, create, 5061 create ? alloc_sz : 0, 5062 &overlay_tcam_scache_ptr); 5063 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 5064 return rv; 5065 } else if (SOC_E_NOT_FOUND == rv && !create) { 5066 /* Not yet allocated in upgrade */ 5067 rv = soc_extended_scache_ptr_get(unit, scache_handle, TRUE, 5068 alloc_sz, 5069 &overlay_tcam_scache_ptr); 5070 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 5071 return rv; 5072 } 5073 if (SOC_SUCCESS(rv)) { 5074 SOC_FP_TCAM_SCACHE_HANDLE(unit) = overlay_tcam_scache_ptr; 5075 } 5076 } else if (SOC_FAILURE(rv)) { 5077 return rv; 5078 } else { 5079 SOC_FP_TCAM_SCACHE_HANDLE(unit) = overlay_tcam_scache_ptr; 5080 } 5081 } 5082 5083 return SOC_E_NONE; 5084 } 5085 5086 int 5087 soc_control_overlay_tcam_scache_sync(int unit) 5088 { 5089 uint8 *overlay_tcam_scache_ptr = SOC_FP_TCAM_SCACHE_HANDLE(unit); 5090 SHR_BITDCL *overlay_tcam_bmp; 5091 int stable_size = 0, index_count, blk, scache_size; 5092 uint16 version = SOC_OVERLAY_TCAM_WARMBOOT_DEFAULT_VERSION; 5093 soc_mem_t mem; 5094 soc_memstate_t *memState; 5095 5096 if (SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) { 5097 mem = FP_GLOBAL_MASK_TCAMm; 5098 index_count = soc_mem_index_count(unit, mem); 5099 scache_size = SHR_BITALLOCSIZE(index_count); 5100 memState = &SOC_MEM_STATE(unit, mem); 5101 } else { 5102 return SOC_E_UNAVAIL; 5103 } 5104 5105 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 5106 if (!stable_size) { 5107 /* If stable not allocated, just return */ 5108 return SOC_E_NONE; 5109 } 5110 if (NULL == overlay_tcam_scache_ptr) { 5111 return SOC_E_UNAVAIL; 5112 } 5113 5114 /* First save version */ 5115 sal_memcpy(overlay_tcam_scache_ptr, &version, sizeof(version)); 5116 overlay_tcam_scache_ptr += sizeof(version); 5117 5118 /* Save overlay tcam bitmap */ 5119 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 5120 overlay_tcam_bmp = memState->OverlayTcamMap[blk]; 5121 5122 if (NULL == overlay_tcam_bmp) { 5123 return SOC_E_INIT; 5124 } 5125 sal_memcpy(overlay_tcam_scache_ptr, 5126 overlay_tcam_bmp, 5127 scache_size); 5128 overlay_tcam_scache_ptr += scache_size; 5129 } 5130 return SOC_E_NONE; 5131 } 5132 5133 int 5134 soc_control_overlay_tcam_scache_load(int unit, void *bmp, int blk, 5135 uint8 *overlay_tcam_scache_ptr) 5136 { 5137 SHR_BITDCL *overlay_tcam_bmp = (SHR_BITDCL *)bmp; 5138 int index_count, scache_size, blk_count; 5139 int stable_size = 0; 5140 5141 if (SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) { 5142 index_count = soc_mem_index_count(unit, FP_GLOBAL_MASK_TCAMm); 5143 scache_size = SHR_BITALLOCSIZE(index_count); 5144 } else { 5145 return SOC_E_UNAVAIL; 5146 } 5147 5148 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 5149 if (!stable_size) { 5150 /* If stable not allocated, just return */ 5151 return SOC_E_RESOURCE; 5152 } 5153 5154 if (NULL == overlay_tcam_scache_ptr) { 5155 return SOC_E_UNAVAIL; 5156 } 5157 5158 if (NULL == overlay_tcam_bmp) { 5159 return SOC_E_INIT; 5160 } 5161 5162 soc_mem_block_count(unit, FP_GLOBAL_MASK_TCAMm, &blk_count); 5163 if (blk >= blk_count || blk < 0) { 5164 return SOC_E_RESOURCE; 5165 } 5166 5167 if (SOC_WARM_BOOT(unit)) { 5168 sal_memcpy(overlay_tcam_bmp, 5169 overlay_tcam_scache_ptr + scache_size*blk, 5170 scache_size); 5171 } 5172 return SOC_E_NONE; 5173 } 5174 5175 /* 5176 * Function: 5177 * soc_mem_cache_overlay_tcam_check 5178 * Purpose: 5179 * Check if the overlay tcam cache is valid. Clear the invalid entry's 5180 * cache and vmap. 5181 */ 5182 int 5183 soc_mem_cache_overlay_tcam_check(int unit, soc_mem_t mem, 5184 SHR_BITDCL *overlay_tcam_bmp, uint8 *vmap) 5185 { 5186 int idx, index_min, index_max; 5187 5188 if (NULL == vmap) { 5189 return SOC_E_PARAM; 5190 } 5191 5192 index_min = soc_mem_index_min(unit, mem); 5193 index_max = soc_mem_index_max(unit, mem); 5194 5195 if (mem != FP_GLOBAL_MASK_TCAMm && 5196 mem != FP_GM_FIELDSm) { 5197 return SOC_E_NONE; 5198 } 5199 5200 if (NULL == overlay_tcam_bmp) { 5201 return SOC_E_INIT; 5202 } 5203 5204 for (idx = index_min; 5205 idx <= index_max; 5206 idx++) { 5207 if (FP_GLOBAL_MASK_TCAMm == mem) { 5208 if (SHR_BITGET(overlay_tcam_bmp, idx)) { 5209 CACHE_VMAP_CLR(vmap, idx); 5210 } 5211 } else if (FP_GM_FIELDSm == mem) { 5212 if (!SHR_BITGET(overlay_tcam_bmp, idx)) { 5213 CACHE_VMAP_CLR(vmap, idx); 5214 } 5215 } 5216 } 5217 5218 return SOC_E_NONE; 5219 } 5220 5221 /* 5222 * Function: 5223 * soc_mem_overlay_tcam_update 5224 * Purpose: 5225 * Update the overlay tcam bitmap during writing or clearing 5226 */ 5227 void 5228 soc_mem_overlay_tcam_update(int unit, soc_mem_t mem, int blk, 5229 int index_begin, int index_end) 5230 { 5231 int num_entries; 5232 SHR_BITDCL *soc_overlay_tcam_bmp; 5233 soc_memstate_t *memState; 5234 5235 if (mem != FP_GLOBAL_MASK_TCAMm && 5236 mem != FP_GM_FIELDSm) { 5237 return; 5238 } 5239 5240 if (index_end - index_begin < 0 || 5241 soc_mem_index_min(unit, mem) > index_begin || 5242 soc_mem_index_max(unit, mem) < index_end) { 5243 return; 5244 } 5245 5246 memState = &SOC_MEM_STATE(unit, mem); 5247 5248 soc_overlay_tcam_bmp = memState->OverlayTcamMap[blk]; 5249 if (NULL == soc_overlay_tcam_bmp) { 5250 return; 5251 } 5252 5253 num_entries = index_end - index_begin + 1; 5254 5255 if (mem == FP_GLOBAL_MASK_TCAMm) { 5256 SHR_BITCLR_RANGE(soc_overlay_tcam_bmp, index_begin, num_entries); 5257 } else if (mem == FP_GM_FIELDSm) { 5258 SHR_BITSET_RANGE(soc_overlay_tcam_bmp, index_begin, num_entries); 5259 } 5260 } 5261 5262 /* 5263 * Function: 5264 * soc_mem_overlay_tcam_cache_set 5265 * Purpose: 5266 * Enable or disable caching for overlay tcam memories 5267 * Notes: 5268 * Set cache for FP_GLOBAL_MASK_TCAMm and FP_GM_FIELDSm 5269 * based on OverlayTcamMap. 5270 */ 5271 int 5272 soc_mem_overlay_tcam_cache_set(int unit, 5273 soc_mem_t mem, 5274 int copyno, 5275 int enable) 5276 { 5277 SHR_BITDCL *OverlayTcamMap; 5278 int alloc_sz = 0, rv = SOC_E_NONE; 5279 int blk_count = 0, index_count = 0, valid_blk = 0, blk; 5280 soc_memstate_t *mem_state, *mem_state_temp; 5281 soc_mem_t fp_mem[2] = {FP_GLOBAL_MASK_TCAMm, FP_GM_FIELDSm}; 5282 uint8 *overlay_tcam_scache_ptr = NULL; 5283 uint16 version = 0; 5284 5285 if (mem != fp_mem[0] && mem != fp_mem[1]) { 5286 return SOC_E_PARAM; 5287 } 5288 5289 index_count = soc_mem_index_count(unit, mem); 5290 alloc_sz = SHR_BITALLOCSIZE(index_count); 5291 soc_mem_block_count(unit, mem, &blk_count); 5292 mem_state = &SOC_MEM_STATE(unit, mem); 5293 5294 if (mem == fp_mem[0]) { 5295 mem_state_temp = &SOC_MEM_STATE(unit, fp_mem[1]); 5296 } else { 5297 mem_state_temp = &SOC_MEM_STATE(unit, fp_mem[0]); 5298 } 5299 5300 /* Init FP overlay tcam bitmap scache*/ 5301 if (enable) { 5302 rv = soc_control_overlay_tcam_scache_init(unit, blk_count); 5303 if (SOC_FAILURE(rv)) { 5304 if (rv == SOC_E_UNAVAIL) { 5305 rv = SOC_E_NONE; 5306 } 5307 goto _tcam_set_done; 5308 } 5309 } 5310 5311 /*load version*/ 5312 if (SOC_WARM_BOOT(unit)) { 5313 overlay_tcam_scache_ptr = SOC_FP_TCAM_SCACHE_HANDLE(unit); 5314 if (overlay_tcam_scache_ptr != NULL) { 5315 sal_memcpy(&version, overlay_tcam_scache_ptr, sizeof(version)); 5316 overlay_tcam_scache_ptr += sizeof(version); 5317 } 5318 } 5319 5320 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 5321 if (copyno != COPYNO_ALL && copyno != blk) { 5322 continue; 5323 } 5324 5325 /* 5326 *FP_GLOBAL_MASK_TCAMm and FP_GM_FIELDSm share one overlay tcam 5327 *bitmap. So only destory overlay tcam bitmap one time. 5328 */ 5329 if (!enable) { 5330 if (mem_state->OverlayTcamMap[blk] != NULL) { 5331 sal_free(mem_state->OverlayTcamMap[blk]); 5332 mem_state->OverlayTcamMap[blk] = NULL; 5333 mem_state_temp->OverlayTcamMap[blk] = NULL; 5334 } 5335 continue; 5336 } 5337 5338 /* 5339 *Alloc overlay tcam bitmap when OverlayTcamMap for both mems equal NULL 5340 */ 5341 if (mem_state->OverlayTcamMap[blk] == NULL) { 5342 if (mem_state_temp->OverlayTcamMap[blk] == NULL) { 5343 if ((OverlayTcamMap = 5344 sal_alloc(alloc_sz, 5345 "mem XY TCAM BITMAP")) == NULL) { 5346 rv = SOC_E_MEMORY; 5347 goto _tcam_set_done; 5348 } 5349 sal_memset(OverlayTcamMap, 0, alloc_sz); 5350 mem_state->OverlayTcamMap[blk] = OverlayTcamMap; 5351 5352 if (SOC_WARM_BOOT(unit)) { 5353 /* Recover overlay tcam bitmap from scache*/ 5354 if (version >= SOC_OVERLAY_TCAM_WARMBOOT_VERSION_1) { 5355 rv = soc_control_overlay_tcam_scache_load 5356 (unit, OverlayTcamMap, valid_blk, overlay_tcam_scache_ptr); 5357 } else { 5358 rv = SOC_E_UNAVAIL; 5359 } 5360 if (SOC_FAILURE(rv)) { 5361 if (rv == SOC_E_UNAVAIL) { 5362 rv = SOC_E_NONE; 5363 } 5364 goto _tcam_set_done; 5365 } 5366 5367 /* Clear the invalid vmap based on overlay tcam bitmap*/ 5368 rv = soc_mem_cache_overlay_tcam_check 5369 (unit, mem, OverlayTcamMap, mem_state->vmap[blk]); 5370 if (SOC_FAILURE(rv)) { 5371 goto _tcam_set_done; 5372 } 5373 5374 valid_blk++; 5375 } 5376 } else { 5377 OverlayTcamMap = mem_state_temp->OverlayTcamMap[blk]; 5378 mem_state->OverlayTcamMap[blk] = OverlayTcamMap; 5379 5380 if (SOC_WARM_BOOT(unit)) { 5381 rv = soc_mem_cache_overlay_tcam_check 5382 (unit, mem, OverlayTcamMap, mem_state->vmap[blk]); 5383 if (SOC_FAILURE(rv)) { 5384 goto _tcam_set_done; 5385 } 5386 } 5387 } 5388 } 5389 } 5390 _tcam_set_done: 5391 return rv; 5392 } 5393 #endif 5394 #endif 5395 5396 /* 5397 * Function: 5398 * soc_mem_cache_set 5399 * Purpose: 5400 * Enable or disable caching for a specified memory or memories 5401 * Notes: 5402 * Only tables whose contents are not modified by hardware in 5403 * any way are eligible for caching. 5404 */ 5405 5406 int 5407 soc_mem_cache_set(int unit, soc_mem_t mem, int copyno, int enable) 5408 { 5409 int blk, entry_dw, index_cnt; 5410 int cache_size, vmap_size, numels = 1, first_array_index = 0; 5411 uint8 *vmap; 5412 #if ((defined BCM_XGS_SWITCH_SUPPORT ) || (defined BCM_SAND_SUPPORT)) 5413 uint8 load_cache = 1, l2 = 0; 5414 #endif 5415 5416 uint32 *cache; 5417 soc_memstate_t *memState; 5418 soc_stat_t *stat = SOC_STAT(unit); 5419 soc_mem_t org_mem = mem; 5420 5421 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 5422 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 5423 defined(BCM_GREYHOUND_SUPPORT) 5424 int corrupt_size = 0; 5425 uint8 *corrupt = NULL; 5426 #endif 5427 #ifdef BCM_KATANA2_SUPPORT 5428 int port_index[15]= 5429 {1,5,9,13,17,21,25,26,27,28,30,33,37,39,41}; 5430 int port = 0; 5431 int idx, j; 5432 #endif /*BCM_KATANA2_SUPPORT */ 5433 #if defined(BCM_TRIDENT2_SUPPORT) 5434 int skip = 0; 5435 #endif 5436 5437 assert(SOC_UNIT_VALID(unit)); 5438 _SOC_MEM_REUSE_MEM_STATE(unit, mem); 5439 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 5440 assert(SOC_MEM_IS_VALID(unit, mem)); 5441 5442 if (!(soc_mem_is_cachable(unit, mem))) { 5443 return (enable ? SOC_E_UNAVAIL : SOC_E_NONE); 5444 } 5445 memState = &SOC_MEM_STATE(unit, mem); 5446 if (memState->lock == NULL) { 5447 return SOC_E_NONE; 5448 } 5449 5450 if (SOC_MEM_INFO(unit,mem).flags & SOC_MEM_FLAG_IS_ARRAY) { 5451 numels = SOC_MEM_ARRAY_INFO(unit,mem).numels; 5452 first_array_index = SOC_MEM_ARRAY_INFO(unit,mem).first_array_index; 5453 } 5454 5455 entry_dw = soc_mem_entry_words(unit, mem); 5456 index_cnt = soc_mem_index_count(unit, mem); 5457 /* Change the index for particular memory in case of hole in space */ 5458 if (soc_feature(unit, soc_feature_defip_2_tcams_with_separate_rpf) 5459 && (mem == L3_DEFIPm)) { 5460 5461 index_cnt +=SOC_DEFIP_HOLE_OFFSET(unit, mem); ; 5462 } 5463 cache_size = numels * index_cnt * entry_dw * 4; 5464 vmap_size = (numels * index_cnt + 7) / 8; 5465 5466 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 5467 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 5468 defined(BCM_GREYHOUND_SUPPORT) 5469 /* TCAM tables have corrupt bitmap */ 5470 if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 5471 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 5472 corrupt_size = (index_cnt + 7) / 8; 5473 } 5474 #endif 5475 5476 LOG_INFO(BSL_LS_SOC_SOCMEM, 5477 (BSL_META_U(unit, 5478 "soc_mem_cache_set: unit %d memory %s.%s %sable\n"), 5479 unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno), 5480 enable ? "en" : "dis")); 5481 5482 if (copyno != COPYNO_ALL) { 5483 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 5484 } 5485 5486 MEM_LOCK(unit, mem); 5487 5488 #ifdef BCM_KATANA2_SUPPORT 5489 if (SOC_IS_KATANA2(unit) && (mem == VLAN_TABm) && (!enable) ) { 5490 for (j = 0; j < SOC_MAX_NUM_BLKS; ++j) { 5491 soc_control[unit]->memState[EGR_VLANm].cache[j] = NULL; 5492 soc_control[unit]->memState[EGR_VLANm].vmap[j] = NULL; 5493 soc_control[unit]->memState[EGR_VLANm].corrupt[j] = NULL; 5494 } 5495 } 5496 #endif 5497 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 5498 if (copyno != COPYNO_ALL && copyno != blk) { 5499 continue; 5500 } 5501 #if defined(BCM_TRIUMPH3_SUPPORT) 5502 if (SOC_IS_TRIUMPH3(unit) && 5503 ((mem == PORT_EHG_RX_TUNNEL_MASKm) || 5504 (mem == PORT_EHG_RX_TUNNEL_DATAm) || 5505 (mem == PORT_EHG_TX_TUNNEL_DATAm))) { 5506 if (!_soc_tr3_port_mem_blk_enabled(unit, blk)) { 5507 continue; 5508 } 5509 } 5510 #endif /* BCM_TRIUMPH3_SUPPORT */ 5511 /* Turn off caching if currently enabled. */ 5512 if (memState->cache[blk] != NULL) { 5513 sal_free(memState->cache[blk]); 5514 memState->cache[blk] = NULL; 5515 } 5516 if (memState->vmap[blk] != NULL) { 5517 sal_free(memState->vmap[blk]); 5518 memState->vmap[blk] = NULL; 5519 } 5520 /* If we don't so, there are dangling pointer */ 5521 if (org_mem != mem) { 5522 /* Share the cache and vmap */ 5523 SOC_MEM_STATE(unit, org_mem).cache[blk] = NULL; 5524 SOC_MEM_STATE(unit, org_mem).vmap[blk] = NULL; 5525 } 5526 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 5527 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 5528 defined(BCM_GREYHOUND_SUPPORT) 5529 if (memState->corrupt[blk] != NULL) { 5530 sal_free(memState->corrupt[blk]); 5531 memState->corrupt[blk] = NULL; 5532 } 5533 #endif 5534 5535 if (!enable) { 5536 continue; 5537 } 5538 /* Allocate new cache */ 5539 if ((cache = sal_alloc(cache_size, "table-cache")) == NULL) { 5540 MEM_UNLOCK(unit, mem); 5541 return SOC_E_MEMORY; 5542 } 5543 stat->mem_cache_count++; 5544 stat->mem_cache_size += cache_size; 5545 5546 if ((vmap = sal_alloc(vmap_size, "table-vmap")) == NULL) { 5547 sal_free(cache); 5548 MEM_UNLOCK(unit, mem); 5549 return SOC_E_MEMORY; 5550 } 5551 stat->mem_cache_vmap_size += vmap_size; 5552 LOG_VERBOSE(BSL_LS_SOC_SER, 5553 (BSL_META_U(unit, 5554 "soc_mem_cache_set: WB=%0d, memory %s.%s cache_count=%0d, " 5555 "cache_size=%0d, vmap_size=%0d \n"), 5556 SOC_WARM_BOOT(unit), SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno), 5557 stat->mem_cache_count, stat->mem_cache_size, 5558 stat->mem_cache_vmap_size)); 5559 5560 sal_memset(vmap, 0, vmap_size); /* zero out all valid bits */ 5561 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 5562 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 5563 defined(BCM_GREYHOUND_SUPPORT) 5564 if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 5565 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 5566 /* Allocate corruption bitmap */ 5567 if ((corrupt = sal_alloc(corrupt_size, "corrupt indication map")) == NULL) { 5568 sal_free(cache); 5569 sal_free(vmap); 5570 MEM_UNLOCK(unit, mem); 5571 return SOC_E_MEMORY; 5572 } 5573 stat->tcam_corrupt_map_size += corrupt_size; 5574 sal_memset(corrupt, 0, corrupt_size); 5575 } 5576 #endif 5577 5578 5579 #if ((defined BCM_XGS_SWITCH_SUPPORT ) || (defined BCM_SAND_SUPPORT)) 5580 if (_SOC_MEM_CHK_L2_MEM(mem)) { 5581 l2 = 1; 5582 } 5583 /* NOTE: This is a temporary way of enabling WB mem cache reload case 5584 * by case on different devices as support is being implemented. 5585 * Eventually this check should go away or be replaced by 5586 * soc_feature_mem_wb_cache_reload. 5587 */ 5588 if (!(SOC_IS_TD_TT(unit) || SOC_IS_ENDURO(unit) || SOC_IS_KATANAX(unit) || SOC_IS_SAND(unit) || 5589 (SOC_IS_TRIUMPH3(unit)) || SOC_IS_TRIUMPH(unit) || 5590 soc_feature(unit, soc_feature_mem_wb_cache_reload))) { 5591 5592 load_cache = 0; 5593 } 5594 /* Pre-load cache from hardware table (if quickly-doable) OR 5595 we are doing Warm-Boot */ 5596 #ifdef BCM_PETRA_SUPPORT 5597 if ((soc_feature(unit, soc_feature_table_dma) && 5598 (soc_mem_dmaable(unit, mem, blk) || SOC_IS_ARAD(unit)) && 5599 (SOC_CONTROL(unit)->soc_flags & SOC_F_INITED) && !l2) || 5600 (SOC_WARM_BOOT(unit) && load_cache && 5601 (SOC_CONTROL(unit)->mem_scache_ptr == NULL))) { 5602 #else 5603 if ((soc_feature(unit, soc_feature_table_dma) && 5604 soc_mem_dmaable(unit, mem, blk) && 5605 (SOC_CONTROL(unit)->soc_flags & SOC_F_INITED) && !l2) || 5606 (SOC_WARM_BOOT(unit) && load_cache && 5607 (SOC_CONTROL(unit)->mem_scache_ptr == NULL))) { 5608 #endif 5609 uint32 *table; 5610 int index, index_max = index_cnt - 1, elem; 5611 int index_min = soc_mem_index_min(unit, mem); 5612 uint32 entry[SOC_MAX_MEM_WORDS]; 5613 5614 #if defined(BCM_TOMAHAWK_SUPPORT) 5615 if (SOC_IS_TOMAHAWKX(unit) && !SOC_IS_TOMAHAWK3(unit)) { 5616 if (soc_mem_is_cam(unit, mem) && 5617 SOC_TH_MEM_CHK_TCAM_GLOBAL_UNIQUE_MODE(mem)) { 5618 int mem_mode = _SOC_SER_MEM_MODE_GLOBAL; 5619 int rv = soc_th_check_hw_global_mode(unit, mem, 5620 &mem_mode); 5621 if (SOC_FAILURE(rv)) { 5622 /* can skip read for this mem */ 5623 sal_memset(cache, 0, cache_size); 5624 /* valid bits will remain 0 for skipped mems */ 5625 LOG_ERROR(BSL_LS_SOC_SER, 5626 (BSL_META_U(unit, 5627 "soc_mem_cache_set: Will skip " 5628 "WB_cache_fill for mem %s " 5629 "cache=%p size=%d vmap=%p\n"), 5630 SOC_MEM_NAME(unit, mem), 5631 (void *)cache, cache_size, (void *)vmap)); 5632 goto iter_done; 5633 } else if (_SOC_SER_MEM_MODE_PIPE_UNIQUE == mem_mode) { 5634 /* must skip read for this mem */ 5635 sal_memset(cache, 0, cache_size); 5636 /* valid bits will remain 0 for skipped mems */ 5637 LOG_VERBOSE(BSL_LS_SOC_SER, 5638 (BSL_META_U(unit, 5639 "soc_mem_cache_set: Will skip " 5640 "WB_cache_fill for mem %s " 5641 "cache=%p size=%d vmap=%p\n"), 5642 SOC_MEM_NAME(unit, mem), 5643 (void *)cache, cache_size, (void *)vmap)); 5644 goto iter_done; 5645 } 5646 /* proceed to read the mem - normal flow */ 5647 } 5648 } 5649 #endif 5650 if ((table = soc_cm_salloc(unit, cache_size/numels, "dma")) != NULL) { 5651 if (SOC_IS_TRIUMPH3(unit) && 5652 ((mem == PORT_EHG_RX_TUNNEL_MASKm) || 5653 (mem == PORT_EHG_RX_TUNNEL_DATAm) || 5654 (mem == PORT_EHG_TX_TUNNEL_DATAm))) { 5655 5656 if (blk == 12 || blk == 13) { 5657 index_cnt = 16; 5658 index_max = index_cnt - 1; 5659 } 5660 } 5661 5662 #if defined(BCM_TOMAHAWK_SUPPORT) 5663 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 5664 if (_SOC_MEM_CHK_IFP_TCAM(mem) || 5665 _SOC_MEM_CHK_IFP_TCAM_WIDE(mem)) { 5666 5667 /* read ifp_tcam using per_slice_dma (which may skip 5668 * reading of slices based on width, so first cleanup 5669 * 'table' */ 5670 LOG_VERBOSE(BSL_LS_SOC_SER, 5671 (BSL_META_U(unit, 5672 "soc_mem_cache_set: " 5673 "WB_cache_fill for mem %s " 5674 "using soc_th_ifp_tcam_dma_read " 5675 "cache=%p size=%d vmap=%p\n"), 5676 SOC_MEM_NAME(unit, mem), 5677 (void *)cache, cache_size, (void *)vmap)); 5678 sal_memset(table, 0, cache_size/numels); 5679 /* Set all vmap bits valid first, will clear the invalid in 5680 soc_th_ifp_tcam_dma_read */ 5681 sal_memset(&vmap[index_min / 8], 0xff, 5682 (index_cnt + 7 - index_min) / 8); 5683 if (soc_th_ifp_tcam_dma_read(unit, mem, blk, table, 0, vmap) >= 0) { 5684 /* When done reading all slices */ 5685 sal_memcpy(cache, table, cache_size); 5686 5687 /* Clear invalid bits at the left and right ends */ 5688 vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8); 5689 vmap[vmap_size - 1] &= 0x00ff >> ((8 - index_cnt % 8) % 8); 5690 5691 } 5692 /* done with read of table, with/without error */ 5693 soc_cm_sfree(unit, table); 5694 goto iter_done; 5695 } 5696 } 5697 #endif /* BCM_TOMAHAWK_SUPPORT */ 5698 #if defined(BCM_TRIDENT2_SUPPORT) 5699 _SOC_MEM_SKIP_READING_MEM_TO_CACHE(unit, mem, skip); 5700 if (skip == 1) { 5701 sal_memset(cache, 0, cache_size); 5702 memState->vmap[blk] = vmap; 5703 memState->cache[blk] = cache; 5704 soc_cm_sfree(unit, table); 5705 continue; 5706 } 5707 #endif 5708 LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit, 5709 "cache_rebuild: memory %s \n"), 5710 SOC_MEM_NAME(unit, mem))); 5711 5712 if (numels > 1) { 5713 for (elem = first_array_index; elem < numels + first_array_index; elem++) { 5714 if (soc_mem_array_read_range(unit, mem, elem, blk, index_min, index_max, 5715 &table[index_min * entry_dw]) >= 0) { 5716 uint32 first_read_elem = (elem - first_array_index)* index_cnt; 5717 uint32 not_read_elem = first_read_elem + index_cnt; 5718 sal_memcpy(cache + (first_read_elem * entry_dw), table, cache_size/numels); 5719 /* Set all vmap bits as valid */ 5720 if (first_read_elem % 8) { 5721 vmap[first_read_elem/8] |= ((uint8)(0xff >> (first_read_elem % 8))); 5722 } 5723 if (not_read_elem % 8) { 5724 vmap[not_read_elem/8] |= ((uint8)(0xff << (8 - (not_read_elem % 8)))); 5725 } 5726 first_read_elem = (first_read_elem + 7)/8; 5727 not_read_elem /= 8; 5728 5729 if (not_read_elem > first_read_elem) { 5730 sal_memset(vmap + first_read_elem, 0xff, not_read_elem - first_read_elem); 5731 } 5732 } 5733 } 5734 } else if (soc_mem_read_range(unit, mem, blk, index_min, index_max, 5735 &table[index_min * entry_dw]) >= 0) { 5736 5737 sal_memcpy(cache, table, cache_size); 5738 5739 /* Set all vmap bits as valid */ 5740 sal_memset(&vmap[index_min / 8], 0xff, 5741 (index_cnt + 7 - index_min) / 8); 5742 5743 #ifdef BCM_KATANA2_SUPPORT 5744 /* In case of SP memories, out of SP0, SP1, SP2 & SP3 5745 * only SP0 is valid i.e. only indices 0,4,8.This check 5746 * is avoid processing invalid indices. Issue is handled 5747 * for THDI memories alone. Has to be handled 5748 * for other SP memories in future */ 5749 /* For PG memories, please note that for ports supporting 5750 * only one PG, there is only one location on the memory, 5751 * eg. Port 6, Pg[0..7] will all point to a same location in the memory */ 5752 if (SOC_IS_KATANA2(unit)) { 5753 if (mem == THDIEMA_THDI_PORT_SP_CONFIGm || 5754 mem == THDIEXT_THDI_PORT_SP_CONFIGm || 5755 mem == THDIQEN_THDI_PORT_SP_CONFIGm || 5756 mem == THDIRQE_THDI_PORT_SP_CONFIGm || 5757 mem == THDI_PORT_SP_CONFIGm) { 5758 sal_memset(&vmap[index_min / 8], 0x11, 5759 (index_cnt + 7 - index_min) / 8); 5760 } else if ((mem == THDIEMA_THDI_PORT_PG_CONFIGm || 5761 mem == THDIEXT_THDI_PORT_PG_CONFIGm || 5762 mem == THDIQEN_THDI_PORT_PG_CONFIGm || 5763 mem == THDIRQE_THDI_PORT_PG_CONFIGm || 5764 mem == THDI_PORT_PG_CONFIGm )) { 5765 sal_memset(&vmap[index_min / 8], 0xff, 5766 (index_cnt + 7 - index_min) / 8); 5767 5768 if (!SOC_IS_SABER2(unit)) { 5769 index = index_min / 8; 5770 idx = 0; 5771 for (port = 0 ; port <= 41; port++) { 5772 if (port_index[idx] == port) { 5773 sal_memset(&vmap[index], 0x01, 5774 1); 5775 idx++; 5776 } 5777 index++; 5778 } 5779 } 5780 } 5781 5782 } 5783 #endif 5784 5785 /* Clear invalid bits at the left and right ends */ 5786 vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8); 5787 vmap[vmap_size - 1] &= 0x00ff >> ((8 - index_cnt % 8) % 8); 5788 } 5789 if (SOC_IS_TD_TT(unit) && (mem == FP_GLOBAL_MASK_TCAMm) 5790 && (SOC_SWITCH_BYPASS_MODE(unit) != 5791 SOC_SWITCH_BYPASS_MODE_L3_AND_FP)) { 5792 /* The read of FP_GLOBAL_MASK_TCAM only returns the 5793 * X-pipe portions of the pbmp. We need the Y-pipe 5794 * portions also to match what was available 5795 * during Cold Boot. So we explicitly read the 5796 * Y-pipe table here and OR the bitmaps together 5797 * to form the complete entry that existed in 5798 * the Cold Boot cache. 5799 */ 5800 if (soc_mem_read_range(unit, FP_GLOBAL_MASK_TCAM_Ym, 5801 blk, index_min, index_max, 5802 &table[index_min * entry_dw]) >= 0) { 5803 soc_pbmp_t pbmp_x, pbmp_y; 5804 uint32 *entry_x, *entry_y; 5805 for (index = index_min; 5806 index <= index_max; 5807 index++) { 5808 /* FP_GLOBAL_MASK_TCAM[_X|_Y] have the same 5809 * field structure, so we can use the field 5810 * accessors for just the base memory. */ 5811 entry_x = cache + index * entry_dw; 5812 entry_y = &table[index_min * entry_dw] + 5813 index * entry_dw; 5814 5815 soc_mem_pbmp_field_get(unit, mem, entry_x, 5816 IPBM_MASKf, &pbmp_x); 5817 SOC_PBMP_AND(pbmp_x, PBMP_XPIPE(unit)); 5818 soc_mem_pbmp_field_get(unit, mem, entry_y, 5819 IPBM_MASKf, &pbmp_y); 5820 SOC_PBMP_AND(pbmp_y, PBMP_YPIPE(unit)); 5821 SOC_PBMP_OR(pbmp_x, pbmp_y); 5822 soc_mem_pbmp_field_set(unit, mem, entry_x, 5823 IPBM_MASKf, &pbmp_x); 5824 5825 soc_mem_pbmp_field_get(unit, mem, entry_x, 5826 IPBMf, &pbmp_x); 5827 SOC_PBMP_AND(pbmp_x, PBMP_XPIPE(unit)); 5828 soc_mem_pbmp_field_get(unit, mem, entry_y, 5829 IPBMf, &pbmp_y); 5830 SOC_PBMP_AND(pbmp_y, PBMP_YPIPE(unit)); 5831 SOC_PBMP_OR(pbmp_x, pbmp_y); 5832 soc_mem_pbmp_field_set(unit, mem, entry_x, 5833 IPBMf, &pbmp_x); 5834 } 5835 } 5836 } 5837 soc_cm_sfree(unit, table); 5838 if (_SOC_MEM_CHK_L2_MEM(mem)) { 5839 for (index = index_min; index <= index_max; index++) { 5840 sal_memcpy(entry, cache + index*entry_dw, entry_dw * 4); 5841 if ((mem == L2_ENTRY_2m && 5842 (soc_mem_field32_get(unit, mem, entry, STATIC_BIT_0f) && 5843 soc_mem_field32_get(unit, mem, entry, STATIC_BIT_1f))) || 5844 ((mem == L2Xm || mem == L2_ENTRY_1m) && 5845 soc_mem_field32_get(unit, mem, entry, STATIC_BITf))) { 5846 /* Continue */ 5847 } else { 5848 CACHE_VMAP_CLR(vmap, index); 5849 } 5850 } 5851 } else if (_SOC_MEM_CHK_L3_MEM(mem)) { 5852 uint32 *centry; 5853 5854 for (index = index_min; index <= index_max; index++) { 5855 centry = cache + index*entry_dw; 5856 sal_memcpy(entry, centry, entry_dw * 4); 5857 _soc_mem_l3_entry_cache_entry_validate(unit, mem, entry, vmap, &index); 5858 if (SOC_MEM_FIELD_VALID(unit, mem, HITf)) { 5859 soc_mem_field32_set(unit, mem, centry, HITf, 0); 5860 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_1f)) { 5861 soc_mem_field32_set(unit, mem, centry, HIT_0f, 0); 5862 soc_mem_field32_set(unit, mem, centry, HIT_1f, 0); 5863 } 5864 if (SOC_MEM_FIELD_VALID(unit, mem, HIT_3f)) { 5865 soc_mem_field32_set(unit, mem, centry, HIT_2f, 0); 5866 soc_mem_field32_set(unit, mem, centry, HIT_3f, 0); 5867 } 5868 } 5869 } 5870 #if defined(BCM_TOMAHAWK_SUPPORT) 5871 else if (_SOC_MEM_CHK_FPEM_MEM(mem)) { 5872 uint32 *centry; 5873 5874 for (index = index_min; index <= index_max; index++) { 5875 centry = cache + index*entry_dw; 5876 sal_memcpy(entry, centry, entry_dw * 4); 5877 _soc_mem_fpem_entry_cache_entry_validate(unit, mem, entry, vmap, &index); 5878 if (SOC_MEM_FIELD_VALID(unit, mem, HIT_0f)) { 5879 soc_mem_field32_set(unit, mem, centry, HIT_0f, 0); 5880 } 5881 if (SOC_MEM_FIELD_VALID(unit, mem, HIT_1f)) { 5882 soc_mem_field32_set(unit, mem, centry, HIT_1f, 0); 5883 } 5884 } 5885 } 5886 #endif /* BCM_TOMAHAWK_SUPPORT */ 5887 else if (_SOC_MEM_CHK_EGR_IP_TUNNEL(mem)) { 5888 uint32 *centry; 5889 soc_field_t fld = ENTRY_TYPEf; 5890 5891 #ifdef BCM_TRIDENT3_SUPPORT 5892 if (SOC_IS_TRIDENT3X(unit)) { 5893 fld = DATA_TYPEf; 5894 } 5895 #endif 5896 5897 for (index = index_min; index <= index_max; index++) { 5898 centry = cache + index*entry_dw; 5899 sal_memcpy(entry, centry, entry_dw * 4); 5900 if (soc_mem_field32_get(unit, mem, entry, fld) == 0) { 5901 CACHE_VMAP_CLR(vmap, index); 5902 } 5903 if (mem == EGR_IP_TUNNELm) { 5904 if (soc_mem_field32_get(unit, mem, entry, fld) != 1) { 5905 CACHE_VMAP_CLR(vmap, index); 5906 } 5907 } else if (mem == EGR_IP_TUNNEL_MPLSm) { 5908 if (soc_mem_field32_get(unit, mem, entry, fld) != 3) { 5909 CACHE_VMAP_CLR(vmap, index); 5910 } 5911 } else if (mem == EGR_IP_TUNNEL_IPV6m) { 5912 if (soc_mem_field32_get(unit, mem, entry, fld) != 2) { 5913 CACHE_VMAP_CLR(vmap, index); 5914 } 5915 } 5916 } 5917 } 5918 #ifdef BCM_TRIUMPH3_SUPPORT 5919 else if (SOC_IS_TRIUMPH3(unit) && _SOC_MEM_CHK_MPLS_MEM(mem)) { 5920 uint32 *centry; 5921 5922 for (index = index_min; index <= index_max; index++) { 5923 centry = cache + index*entry_dw; 5924 sal_memcpy(entry, centry, entry_dw * 4); 5925 if (mem == MPLS_ENTRYm || mem == MPLS_ENTRY_1m) { 5926 if (soc_mem_field32_get(unit, mem, entry, VALIDf) == 0) { 5927 CACHE_VMAP_CLR(vmap, index); 5928 } else { 5929 switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPEf)) { 5930 case 0x06: /* 0x06 = L2GRE_SIP - key = {SIP}. */ 5931 case 0x07: /* 0x07 = L2GRE_VPNID - key = {GRE.VPNID}. */ 5932 case 0x08: /* 0x08 = L2GRE_VPNID_SIP - key = {GRE.VPNID, SIP}.*/ 5933 case 0x10: /* 0x10 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */ 5934 case 0x12: /* 0x12 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */ 5935 break; 5936 case 0x11: /* 0x11 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */ 5937 case 0x13: /* 0x13 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */ 5938 case 0x17: /* 0x17 = MIM_NVP - key = {MAC-in-MAC B-VID, B-SA}. */ 5939 case 0x18: /* 0x18 = MIM_ISID - key = {MAC-in-MAC ISID}. */ 5940 case 0x19: /* 0x19 = MIM_ISID_SVP - key = {MAC-in-MAC ISID, B-VID, B-SA}. */ 5941 case 0x1a: /* 0x1A = TRILL - key = {RBRIDGE_NICKNAME}. */ 5942 default: 5943 CACHE_VMAP_CLR(vmap, index); 5944 break; 5945 } 5946 } 5947 } else if (mem == MPLS_ENTRY_EXTDm) { 5948 if ((soc_mem_field32_get(unit, mem, entry, VALID_0f) == 0) || 5949 (soc_mem_field32_get(unit, mem, entry, VALID_1f) == 0)) { 5950 CACHE_VMAP_CLR(vmap, index); 5951 } else if (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f) != 5952 soc_mem_field32_get(unit, mem, entry, KEY_TYPE_1f)) { 5953 CACHE_VMAP_CLR(vmap, index); 5954 } else { 5955 switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f)) { 5956 case 0x06: /* 0x06 = L2GRE_SIP - key = {SIP}. */ 5957 case 0x07: /* 0x07 = L2GRE_VPNID - key = {GRE.VPNID}. */ 5958 case 0x08: /* 0x08 = L2GRE_VPNID_SIP - key = {GRE.VPNID, SIP}.*/ 5959 case 0x10: /* 0x10 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */ 5960 case 0x12: /* 0x12 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */ 5961 CACHE_VMAP_CLR(vmap, index); 5962 break; 5963 case 0x11: /* 0x11 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */ 5964 case 0x13: /* 0x13 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */ 5965 case 0x17: /* 0x17 = MIM_NVP - key = {MAC-in-MAC B-VID, B-SA}. */ 5966 case 0x18: /* 0x18 = MIM_ISID - key = {MAC-in-MAC ISID}. */ 5967 case 0x19: /* 0x19 = MIM_ISID_SVP - key = {MAC-in-MAC ISID, B-VID, B-SA}. */ 5968 case 0x1a: /* 0x1A = TRILL - key = {RBRIDGE_NICKNAME}. */ 5969 break; 5970 default: 5971 CACHE_VMAP_CLR(vmap, index); 5972 break; 5973 } 5974 } 5975 } 5976 } 5977 } 5978 #endif /* BCM_TRIUMPH3_SUPPORT */ 5979 #ifdef BCM_TRIDENT3_SUPPORT 5980 /* On TD3, we always use MPLS_ENTRY not MPLS_ENTRY_SINGLE */ 5981 else if (SOC_IS_TRIDENT3X(unit) && mem == MPLS_ENTRY_SINGLEm) { 5982 for (index = index_min; index <= index_max; index++) { 5983 CACHE_VMAP_CLR(vmap, index); 5984 } 5985 } else if(SOC_IS_TRIDENT3X(unit) && _SOC_MEM_CHK_VLAN_XLATE(mem)) { 5986 uint32 *centry; 5987 5988 for(index = index_min; index <= index_max; index++) { 5989 centry = cache + index*entry_dw; 5990 sal_memcpy(entry, centry, entry_dw * 4); 5991 if (mem == VLAN_XLATE_1_SINGLEm || 5992 mem == VLAN_XLATE_2_SINGLEm) { 5993 switch (soc_mem_field32_get(unit, mem, entry, BASE_VALIDf)) { 5994 case 1: 5995 break; 5996 case 3: 5997 case 7: 5998 default: 5999 CACHE_VMAP_CLR(vmap, index); 6000 break; 6001 } 6002 } else if (mem == VLAN_XLATE_1_DOUBLEm || 6003 mem == VLAN_XLATE_2_DOUBLEm) { 6004 switch (soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f)) { 6005 case 3: 6006 break; 6007 default: 6008 CACHE_VMAP_CLR(vmap, index); 6009 break; 6010 } 6011 switch (soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f)) { 6012 case 7: 6013 break; 6014 default: 6015 CACHE_VMAP_CLR(vmap, index); 6016 break; 6017 } 6018 } 6019 } 6020 } 6021 #endif 6022 else if (SOC_MEM_SER_CORRECTION_TYPE(unit, mem) & 6023 SOC_MEM_FLAG_SER_WRITE_CACHE_RESTORE) { 6024 uint32 *centry; 6025 6026 for (index = index_min; index <= index_max; index++) { 6027 centry = cache + index*entry_dw; 6028 if (SOC_MEM_FIELD_VALID(unit, mem, HITf)) { 6029 soc_mem_field32_set(unit, mem, centry, HITf, 0); 6030 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT0f)) { 6031 soc_mem_field32_set(unit, mem, centry, HIT0f, 0); 6032 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT1f)) { 6033 soc_mem_field32_set(unit, mem, centry, HIT1f, 0); 6034 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_0f)) { 6035 soc_mem_field32_set(unit, mem, centry, HIT_0f, 0); 6036 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_1f)) { 6037 soc_mem_field32_set(unit, mem, centry, HIT_1f, 0); 6038 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_2f)) { 6039 soc_mem_field32_set(unit, mem, centry, HIT_2f, 0); 6040 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_3f)) { 6041 soc_mem_field32_set(unit, mem, centry, HIT_3f, 0); 6042 } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_BITSf)) { 6043 soc_mem_field32_set(unit, mem, centry, HIT_BITSf, 0); 6044 } 6045 } 6046 } 6047 } 6048 } 6049 #endif /* BCM_XGS_SWITCH_SUPPORT */ 6050 6051 #ifdef BCM_TOMAHAWK_SUPPORT 6052 iter_done: 6053 #endif 6054 LOG_INFO(BSL_LS_SOC_SOCMEM, 6055 (BSL_META_U(unit, 6056 "soc_mem_cache_set: cache=%p size=%d vmap=%p\n"), 6057 (void *)cache, cache_size, (void *)vmap)); 6058 6059 memState->vmap[blk] = vmap; 6060 memState->cache[blk] = cache; 6061 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 6062 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 6063 defined(BCM_GREYHOUND_SUPPORT) 6064 if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 6065 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 6066 memState->corrupt[blk] = corrupt; 6067 } 6068 #endif 6069 if (org_mem != mem) { 6070 /* Share the cache and vmap */ 6071 SOC_MEM_STATE(unit, org_mem).cache[blk] = cache; 6072 SOC_MEM_STATE(unit, org_mem).vmap[blk] = vmap; 6073 } else if (_SOC_MEM_IS_REUSED_MEM(unit, mem)) { 6074 /* Sync the cache and vmap */ 6075 _SOC_MEM_SYNC_MAPPED_MEM_STATES(unit, mem); 6076 } 6077 } 6078 6079 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 6080 #ifdef BCM_WARM_BOOT_SUPPORT 6081 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) || 6082 SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit))&& 6083 (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_GM_FIELDSm)) { 6084 int rv; 6085 if ((rv = soc_mem_overlay_tcam_cache_set 6086 (unit, mem, copyno, enable)) != SOC_E_NONE) { 6087 MEM_UNLOCK(unit, mem); 6088 return rv; 6089 } 6090 } 6091 #endif 6092 #endif 6093 6094 MEM_UNLOCK(unit, mem); 6095 6096 /* 6097 * COVERITY 6098 * 6099 * This is a false positive alarm. 6100 * corrupt pointer is assigned to memState->corrupt[blk]. 6101 */ 6102 /* coverity[leaked_storage] */ 6103 return SOC_E_NONE; 6104 } 6105 6106 /* 6107 * Function: 6108 * soc_mem_cache_invalidate 6109 * Purpose: 6110 * Invalidate a cache entry. Forces read from the device instead 6111 * of from cached copy. 6112 */ 6113 6114 int 6115 soc_mem_cache_invalidate(int unit, soc_mem_t mem, int copyno, int index) 6116 { 6117 int blk; 6118 uint8 *vmap; 6119 6120 assert(SOC_UNIT_VALID(unit)); 6121 _SOC_MEM_REUSE_MEM_STATE(unit, mem); 6122 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 6123 assert(SOC_MEM_IS_VALID(unit, mem)); 6124 6125 if (!soc_mem_is_cachable(unit, mem)) { 6126 return SOC_E_UNAVAIL; 6127 } 6128 6129 if (index < soc_mem_index_min(unit, mem) || 6130 index > soc_mem_index_max(unit, mem)) { 6131 LOG_WARN(BSL_LS_SOC_SOCMEM, 6132 (BSL_META_U(unit, 6133 "soc_mem_cache_invalidate: invalid index %d " 6134 "for memory %s\n"), 6135 index, SOC_MEM_NAME(unit, mem))); 6136 return SOC_E_PARAM; 6137 } 6138 6139 MEM_LOCK(unit, mem); 6140 6141 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 6142 if (copyno != SOC_BLOCK_ALL && copyno != blk) { 6143 continue; 6144 } 6145 6146 if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) { 6147 continue; 6148 } 6149 6150 /* Invalidate the cached entry */ 6151 6152 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 6153 CACHE_VMAP_CLR(vmap, index); 6154 } 6155 6156 MEM_UNLOCK(unit, mem); 6157 6158 return SOC_E_NONE; 6159 } 6160 6161 /* 6162 * Function: 6163 * _soc_mem_bits_move_one_byte() 6164 * Purpose: 6165 * same as _soc_mem_bits_move, but only for a single byte. 6166 * Parameters: 6167 * dst_ptr - (IN) bit stream address. 6168 * dst_first - (IN) starting bit after the address pointed to by dst_ptr. 6169 * src - (IN) src byte. 6170 * src_first - (IN) starting bit in src byte. 6171 * nbits - (IN) the number of conntiguous bits to be move. 6172 * Returns: 6173 * BCM_E_XXX - Function status. 6174 * Notes: 6175 * The following constraints are kept: 6176 * a. dst_first < 8 6177 * b. src_first < 8 6178 * c. dst_first + nbits <= 8 6179 * d. src_first + nbits <= 8 6180 */ 6181 6182 static void 6183 _soc_mem_bits_move_one_byte(uint8 *dst_ptr, int dst_first, uint8 src, int src_first, int nbits) 6184 { 6185 uint8 data; 6186 uint8 mask; 6187 6188 /* no need to check that dst_first == 0 and src_first == 0, 6189 It must be becuse of the constrains */ 6190 if ((nbits) == 8) { 6191 *(dst_ptr) = src; 6192 return; 6193 } 6194 /* get the data */ 6195 data = src >> (src_first); 6196 /* align the data to the place it may be inserted */ 6197 data <<= (dst_first); 6198 6199 mask = ~0; 6200 mask >>= 8 - nbits; 6201 mask <<= dst_first; 6202 data &= mask; /* clear possile bits in src above src_first + range */ 6203 *(dst_ptr) &= ~mask; 6204 *(dst_ptr) |= data; 6205 } 6206 6207 /* 6208 * Function: 6209 * soc_mem_bits_move() 6210 * Purpose: 6211 * same as _soc_mem_bits_move, but only for a single byte. 6212 * Parameters: 6213 * dst_ptr - (IN) dst bit stream address. 6214 * dst_first - (IN) starting bit after the address pointed to by dst_ptr. 6215 * src_ptr - (IN) src bit stream address. 6216 * src_first - (IN) starting bit after the address pointed to by src_ptr. 6217 * nbits - (IN) the number of conntiguous bits to be move. 6218 * Returns: 6219 * BCM_E_XXX - Function status. 6220 * Notes: 6221 */ 6222 6223 static void 6224 _soc_mem_bits_move(uint8 *dst_ptr, int dst_first, uint8 *src_ptr, int src_first, int nbits) 6225 { 6226 if (nbits <= 0) { 6227 return; 6228 } 6229 6230 if ((((dst_first) & 0x7) == 0) && 6231 (((src_first) & 0x7) == 0) && 6232 (((nbits) & 0x7) == 0)) { 6233 sal_memcpy(&((dst_ptr)[(dst_first) >> 3]), 6234 &((src_ptr)[(src_first) >> 3]), 6235 ((nbits) >> 3)); 6236 } else { 6237 uint8 *cur_dst; 6238 uint8 *cur_src; 6239 int woff_src, woff_dst, wremain; 6240 6241 cur_dst = (dst_ptr) + ((dst_first) >> 3); 6242 cur_src = (src_ptr) + ((src_first) >> 3); 6243 6244 woff_src = src_first & 0x7; 6245 woff_dst = dst_first & 0x7; 6246 6247 if (woff_dst >= woff_src) { 6248 wremain = 8 - woff_dst; 6249 } else { 6250 wremain = 8 - woff_src; 6251 } 6252 if (nbits <= wremain) { 6253 _soc_mem_bits_move_one_byte(cur_dst, woff_dst, *cur_src, woff_src, nbits); 6254 return; 6255 } 6256 _soc_mem_bits_move_one_byte(cur_dst, woff_dst, *cur_src, woff_src, wremain); 6257 nbits -= wremain; 6258 6259 while (nbits >= 8) { 6260 if (woff_dst >= woff_src) { 6261 ++cur_dst; 6262 wremain = woff_dst - woff_src; 6263 if(wremain > 0) { 6264 _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain, wremain); 6265 } 6266 } else { 6267 ++cur_src; 6268 wremain = woff_src - woff_dst; 6269 _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, wremain); 6270 } 6271 nbits -= wremain; 6272 wremain = 8 - wremain; 6273 if (woff_dst >= woff_src) { 6274 ++cur_src; 6275 _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, wremain); 6276 } else { 6277 ++cur_dst; 6278 _soc_mem_bits_move_one_byte(cur_dst, 6279 0, 6280 *cur_src, 6281 8 - wremain, 6282 wremain); 6283 } 6284 nbits -= wremain; 6285 } 6286 6287 if (woff_dst >= woff_src) { 6288 ++cur_dst; 6289 wremain = woff_dst - woff_src; 6290 if (nbits <= wremain) { 6291 if(nbits > 0) { 6292 _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain, nbits); 6293 } 6294 return; 6295 } 6296 if(wremain > 0) { 6297 _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain, wremain); 6298 } 6299 } else { 6300 ++cur_src; 6301 wremain = woff_src - woff_dst; 6302 if (nbits <= wremain) { 6303 if(nbits > 0) { 6304 _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, nbits); 6305 } 6306 return; 6307 } 6308 _soc_mem_bits_move_one_byte(cur_dst, 6309 8 - wremain, 6310 *cur_src, 6311 0, 6312 wremain); 6313 } 6314 nbits -= wremain; 6315 6316 if(nbits > 0) { 6317 wremain = 8 - wremain; 6318 if (woff_dst >= woff_src) { 6319 ++cur_src; 6320 _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, nbits); 6321 } else { 6322 ++cur_dst; 6323 _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain, nbits); 6324 } 6325 } 6326 } 6327 } 6328 6329 6330 /* 6331 * Move Cached old entries (block) to new location and invalidate the old entries. 6332 * Imitate HW Support to move block of entries. 6333 */ 6334 int soc_mem_cache_block_move(int unit, /* unit of the memory */ 6335 uint32 flags, /* flags */ 6336 soc_mem_t mem, /* Memory to be written to */ 6337 unsigned src_arr_index, /* min array index to be written to, not used in memories which are not arrays */ 6338 unsigned dest_arr_index, /* max array index to be written to, not used in memories which are not arrays */ 6339 int copyno, /* Memory block to write to */ 6340 int src_index_start, /* start memory index to read from and to invalidate */ 6341 int dest_index_start, /* start memory index to write */ 6342 int entries_count) /* number of entries to move (Range) */ 6343 { 6344 int blk, index; 6345 int entry_dw = soc_mem_entry_words(unit, mem); 6346 int block_size_byte = WORDS2BYTES(entries_count * entry_dw); 6347 int src_index_end = src_index_start + entries_count - 1; 6348 int dest_index_end = dest_index_start + entries_count - 1; 6349 int src_mem_array_vmap_offset, src_mem_array_cache_offset; 6350 int dest_mem_array_vmap_offset, dest_mem_array_cache_offset; 6351 int invalidate_index_start, invalidate_index_end; 6352 uint32 *cache; 6353 uint8 *vmap; 6354 uint8 *tmp_cache_block; 6355 uint8 *tmp_vmap; 6356 6357 6358 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 6359 (BSL_META_U(unit, 6360 "%s: unit %d, memory %s, block %s, copyno %d, src_index_start %d, \ndest_index_start %d, entries_count %d, entry_dw=%d, \nind_min=%d, ind_max=%d\n src_arr_index=%d, dest_arr_index=%d\n"), 6361 FUNCTION_NAME(), unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno), 6362 copyno, src_index_start, dest_index_start, entries_count, entry_dw, soc_mem_index_min(unit, mem), soc_mem_index_max(unit, mem), src_arr_index, dest_arr_index)); 6363 6364 if (!soc_mem_is_valid(unit, mem)) 6365 { 6366 return SOC_E_MEMORY; 6367 } 6368 6369 if (!soc_mem_is_cachable(unit, mem)) 6370 { 6371 /* If cache is not available just return */ 6372 return SOC_E_NONE; 6373 } 6374 6375 if ((entries_count < 0) || (entries_count > soc_mem_index_count(unit, mem))) 6376 { 6377 LOG_ERROR(BSL_LS_SOC_SOCMEM, 6378 (BSL_META_U(unit, 6379 "%s: invalid entries_count=%d for memory %s\n"), FUNCTION_NAME(), entries_count, SOC_MEM_NAME( unit, mem))); 6380 return SOC_E_PARAM; 6381 } 6382 6383 if (((src_index_start < soc_mem_index_min(unit, mem)) 6384 || (src_index_end > soc_mem_index_max(unit, mem))) 6385 || ((dest_index_start < soc_mem_index_min(unit, mem)) 6386 || (dest_index_end > soc_mem_index_max(unit, mem)))) 6387 { 6388 LOG_ERROR(BSL_LS_SOC_SOCMEM, 6389 (BSL_META_U(unit, "%s: invalid index for memory %s\n"), FUNCTION_NAME(), SOC_MEM_NAME(unit, mem))); 6390 return SOC_E_PARAM; 6391 } 6392 6393 if ((tmp_cache_block = sal_alloc(block_size_byte, "tmp_cache_block")) == NULL) 6394 { 6395 return SOC_E_MEMORY; 6396 } 6397 6398 src_mem_array_vmap_offset = src_arr_index * soc_mem_index_count(unit, mem); 6399 src_mem_array_cache_offset = src_mem_array_vmap_offset * entry_dw; 6400 dest_mem_array_vmap_offset = dest_arr_index * soc_mem_index_count(unit, mem); 6401 dest_mem_array_cache_offset = dest_mem_array_vmap_offset * entry_dw; 6402 6403 if ((tmp_vmap = sal_alloc(((src_mem_array_vmap_offset + src_index_start + entries_count + 7) / 8), "tmp_vmap")) == NULL) 6404 { 6405 sal_free(tmp_cache_block); 6406 return SOC_E_MEMORY; 6407 } 6408 6409 /* Calculate the index range for invalidation */ 6410 if ((src_index_start > dest_index_start) && (src_index_start <= dest_index_end) && (src_arr_index == dest_arr_index)) 6411 { 6412 /* overlapping move up */ 6413 invalidate_index_start = dest_index_end + 1; 6414 invalidate_index_end = src_index_end; 6415 } 6416 else if((dest_index_start > src_index_start) && (dest_index_start <= src_index_end) && (src_arr_index == dest_arr_index)) 6417 { 6418 /* overlapping move down */ 6419 invalidate_index_start = src_index_start; 6420 invalidate_index_end = dest_index_start - 1; 6421 } 6422 else 6423 { 6424 /* not-overlapping move */ 6425 invalidate_index_start = src_index_start; 6426 invalidate_index_end = src_index_end; 6427 } 6428 6429 /* Copy cache entries + invalidate old entries */ 6430 MEM_LOCK(unit, mem); 6431 6432 SOC_MEM_BLOCK_ITER(unit, mem, blk) 6433 { 6434 if (copyno != SOC_BLOCK_ALL && copyno != blk) 6435 { 6436 continue; 6437 } 6438 6439 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 6440 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 6441 6442 if (cache == NULL) 6443 { 6444 continue; 6445 } 6446 6447 /* Copy cache entries from old location to new location. We are doing it in 2 copies since the blocks can overlap. */ 6448 sal_memcpy(tmp_cache_block, cache + src_mem_array_cache_offset+ (src_index_start * entry_dw), block_size_byte); 6449 sal_memcpy(cache + dest_mem_array_cache_offset + (dest_index_start * entry_dw), tmp_cache_block, block_size_byte); 6450 6451 /* Copy vmap from old location to new location. We are doing it in 2 copies since the blocks can overlap. */ 6452 sal_memcpy(tmp_vmap, vmap, ((src_mem_array_vmap_offset + src_index_start + entries_count + 7) / 8)); 6453 _soc_mem_bits_move(vmap, dest_mem_array_vmap_offset + dest_index_start, tmp_vmap, src_mem_array_vmap_offset + src_index_start, entries_count); 6454 6455 /* Invalidate the cached entry */ 6456 for (index = invalidate_index_start; index <= invalidate_index_end; index++) 6457 { 6458 CACHE_VMAP_CLR(vmap, src_mem_array_vmap_offset + index); 6459 } 6460 } 6461 6462 MEM_UNLOCK(unit, mem); 6463 6464 sal_free(tmp_cache_block); 6465 sal_free(tmp_vmap); 6466 6467 return SOC_E_NONE; 6468 6469 } 6470 6471 6472 #ifdef BCM_WARM_BOOT_SUPPORT 6473 6474 /* 6475 * Mem cache structure: 6476 * +++++++++++++++++++++++++++ 6477 * | Mem 0: Name string | -> 128 characters 6478 * +++++++++++++++++++++++++++ 6479 * | | 6480 * | Mem table | 6481 * | | 6482 * | | 6483 * +++++++++++++++++++++++++++ 6484 * | Valid bitmap | 6485 * +++++++++++++++++++++++++++ 6486 * .... 6487 * .... 6488 * .... 6489 * .... 6490 * +++++++++++++++++++++++++++ 6491 * | Mem n: Name string | 6492 * +++++++++++++++++++++++++++ 6493 * | | 6494 * | Mem table | 6495 * | | 6496 * | | 6497 * +++++++++++++++++++++++++++ 6498 * | Valid bitmap | 6499 * +++++++++++++++++++++++++++ 6500 * | | 6501 * | Reg cache | 6502 * | | 6503 * +++++++++++++++++++++++++++ 6504 */ 6505 6506 int 6507 soc_mem_scache_size_get(int unit) 6508 { 6509 int size = 0; 6510 #if defined(BCM_XGS_SUPPORT) 6511 int count; 6512 soc_ser_reg_cache_info(unit, &count, &size); 6513 #endif 6514 return size + SOC_STAT(unit)->mem_cache_size + 6515 SOC_STAT(unit)->mem_cache_count*128; 6516 } 6517 6518 int 6519 soc_mem_cache_scache_init(int unit) 6520 { 6521 uint32 alloc_get; 6522 soc_scache_handle_t scache_handle; 6523 uint8 *mem_scache_ptr; 6524 int rv, stable_size, alloc_sz = soc_mem_scache_size_get(unit); 6525 6526 /* This code is not executed for now, but will enable it in future 6527 if required */ 6528 if (0 /*NULL == SOC_CONTROL(unit)->mem_scache_ptr*/) { 6529 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 6530 if ((stable_size > SOC_DEFAULT_LVL2_STABLE_SIZE) && 6531 !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 6532 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 6533 SOC_SCACHE_MEMCACHE_HANDLE, 0); 6534 /* Get the pointer for the Level 2 cache */ 6535 rv = soc_scache_ptr_get(unit, scache_handle, 6536 &mem_scache_ptr, &alloc_get); 6537 if (!SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) { 6538 /* Not yet allocated in Cold Boot */ 6539 SOC_IF_ERROR_RETURN 6540 (soc_scache_alloc(unit, scache_handle, 6541 alloc_sz + SOC_WB_SCACHE_CONTROL_SIZE)); 6542 rv = soc_scache_ptr_get(unit, scache_handle, 6543 &mem_scache_ptr, &alloc_get); 6544 if (SOC_FAILURE(rv)) { 6545 return rv; 6546 } else if (alloc_get != alloc_sz + 6547 SOC_WB_SCACHE_CONTROL_SIZE) { 6548 /* Expected size doesn't match retrieved size */ 6549 return SOC_E_INTERNAL; 6550 } else if (NULL == mem_scache_ptr) { 6551 return SOC_E_MEMORY; 6552 } 6553 SOC_CONTROL(unit)->mem_scache_ptr = mem_scache_ptr; 6554 } 6555 } 6556 } 6557 return SOC_E_NONE; 6558 } 6559 6560 int 6561 soc_mem_cache_scache_sync(int unit) 6562 { 6563 uint32 *cache; 6564 int blk, entry_dw, index_cnt; 6565 int cache_size, vmap_size, offset= 0; 6566 soc_mem_t mem, tmp_mem; 6567 uint8 *vmap, *mem_scache_ptr = SOC_CONTROL(unit)->mem_scache_ptr; 6568 6569 if (NULL == mem_scache_ptr) { 6570 return SOC_E_UNAVAIL; 6571 } 6572 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 6573 if (!SOC_MEM_IS_VALID(unit, mem)) { 6574 continue; 6575 } 6576 if (soc_mem_index_count(unit, mem) == 0) { 6577 continue; 6578 } 6579 tmp_mem = mem; 6580 _SOC_MEM_REUSE_MEM_STATE(unit, tmp_mem); 6581 if (tmp_mem != mem) { 6582 continue; 6583 } 6584 entry_dw = soc_mem_entry_words(unit, mem); 6585 index_cnt = soc_mem_index_count(unit, mem); 6586 cache_size = index_cnt * entry_dw * 4; 6587 vmap_size = (index_cnt + 7) / 8; 6588 6589 MEM_LOCK(unit, mem); 6590 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 6591 if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) { 6592 continue; 6593 } 6594 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 6595 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 6596 6597 sal_memcpy(mem_scache_ptr+offset, SOC_MEM_UFNAME(unit, mem), 6598 strlen(SOC_MEM_UFNAME(unit, mem))); 6599 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 6600 (BSL_META_U(unit, 6601 "Store at %d %s\n"), offset, SOC_MEM_UFNAME(unit, mem))); 6602 offset += 128; 6603 sal_memcpy(mem_scache_ptr+offset, cache, cache_size); 6604 offset += cache_size; 6605 sal_memcpy(mem_scache_ptr+offset, vmap, vmap_size); 6606 offset += vmap_size; 6607 } 6608 MEM_UNLOCK(unit, mem); 6609 } 6610 return SOC_E_NONE; 6611 } 6612 6613 int 6614 soc_mem_cache_scache_get(int unit) 6615 { 6616 uint32 alloc_get; 6617 soc_scache_handle_t scache_handle; 6618 uint8 *mem_scache_ptr; 6619 int stable_size; 6620 6621 /* This code is not executed for now, but will enable it in future 6622 if required */ 6623 if (0 /*NULL == SOC_CONTROL(unit)->mem_scache_ptr*/) { 6624 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 6625 if ((stable_size > SOC_DEFAULT_LVL2_STABLE_SIZE) && 6626 !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 6627 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 6628 SOC_SCACHE_MEMCACHE_HANDLE, 0); 6629 /* Get the pointer for the Level 2 cache */ 6630 SOC_IF_ERROR_RETURN 6631 (soc_scache_ptr_get(unit, scache_handle, 6632 &mem_scache_ptr, &alloc_get)); 6633 if (alloc_get == 0) { 6634 return SOC_E_INTERNAL; 6635 } else if (NULL == mem_scache_ptr) { 6636 return SOC_E_MEMORY; 6637 } 6638 SOC_CONTROL(unit)->mem_scache_ptr = mem_scache_ptr; 6639 } 6640 } 6641 return SOC_E_NONE; 6642 } 6643 6644 int 6645 soc_mem_cache_scache_load(int unit, soc_mem_t mem, int *offset) 6646 { 6647 int blk, entry_dw, index_cnt; 6648 int cache_size, vmap_size; 6649 uint32 *cache; 6650 uint8 *vmap, *mem_scache_ptr = SOC_CONTROL(unit)->mem_scache_ptr; 6651 6652 if (SOC_WARM_BOOT(unit) && SOC_CONTROL(unit)->mem_scache_ptr) { 6653 entry_dw = soc_mem_entry_words(unit, mem); 6654 index_cnt = soc_mem_index_count(unit, mem); 6655 cache_size = index_cnt * entry_dw * 4; 6656 vmap_size = (index_cnt + 7) / 8; 6657 6658 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 6659 if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) { 6660 continue; 6661 } 6662 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 6663 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 6664 6665 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 6666 (BSL_META_U(unit, 6667 "Load from %d %s to %s\n"), *offset, 6668 mem_scache_ptr + *offset, SOC_MEM_UFNAME(unit, mem))); 6669 *offset += 128; 6670 sal_memcpy(cache, mem_scache_ptr + *offset, cache_size); 6671 *offset += cache_size; 6672 sal_memcpy(vmap, mem_scache_ptr + *offset, vmap_size); 6673 *offset += vmap_size; 6674 } 6675 } 6676 return SOC_E_NONE; 6677 } 6678 6679 int 6680 soc_control_defip_scache_init(int unit) 6681 { 6682 soc_scache_handle_t scache_handle; 6683 uint8 *l3_defip_scache_ptr; 6684 int rv; 6685 int stable_size; 6686 uint16 version = SOC_DEFIP_WARMBOOT_DEFAULT_VERSION; 6687 int alloc_sz = sizeof(SOC_L3_DEFIP_MAX_128B_ENTRIES(unit)) + 6688 sizeof(version); 6689 int create = SOC_WARM_BOOT(unit) ? FALSE : TRUE; 6690 6691 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 6692 if (!stable_size) { 6693 /* If stable not allocated, just return */ 6694 return SOC_E_NONE; 6695 } 6696 SOC_SCACHE_ALIGN_SIZE(alloc_sz); 6697 6698 alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE; 6699 6700 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 6701 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 6702 SOC_SCACHE_SOC_DEFIP_HANDLE, 0); 6703 /* Get the pointer for the Level 2 cache */ 6704 rv = soc_extended_scache_ptr_get(unit, scache_handle, create, 6705 create ? alloc_sz : 0, 6706 &l3_defip_scache_ptr); 6707 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 6708 return rv; 6709 } else if (SOC_E_NOT_FOUND == rv && !create) { 6710 /* Not yet allocated in upgrade */ 6711 rv = soc_extended_scache_ptr_get(unit, scache_handle, TRUE, 6712 alloc_sz, 6713 &l3_defip_scache_ptr); 6714 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 6715 return rv; 6716 } 6717 if (SOC_SUCCESS(rv)) { 6718 SOC_L3_DEFIP_SCACHE_HANDLE(unit) = l3_defip_scache_ptr; 6719 } 6720 } else if (SOC_FAILURE(rv)) { 6721 return rv; 6722 } else { 6723 SOC_L3_DEFIP_SCACHE_HANDLE(unit) = l3_defip_scache_ptr; 6724 } 6725 } 6726 6727 return SOC_E_NONE; 6728 } 6729 6730 6731 int 6732 soc_control_defip_scache_sync(int unit) 6733 { 6734 uint8 *l3_defip_scache_ptr = SOC_L3_DEFIP_SCACHE_HANDLE(unit); 6735 int scache_size = sizeof(SOC_L3_DEFIP_MAX_128B_ENTRIES(unit)); 6736 int stable_size = 0; 6737 uint16 version = SOC_DEFIP_WARMBOOT_DEFAULT_VERSION; 6738 6739 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 6740 if (!stable_size) { 6741 /* If stable not allocated, just return */ 6742 return SOC_E_NONE; 6743 } 6744 if (NULL == l3_defip_scache_ptr) { 6745 return SOC_E_UNAVAIL; 6746 } 6747 6748 /* First save version */ 6749 sal_memcpy(l3_defip_scache_ptr, &version, sizeof(version)); 6750 sal_memcpy(l3_defip_scache_ptr + sizeof(version), 6751 &SOC_L3_DEFIP_MAX_128B_ENTRIES(unit), 6752 scache_size); 6753 return SOC_E_NONE; 6754 } 6755 6756 int 6757 soc_control_defip_scache_load(int unit, int *num_ipv6_128b_entries) 6758 { 6759 uint8 *l3_defip_scache_ptr = NULL; 6760 int scache_size = sizeof(SOC_L3_DEFIP_MAX_128B_ENTRIES(unit)); 6761 int stable_size = 0; 6762 uint16 version = 0; 6763 6764 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 6765 if (!stable_size) { 6766 /* If stable not allocated, just return */ 6767 return SOC_E_RESOURCE; 6768 } 6769 6770 l3_defip_scache_ptr = SOC_L3_DEFIP_SCACHE_HANDLE(unit); 6771 if (l3_defip_scache_ptr == NULL) { 6772 return SOC_E_RESOURCE; 6773 } 6774 if (SOC_WARM_BOOT(unit)) { 6775 sal_memcpy(&version, l3_defip_scache_ptr, sizeof(version)); 6776 if (version >= SOC_DEFIP_WARMBOOT_VERSION_1) { 6777 sal_memcpy(num_ipv6_128b_entries, 6778 l3_defip_scache_ptr + sizeof(version), 6779 scache_size); 6780 } else { 6781 return SOC_E_UNAVAIL; 6782 } 6783 } 6784 return SOC_E_NONE; 6785 } 6786 #endif /* BCM_WARM_BOOT_SUPPORT */ 6787 6788 /************************************************************************/ 6789 /* Routines for CFAPINIT */ 6790 /************************************************************************/ 6791 6792 #ifdef BCM_ESW_SUPPORT 6793 /* 6794 * Function: 6795 * cfapinit_write_cb (internal) 6796 * Purpose: 6797 * Memory test callback routine for cfapinit 6798 */ 6799 6800 static int 6801 cfapinit_write_cb(struct soc_mem_test_s *parm, 6802 unsigned array_index, 6803 int copyno, 6804 int index, 6805 uint32 *entry_data) 6806 { 6807 return soc_mem_array_write(parm->unit, parm->mem, array_index, copyno, 6808 index, entry_data); 6809 } 6810 6811 /* 6812 * Function: 6813 * cfapinit_read_cb (internal) 6814 * Purpose: 6815 * Memory test callback routine for cfapinit 6816 */ 6817 6818 static int 6819 cfapinit_read_cb(struct soc_mem_test_s *parm, 6820 unsigned array_index, 6821 int copyno, 6822 int index, 6823 uint32 *entry_data) 6824 { 6825 return soc_mem_array_read(parm->unit, parm->mem, array_index, copyno, index, 6826 entry_data); 6827 } 6828 6829 /* 6830 * Function: 6831 * cfapinit_miscompare_cb (internal) 6832 * Purpose: 6833 * Memory test callback routine for cfapinit 6834 */ 6835 6836 static int 6837 cfapinit_miscompare_cb(struct soc_mem_test_s *parm, 6838 unsigned array_index, 6839 int copyno, 6840 int index, 6841 uint32 *read_data, 6842 uint32 *wrote_data, 6843 uint32 *mask_data) 6844 { 6845 uint8 *bad_list = parm->userdata; 6846 6847 COMPILER_REFERENCE(array_index); 6848 COMPILER_REFERENCE(copyno); 6849 COMPILER_REFERENCE(read_data); 6850 COMPILER_REFERENCE(wrote_data); 6851 COMPILER_REFERENCE(mask_data); 6852 6853 bad_list[index - parm->index_start] = 1; 6854 6855 return 1; 6856 } 6857 6858 #endif /* BCM_ESW_SUPPORT */ 6859 /* 6860 * Function: 6861 * soc_mem_cfap_init 6862 * Purpose: 6863 * Routine to diagnose and initialize CFAP pool. 6864 * Notes: 6865 * Ordinarily this routine is not used. When the chip is reset, it 6866 * automatically writes the CFAP table with the correct pointer 6867 * data. 6868 * 6869 * This routine does the same thing, except it also runs a memory 6870 * test and excludes bad entries in CBPHEADER/CBPDATA[0-3] from the 6871 * CFAP pool. 6872 * 6873 * On some devices, errors in the first 63 entries can't be eliminated. 6874 * The routine fails if such errors are found. 6875 */ 6876 6877 #ifdef BCM_ESW_SUPPORT 6878 int 6879 soc_mem_cfap_init(int unit) 6880 { 6881 soc_mem_test_t mt; 6882 uint8 *bad_list; 6883 int entry_count, bad_count, bad_count_63; 6884 int i, ptr, rv; 6885 uint32 cfappoolsize; 6886 soc_mem_t cbpcellheader_m; 6887 soc_mem_t cbppktheader_start_m; 6888 soc_mem_t cbppktheader_end_m; 6889 soc_mem_t cbpdata_start_m; 6890 soc_mem_t cbpdata_end_m; 6891 soc_mem_t cfap_m; 6892 6893 if (!SOC_IS_XGS_SWITCH(unit)) { 6894 return SOC_E_NONE; 6895 } 6896 6897 if (!soc_feature(unit, soc_feature_cfap_pool)) { 6898 return SOC_E_UNAVAIL; 6899 } 6900 6901 cbpcellheader_m = MMU_CBPCELLHEADERm; 6902 cbppktheader_start_m = MMU_CBPPKTHEADER0m; 6903 cbppktheader_end_m = MMU_CBPPKTHEADER1m; 6904 cbpdata_start_m = MMU_CBPDATA0m; 6905 cbpdata_end_m = MMU_CBPDATA15m; 6906 cfap_m = MMU_CFAPm; 6907 SOC_IF_ERROR_RETURN(READ_CFAPCONFIGr(unit, &cfappoolsize)); 6908 cfappoolsize = soc_reg_field_get(unit, CFAPCONFIGr, 6909 cfappoolsize, CFAPPOOLSIZEf); 6910 6911 mt.unit = unit; 6912 mt.patterns = soc_property_get(unit, spn_CFAP_TESTS, 6913 MT_PAT_CHECKER | MT_PAT_ICHECKER); 6914 mt.copyno = COPYNO_ALL; 6915 mt.index_start = soc_mem_index_min(unit, cbpcellheader_m); 6916 mt.index_end = soc_mem_index_max(unit, cbpcellheader_m); 6917 mt.index_step = 1; 6918 mt.read_count = 1; 6919 mt.status_cb = 0; /* No status */ 6920 mt.write_cb = cfapinit_write_cb; 6921 mt.read_cb = cfapinit_read_cb; 6922 mt.miscompare_cb = cfapinit_miscompare_cb; 6923 6924 /* 6925 * Create array of status per entry, initially with all entries 6926 * marked good. The test callback will mark bad entries. 6927 */ 6928 6929 entry_count = mt.index_end - mt.index_start + 1; 6930 6931 if ((bad_list = sal_alloc(entry_count, "bad_list")) == NULL) { 6932 return SOC_E_MEMORY; 6933 } 6934 6935 sal_memset(bad_list, 0, entry_count); 6936 6937 /* 6938 * Test the five "parallel" memories: CBPHEADER and CBPDATA[0-3]. 6939 */ 6940 6941 mt.userdata = bad_list; 6942 mt.mem = cbpcellheader_m; 6943 LOG_VERBOSE(BSL_LS_SOC_COMMON, 6944 (BSL_META_U(unit, 6945 "soc_mem_cfap_init: unit %d: testing CBPHEADER\n"), 6946 unit)); 6947 6948 if ((rv = soc_mem_parity_control(unit, mt.mem, 6949 mt.copyno, FALSE)) < 0) { 6950 LOG_ERROR(BSL_LS_SOC_SOCMEM, 6951 (BSL_META_U(unit, 6952 "Unable to disable parity warnings on %s\n"), 6953 SOC_MEM_UFNAME(unit, mt.mem))); 6954 goto done; 6955 } 6956 6957 (void) soc_mem_test(&mt); 6958 6959 if ((rv = soc_mem_parity_control(unit, mt.mem, 6960 mt.copyno, TRUE)) < 0) { 6961 LOG_ERROR(BSL_LS_SOC_SOCMEM, 6962 (BSL_META_U(unit, 6963 "Unable to disable parity warnings on %s\n"), 6964 SOC_MEM_UFNAME(unit, mt.mem))); 6965 goto done; 6966 } 6967 6968 for (mt.mem = cbppktheader_start_m; 6969 mt.mem <= cbppktheader_end_m; 6970 mt.mem++) { 6971 LOG_VERBOSE(BSL_LS_SOC_COMMON, 6972 (BSL_META_U(unit, 6973 "soc_mem_cfap_init: unit %d: testing CBPPKTHEADER%d\n"), 6974 unit, mt.mem - cbppktheader_start_m)); 6975 6976 if ((rv = soc_mem_parity_control(unit, mt.mem, 6977 mt.copyno, FALSE)) < 0) { 6978 LOG_ERROR(BSL_LS_SOC_SOCMEM, 6979 (BSL_META_U(unit, 6980 "Unable to disable parity warnings on %s\n"), 6981 SOC_MEM_UFNAME(unit, mt.mem))); 6982 goto done; 6983 } 6984 (void) soc_mem_test(&mt); 6985 6986 if ((rv = soc_mem_parity_control(unit, mt.mem, 6987 mt.copyno, TRUE)) < 0) { 6988 LOG_ERROR(BSL_LS_SOC_SOCMEM, 6989 (BSL_META_U(unit, 6990 "Unable to disable parity warnings on %s\n"), 6991 SOC_MEM_UFNAME(unit, mt.mem))); 6992 goto done; 6993 } 6994 } 6995 6996 for (mt.mem = cbpdata_start_m; 6997 mt.mem <= cbpdata_end_m; 6998 mt.mem++) { 6999 LOG_VERBOSE(BSL_LS_SOC_COMMON, 7000 (BSL_META_U(unit, 7001 "soc_mem_cfap_init: unit %d: testing CBPDATA%d\n"), 7002 unit, mt.mem - cbpdata_start_m)); 7003 7004 if ((rv = soc_mem_parity_control(unit, mt.mem, 7005 mt.copyno, FALSE)) < 0) { 7006 LOG_ERROR(BSL_LS_SOC_SOCMEM, 7007 (BSL_META_U(unit, 7008 "Unable to disable parity warnings on %s\n"), 7009 SOC_MEM_UFNAME(unit, mt.mem))); 7010 goto done; 7011 } 7012 (void) soc_mem_test(&mt); 7013 7014 if ((rv = soc_mem_parity_control(unit, mt.mem, 7015 mt.copyno, TRUE)) < 0) { 7016 LOG_ERROR(BSL_LS_SOC_SOCMEM, 7017 (BSL_META_U(unit, 7018 "Unable to disable parity warnings on %s\n"), 7019 SOC_MEM_UFNAME(unit, mt.mem))); 7020 goto done; 7021 } 7022 } 7023 7024 /* 7025 * Test only 7026 for (i = 1; i < 512; i += 2) { 7027 if (i < entry_count) { 7028 bad_list[i] = 1; 7029 } 7030 } 7031 */ 7032 7033 bad_count = 0; 7034 bad_count_63 = 0; 7035 7036 for (i = mt.index_start; i <= mt.index_end; i++) { 7037 if (bad_list[i - mt.index_start]) { 7038 bad_count++; 7039 if (i < mt.index_start + 63) { 7040 bad_count_63++; 7041 } 7042 } 7043 } 7044 7045 if (bad_count_63 > 0) { 7046 /* 7047 * On some devices the first 63 entries MUST be good since they are 7048 * allocated by the hardware on startup. 7049 */ 7050 7051 LOG_CLI((BSL_META_U(unit, 7052 "soc_mem_cfap_init: unit %d: " 7053 "Chip unusable, %d error(s) in low entries\n"), 7054 unit, bad_count_63)); 7055 sal_free(bad_list); 7056 return SOC_E_FAIL; 7057 } 7058 7059 if (bad_count >= entry_count / 2) { 7060 LOG_CLI((BSL_META_U(unit, 7061 "soc_mem_cfap_init: unit %d: " 7062 "Chip unusable, too many bad entries (%d)\n"), 7063 unit, bad_count)); 7064 sal_free(bad_list); 7065 return SOC_E_FAIL; 7066 } 7067 7068 /* 7069 * For each bad entry, swap it with a good entry taken from the end 7070 * of the list. This puts all bad entries at the end of the table 7071 * where they will not be used. 7072 */ 7073 7074 ptr = mt.index_end + 1; 7075 7076 for (i = mt.index_start; i < ptr; i++) { 7077 uint32 e_good, e_bad; 7078 7079 if (bad_list[i - mt.index_start]) { 7080 LOG_VERBOSE(BSL_LS_SOC_COMMON, 7081 (BSL_META_U(unit, 7082 "soc_mem_cfap_init: unit %d: " 7083 "mapping out CBP index %d\n"), 7084 unit, i)); 7085 7086 do { 7087 --ptr; 7088 } while (bad_list[ptr - mt.index_start]); 7089 7090 if ((rv = soc_mem_read(unit, cfap_m, 7091 MEM_BLOCK_ANY, i, &e_bad)) < 0) { 7092 sal_free(bad_list); 7093 return rv; 7094 } 7095 7096 if ((rv = soc_mem_read(unit, cfap_m, 7097 MEM_BLOCK_ANY, ptr, &e_good)) < 0) { 7098 sal_free(bad_list); 7099 return rv; 7100 } 7101 7102 if ((rv = soc_mem_write(unit, cfap_m, 7103 MEM_BLOCK_ANY, ptr, &e_bad)) < 0) { 7104 sal_free(bad_list); 7105 return rv; 7106 } 7107 7108 if ((rv = soc_mem_write(unit, cfap_m, 7109 MEM_BLOCK_ANY, i, &e_good)) < 0) { 7110 sal_free(bad_list); 7111 return rv; 7112 } 7113 } 7114 } 7115 7116 /* 7117 * Write CFAPPOOLSIZE with the number of good entries (minus 1). 7118 */ 7119 7120 if (bad_count > 0) { 7121 uint32 cfap_config = 0; 7122 uint32 val; 7123 uint32 cfap_thresh; 7124 7125 LOG_CLI((BSL_META_U(unit, 7126 "soc_mem_cfap_init: unit %d: " 7127 "detected and removed %d bad entries\n"), 7128 unit, bad_count)); 7129 7130 cfappoolsize -= bad_count; 7131 7132 soc_reg_field_set(unit, CFAPCONFIGr, &cfap_config, 7133 CFAPPOOLSIZEf, cfappoolsize); 7134 7135 if ((rv = WRITE_CFAPCONFIGr(unit, cfappoolsize)) < 0) { 7136 sal_free(bad_list); 7137 return rv; 7138 } 7139 7140 if ((rv = READ_CFAPFULLTHRESHOLDr(unit, &val)) < 0) { 7141 sal_free(bad_list); 7142 return rv; 7143 } 7144 cfap_thresh = soc_reg_field_get(unit, CFAPFULLTHRESHOLDr, 7145 val, CFAPFULLRESETPOINTf); 7146 cfap_thresh -= bad_count; 7147 7148 soc_reg_field_set(unit, CFAPFULLTHRESHOLDr, &val, 7149 CFAPFULLRESETPOINTf, cfap_thresh); 7150 7151 cfap_thresh = soc_reg_field_get(unit, CFAPFULLTHRESHOLDr, 7152 val, CFAPFULLSETPOINTf); 7153 cfap_thresh -= bad_count; 7154 soc_reg_field_set(unit, CFAPFULLTHRESHOLDr, &val, 7155 CFAPFULLSETPOINTf, cfap_thresh); 7156 if ((rv = WRITE_CFAPFULLTHRESHOLDr(unit, val)) < 0) { 7157 sal_free(bad_list); 7158 return rv; 7159 } 7160 } 7161 7162 done: 7163 7164 sal_free(bad_list); 7165 7166 return SOC_E_NONE; 7167 } 7168 7169 #endif /* BCM_ESW_SUPPORT */ 7170 7171 7172 /************************************************************************/ 7173 /* Routines for Filter Mask START/COUNT Maintenance */ 7174 /************************************************************************/ 7175 7176 #if defined(BCM_XGS_SUPPORT) || \ 7177 defined(BCM_SAND_SUPPORT) ||\ 7178 defined(PORTMOD_SUPPORT) 7179 7180 /************************************************************************ 7181 * Table DMA 7182 * 7183 * In hardware, it shares the same buffers and registers used for ARL DMA 7184 * In software, it shares with ARL DMA the same semaphore and interrupt 7185 * handler 7186 * Assumption 7187 * ARL DMA and Table DMA should not co-exist. The buffer should be 7188 * pre-allocated at least (index_max - index_min + 1) * sizeof (entry) 7189 */ 7190 7191 #define SOC_MEM_DMA_MAX_DATA_BEATS 4 7192 7193 /* 7194 * Function: 7195 * soc_mem_dmaable 7196 * Purpose: 7197 * Determine whether a table is DMA_able 7198 * Returns: 7199 * 0 if not, 1 otherwise 7200 */ 7201 int 7202 soc_mem_dmaable(int unit, soc_mem_t mem, int copyno) 7203 { 7204 if (SOC_CONTROL(unit)->tdma_enb == 0) { /* not enabled */ 7205 return FALSE; 7206 } 7207 7208 7209 #if defined(BCM_RCPU_SUPPORT) 7210 if(SOC_IS_RCPU_ONLY(unit)) { 7211 return FALSE; 7212 } 7213 #endif 7214 7215 #if defined(BCM_DFE_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 7216 if(SOC_IS_DFE(unit) || SOC_IS_DNXF(unit) || SOC_IS_DNX(unit)) { 7217 #ifndef PLISIM 7218 return TRUE; 7219 #else 7220 return FALSE; 7221 #endif /* PLISIM */ 7222 } 7223 #endif /* BCM_DFE_SUPPORT || BCM_DNXF_SUPPORT */ 7224 7225 #if defined(BCM_PETRA_SUPPORT) 7226 if(SOC_IS_ARAD(unit)) { 7227 #ifndef PLISIM 7228 if (SOC_IS_ARADPLUS_AND_BELOW(unit) && (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SCH)) { 7229 return FALSE; 7230 } 7231 7232 7233 return TRUE; 7234 #else 7235 return FALSE; 7236 #endif /* PLISIM */ 7237 } 7238 #endif /* BCM_PETRA_SUPPORT */ 7239 7240 assert(SOC_MEM_IS_VALID(unit, mem)); /* some devices test id DMA is enabled per memory */ 7241 7242 #ifdef BCM_TRIDENT2PLUS_SUPPORT 7243 if (soc_feature(unit, soc_feature_field_stage_quarter_slice) 7244 && soc_feature(unit, soc_feature_field_quarter_slice_single_tcam) 7245 && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) { 7246 /* Do not use dma for TCAMs with holes */ 7247 if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem) 7248 || (FP_GLOBAL_MASK_TCAMm == mem) || (FP_GLOBAL_MASK_TCAM_Xm == mem) 7249 || (FP_GLOBAL_MASK_TCAM_Ym == mem) || (FP_COUNTER_TABLEm == mem)) { 7250 return FALSE; 7251 } 7252 } 7253 #endif /* !BCM_TRIDENT2PLUS_SUPPORT */ 7254 7255 7256 #ifdef BCM_APACHE_SUPPORT 7257 if (soc_feature(unit, soc_feature_field_stage_half_slice) 7258 && soc_feature(unit, soc_feature_field_half_slice_single_tcam) 7259 && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) { 7260 /* Do not use dma for TCAMs with holes */ 7261 if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem) 7262 || (FP_GLOBAL_MASK_TCAMm == mem) || (FP_GLOBAL_MASK_TCAM_Xm == mem) 7263 || (FP_GLOBAL_MASK_TCAM_Ym == mem) || (FP_COUNTER_TABLEm == mem)) { 7264 return FALSE; 7265 } 7266 } 7267 #endif /* !BCM_APACHE_SUPPORT */ 7268 #ifdef BCM_TOMAHAWK2_SUPPORT 7269 if (soc_feature(unit, soc_feature_field_stage_half_slice) || 7270 soc_feature(unit, soc_feature_field_stage_quarter_slice)) { 7271 /* Do not use dma for TCAMs with holes */ 7272 if ((IFP_TCAMm == mem) || 7273 (IFP_TCAM_PIPE0m == mem) ||(IFP_TCAM_PIPE1m == mem) || 7274 (IFP_TCAM_PIPE2m == mem) || (IFP_TCAM_PIPE3m == mem) || 7275 (IFP_TCAM_WIDEm == mem) || 7276 (IFP_TCAM_WIDE_PIPE0m == mem) || (IFP_TCAM_WIDE_PIPE1m == mem) || 7277 (IFP_TCAM_WIDE_PIPE2m == mem) || (IFP_TCAM_WIDE_PIPE3m == mem)) { 7278 return FALSE; 7279 } 7280 } 7281 #endif /* BCM_TOMAHAWK2_SUPPORT */ 7282 /* Do not use DMA for TCAMs with holes */ 7283 if (soc_feature(unit, soc_feature_field_stage_egress_512_half_slice)) { 7284 if ((mem == EFP_TCAMm) || (mem == EFP_POLICY_TABLEm)) { 7285 return FALSE; 7286 } 7287 } 7288 if (soc_feature(unit, soc_feature_field_stage_lookup_512_half_slice)) { 7289 if ((mem == VFP_TCAMm) || (mem == VFP_POLICY_TABLEm)) { 7290 return FALSE; 7291 } 7292 } 7293 7294 #ifdef ALPM_ENABLE 7295 if (soc_feature(unit, soc_feature_alpm) && 7296 (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 7297 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 7298 mem == L3_DEFIP_ALPM_IPV6_128m)) { 7299 return FALSE; 7300 } 7301 #endif 7302 7303 #if defined(BCM_FIREBOLT_SUPPORT) 7304 #if defined(SOC_MEM_L3_DEFIP_WAR) || defined(BCM_TRIUMPH3_SUPPORT) || \ 7305 defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \ 7306 defined(BCM_KATANA_SUPPORT) 7307 if (soc_feature(unit, soc_feature_l3_defip_map) && 7308 (mem == L3_DEFIPm || 7309 mem == L3_DEFIP_LEVEL1m || 7310 mem == L3_DEFIP_ONLYm || 7311 mem == L3_DEFIP_DATA_ONLYm || 7312 mem == L3_DEFIP_HIT_ONLYm || 7313 mem == L3_DEFIP_HIT_ONLY_Xm || 7314 mem == L3_DEFIP_HIT_ONLY_Ym)) { 7315 return FALSE; /* Could be non-contiguous */ 7316 } 7317 #endif /* SOC_MEM_L3_DEFIP_WAR || BCM_TRIUMPH3_SUPPORT || 7318 * BCM_ENDURO_SUPPORT || BCM_KATANA2_SUPPORT*/ 7319 #endif /* BCM_FIREBOLT_SUPPORT */ 7320 7321 #ifdef BCM_TRIUMPH2_SUPPORT 7322 if (soc_feature(unit, soc_feature_l3_defip_hole) && 7323 (mem == L3_DEFIPm || 7324 mem == L3_DEFIP_ONLYm || 7325 mem == L3_DEFIP_DATA_ONLYm || 7326 mem == L3_DEFIP_HIT_ONLYm)) { 7327 return FALSE; 7328 } 7329 if ((mem == LMEPm) || (mem == LMEP_1m)) { 7330 return FALSE; 7331 } 7332 if (mem == EFP_TCAMm) { 7333 /* Do not use dma for tcams with holes */ 7334 if (soc_feature(unit, soc_feature_field_stage_half_slice)) { 7335 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_VALKYRIE2(unit)) { 7336 return FALSE; 7337 } 7338 } 7339 } 7340 7341 #endif /* BCM_TRIUMPH2_SUPPORT */ 7342 7343 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \ 7344 defined(BCM_KATANA_SUPPORT) 7345 if (soc_feature(unit, soc_feature_l3_defip_map) && 7346 (mem == L3_DEFIP_PAIR_128m || 7347 mem == L3_DEFIP_PAIR_LEVEL1m || 7348 mem == L3_DEFIP_PAIR_128_ONLYm || 7349 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 7350 mem == L3_DEFIP_PAIR_128_HIT_ONLYm || 7351 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 7352 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym)) { 7353 return FALSE; 7354 } 7355 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPPORT*/ 7356 #if defined(BCM_TRIUMPH3_SUPPORT) 7357 if (mem == PORT_EHG_RX_TUNNEL_DATAm || mem == PORT_EHG_RX_TUNNEL_MASKm || 7358 mem == PORT_EHG_TX_TUNNEL_DATAm) { 7359 return FALSE; 7360 } 7361 #endif /* BCM_TRIUMPH3_SUPPORT*/ 7362 7363 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 7364 if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm || mem == EFP_TCAMm) { 7365 /* Do not use dma for tcams with holes */ 7366 if (soc_feature(unit, soc_feature_field_stage_half_slice) || 7367 soc_feature(unit, soc_feature_field_slice_size128)) { 7368 return FALSE; 7369 } 7370 } 7371 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_HURRICANE2_SUPPORT*/ 7372 7373 #ifdef BCM_TRX_SUPPORT 7374 if (SOC_IS_TRX(unit) && !SOC_IS_TD2_TT2(unit) && !SAL_BOOT_BCMSIM) { 7375 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU) { 7376 switch (mem) { 7377 case CTR_FLEX_COUNT_0m: case CTR_FLEX_COUNT_1m: case CTR_FLEX_COUNT_2m: 7378 case CTR_FLEX_COUNT_3m: case CTR_FLEX_COUNT_4m: case CTR_FLEX_COUNT_5m: 7379 case CTR_FLEX_COUNT_6m: case CTR_FLEX_COUNT_7m: case CTR_FLEX_COUNT_8m: 7380 case CTR_FLEX_COUNT_9m: case CTR_FLEX_COUNT_10m: case CTR_FLEX_COUNT_11m: 7381 return TRUE; 7382 default: 7383 return FALSE; 7384 } 7385 } 7386 } 7387 #endif /* BCM_TRX_SUPPORT */ 7388 if (!soc_feature(unit, soc_feature_flexible_dma_steps) && 7389 soc_mem_index_count(unit, mem) > 1) { 7390 #ifdef BCM_TRIUMPH_SUPPORT 7391 /* For DNX chips - We can't reach here, and hence the coverity defect is not relevant for DNX chips */ 7392 /* coverity[index:FALSE] */ 7393 if (soc_feature(unit, soc_feature_esm_support) && 7394 SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) { 7395 int index0, index1; 7396 soc_mem_t real_mem; 7397 7398 /* On BCM56624_A0, don't do DMA for tables whose associated TCAM 7399 * entry is wider than a single raw TCAM entry */ 7400 soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0); 7401 soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1); 7402 if (index1 - index0 != 1) { 7403 return FALSE; 7404 } 7405 } 7406 #endif /* BCM_TRIUMPH_SUPPORT */ 7407 } 7408 7409 #ifdef BCM_TRIDENT_SUPPORT 7410 if (SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) { 7411 /* 7412 * EGR_VLAN requires to combine entries from both pipe 7413 * the single entry ISBS_PORT_TO_PIPE_MAPPING and 7414 * ESBS_PORT_TO_PIPE_MAPPING table need data_beat size adjustment 7415 */ 7416 if (mem == EGR_VLANm || 7417 mem == ISBS_PORT_TO_PIPE_MAPPINGm || 7418 mem == ESBS_PORT_TO_PIPE_MAPPINGm) { 7419 return FALSE; 7420 } 7421 } 7422 #endif /* BCM_TRIDENT_SUPPORT */ 7423 7424 #ifdef BCM_TRIUMPH3_SUPPORT 7425 if (SOC_IS_TRIUMPH3(unit)) { 7426 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_IBOD) { 7427 return FALSE; 7428 } 7429 7430 } 7431 if (soc_feature(unit, soc_feature_field_stage_quarter_slice)) { 7432 /* Do not use dma for tcams with holes */ 7433 if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm || 7434 mem == VFP_TCAMm || mem == EFP_TCAMm || mem == FP_COUNTER_TABLEm) { 7435 return FALSE; 7436 } 7437 } 7438 #endif /* BCM_TRIUMPH3_SUPPORT */ 7439 7440 #ifdef BCM_HURRICANE2_SUPPORT 7441 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 7442 SOC_IS_HURRICANE3(unit)) { 7443 if (mem == EFP_TCAMm) { 7444 /* Probable Non Contiguous.. Need to Investigate */ 7445 return FALSE; 7446 } 7447 } 7448 #endif /* BCM_HURRICANE2_SUPPORT */ 7449 7450 #ifdef BCM_SHADOW_SUPPORT 7451 if (SOC_IS_SHADOW(unit)) { 7452 /* 7453 * IL_STAT_MEM_x counters 7454 */ 7455 if (mem == IL_STAT_MEM_3m ) { 7456 return FALSE; 7457 } 7458 } 7459 #endif /* BCM_SHADOW_SUPPORT */ 7460 7461 7462 #ifdef BCM_XGS3_SWITCH_SUPPORT 7463 if (SOC_IS_XGS3_SWITCH(unit)) { 7464 return TRUE; 7465 } 7466 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7467 7468 return (soc_mem_entry_words(unit, mem) <= SOC_MEM_DMA_MAX_DATA_BEATS); 7469 } 7470 7471 /* 7472 * Function: 7473 * soc_mem_slamable 7474 * Purpose: 7475 * Determine whether a table is SLAMable 7476 * Returns: 7477 * 0 if not, 1 otherwise 7478 */ 7479 int 7480 soc_mem_slamable(int unit, soc_mem_t mem, int copyno) 7481 { 7482 if (SOC_CONTROL(unit)->tslam_enb == 0) { /* not enabled */ 7483 return FALSE; 7484 } 7485 7486 #if defined(BCM_RCPU_SUPPORT) 7487 if(SOC_IS_RCPU_ONLY(unit)) { 7488 return FALSE; 7489 } 7490 #endif 7491 7492 #if defined(BCM_DFE_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 7493 if(SOC_IS_DFE(unit) || SOC_IS_DNXF(unit) || SOC_IS_DNX(unit)) { 7494 #ifndef PLISIM 7495 return TRUE; 7496 #else 7497 return FALSE; 7498 #endif /* PLISIM */ 7499 } 7500 #endif /* BCM_DFE_SUPPORT || BCM_DNXF_SUPPORT */ 7501 7502 #if defined(BCM_PETRA_SUPPORT) 7503 if (SOC_IS_DPP(unit)) { 7504 #ifndef PLISIM 7505 return TRUE; 7506 #else 7507 return FALSE; 7508 #endif /* PLISIM */ 7509 } 7510 #endif /* BCM_PETRA_SUPPORT */ 7511 7512 assert(SOC_MEM_IS_VALID(unit, mem)); /* some devices test id DMA is enabled per memory */ 7513 7514 #if defined(BCM_FIREBOLT_SUPPORT) 7515 #if defined(SOC_MEM_L3_DEFIP_WAR) || defined(BCM_TRIUMPH3_SUPPORT) || \ 7516 defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT) 7517 if (soc_feature(unit, soc_feature_l3_defip_map) && 7518 (mem == L3_DEFIPm || 7519 mem == L3_DEFIP_LEVEL1m || 7520 mem == L3_DEFIP_ONLYm || 7521 mem == L3_DEFIP_DATA_ONLYm || 7522 mem == L3_DEFIP_HIT_ONLYm || 7523 mem == L3_DEFIP_HIT_ONLY_Xm || 7524 mem == L3_DEFIP_HIT_ONLY_Ym)) { 7525 return FALSE; /* Could be non-contiguous */ 7526 } 7527 #endif /* SOC_MEM_L3_DEFIP_WAR || BCM_TRIUMPH3_SUPPORT || BCM_ENDURO_SUPPORT */ 7528 #endif /* BCM_FIREBOLT_SUPPORT */ 7529 7530 #ifdef BCM_TRIUMPH2_SUPPORT 7531 if (soc_feature(unit, soc_feature_l3_defip_hole) && 7532 (mem == L3_DEFIPm || 7533 mem == L3_DEFIP_ONLYm || 7534 mem == L3_DEFIP_DATA_ONLYm || 7535 mem == L3_DEFIP_HIT_ONLYm)) { 7536 return FALSE; 7537 } 7538 if ((mem == LMEPm) || (mem == LMEP_1m)) { 7539 return FALSE; 7540 } 7541 #endif /* BCM_TRIUMPH2_SUPPORT */ 7542 7543 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \ 7544 defined(BCM_KATANA_SUPPORT) 7545 if (soc_feature(unit, soc_feature_l3_defip_map) && 7546 (mem == L3_DEFIP_PAIR_128m || 7547 mem == L3_DEFIP_PAIR_LEVEL1m || 7548 mem == L3_DEFIP_PAIR_128_ONLYm || 7549 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 7550 mem == L3_DEFIP_PAIR_128_HIT_ONLYm || 7551 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 7552 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym)) { 7553 return FALSE; 7554 } 7555 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPPORT*/ 7556 7557 #ifdef BCM_TRX_SUPPORT 7558 if (SOC_IS_TRX(unit) && !SOC_IS_TD2_TT2(unit)) { 7559 if (!SAL_BOOT_BCMSIM && SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU) { 7560 return FALSE; 7561 } 7562 } 7563 #endif /* BCM_TRX_SUPPORT */ 7564 7565 if (!soc_feature(unit, soc_feature_flexible_dma_steps) && 7566 soc_mem_index_count(unit, mem) > 1) { 7567 #ifdef BCM_TRIUMPH_SUPPORT 7568 if (soc_feature(unit, soc_feature_esm_support) && 7569 SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) { 7570 int index0, index1; 7571 soc_mem_t real_mem; 7572 7573 /* On BCM56624_A0, don't do DMA for tables whose associated TCAM 7574 * entry is wider than a single raw TCAM entry */ 7575 soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0); 7576 soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1); 7577 if (index1 - index0 != 1) { 7578 return FALSE; 7579 } 7580 } 7581 #endif /* BCM_TRIUMPH_SUPPORT */ 7582 } 7583 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 7584 if (SOC_CONTROL(unit)->l3_defip_index_remap && 7585 (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIPm || 7586 mem == L3_DEFIP_PAIR_LEVEL1m || mem == L3_DEFIP_LEVEL1m)) { 7587 return FALSE; 7588 } 7589 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPPORT*/ 7590 return TRUE; 7591 } 7592 7593 /* 7594 * Function: 7595 * _soc_xgs3_mem_dma 7596 * Purpose: 7597 * DMA acceleration for soc_mem_read_range() on FB/ER 7598 * Parameters: 7599 * buffer -- must be pointer to sufficiently large 7600 * DMA-able block of memory 7601 */ 7602 STATIC int 7603 _soc_xgs3_mem_dma(int unit, soc_mem_t mem, unsigned array_index, 7604 int copyno, int index_min, int index_max, 7605 uint32 ser_flags, void *buffer) 7606 { 7607 soc_control_t *soc = SOC_CONTROL(unit); 7608 uint32 start_addr; 7609 uint32 count; 7610 uint32 data_beats; 7611 uint32 spacing; 7612 int rv = SOC_E_NONE; 7613 uint32 cfg, rval; 7614 soc_mem_t cmd_mem = INVALIDm; 7615 uint8 at; 7616 #if (defined BCM_CMICM_SUPPORT) 7617 int cmc = SOC_PCI_CMC(unit); 7618 #endif 7619 7620 /* coverity[var_tested_neg] */ 7621 LOG_INFO(BSL_LS_SOC_DMA, 7622 (BSL_META_U(unit, 7623 "_soc_xgs3_mem_dma: unit %d" 7624 " mem %s.%s index %d-%d buffer %p\n"), 7625 unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno), 7626 index_min, index_max, buffer)); 7627 7628 data_beats = soc_mem_entry_words(unit, mem); 7629 7630 count = index_max - index_min + 1; 7631 if (count < 1) { 7632 return SOC_E_NONE; 7633 } 7634 7635 if (cmd_mem != INVALIDm) { 7636 MEM_LOCK(unit, cmd_mem); 7637 } 7638 7639 TABLE_DMA_LOCK(unit); 7640 7641 #if defined(BCM_TRIUMPH3_SUPPORT) 7642 if (soc_feature(unit, soc_feature_esm_correction) && 7643 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 7644 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 7645 SOC_ESM_LOCK(unit); 7646 } 7647 #endif 7648 7649 /* coverity[negative_returns : FALSE] */ 7650 start_addr = soc_mem_addr_get(unit, mem, array_index, 7651 copyno, index_min, &at); 7652 7653 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7654 if (0 != (ser_flags & _SOC_SER_FLAG_MULTI_PIPE)) { 7655 uint32 acc_type = ser_flags & _SOC_SER_FLAG_ACC_TYPE_MASK; 7656 if (0 != acc_type) { 7657 /* Override ACC_TYPE in address */ 7658 start_addr &= ~(_SOC_MEM_ADDR_ACC_TYPE_MASK << 7659 _SOC_MEM_ADDR_ACC_TYPE_SHIFT); 7660 start_addr |= (acc_type & _SOC_MEM_ADDR_ACC_TYPE_MASK) << 7661 _SOC_MEM_ADDR_ACC_TYPE_SHIFT; 7662 } 7663 } 7664 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7665 7666 #if (defined BCM_CMICM_SUPPORT) 7667 if(soc_feature(unit, soc_feature_cmicm)) { 7668 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_PCIMEM_START_ADDR_OFFSET(cmc), 7669 soc_cm_l2p(unit, buffer)); 7670 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_SBUS_START_ADDR_OFFSET(cmc), 7671 start_addr); 7672 rval = 0; 7673 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_ENTRY_COUNTr, &rval, 7674 COUNTf, count); 7675 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_ENTRY_COUNT_OFFSET(cmc), rval); 7676 } else 7677 #endif /* CMICM Support */ 7678 { 7679 7680 WRITE_CMIC_TABLE_DMA_PCIMEM_START_ADDRr(unit, 7681 soc_cm_l2p(unit, buffer)); 7682 WRITE_CMIC_TABLE_DMA_SBUS_START_ADDRr(unit, start_addr); 7683 rval = 0; 7684 soc_reg_field_set(unit, CMIC_TABLE_DMA_ENTRY_COUNTr, &rval, 7685 COUNTf, count); 7686 if (soc_feature(unit, soc_feature_flexible_dma_steps) && 7687 soc_mem_index_count(unit, mem) > 1) { 7688 #if defined(BCM_TRIUMPH_SUPPORT) 7689 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) { 7690 int index0, index1, increment; 7691 soc_mem_t real_mem; 7692 7693 soc_tcam_mem_index_to_raw_index(unit, mem, 0, 7694 &real_mem, &index0); 7695 soc_tcam_mem_index_to_raw_index(unit, mem, 1, 7696 &real_mem, &index1); 7697 increment = _shr_popcount(index1 - index0 - 1); 7698 soc_reg_field_set(unit, CMIC_TABLE_DMA_ENTRY_COUNTr, &rval, 7699 SBUS_ADDR_INCREMENT_STEPf, increment); 7700 } 7701 #endif /* BCM_TRIUMPH_SUPPORT */ 7702 #if defined(BCM_TRIUMPH3_SUPPORT) 7703 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU) { 7704 int index0, index1, increment; 7705 soc_mem_t real_mem; 7706 7707 soc_tcam_mem_index_to_raw_index(unit, mem, 0, 7708 &real_mem, &index0); 7709 soc_tcam_mem_index_to_raw_index(unit, mem, 1, 7710 &real_mem, &index1); 7711 increment = _shr_popcount(index1 - index0 - 1); 7712 soc_reg_field_set(unit, CMIC_TABLE_DMA_ENTRY_COUNTr, &rval, 7713 SBUS_ADDR_INCREMENT_STEPf, increment); 7714 } 7715 #endif /* BCM_TRIUMPH3_SUPPORT */ 7716 } 7717 WRITE_CMIC_TABLE_DMA_ENTRY_COUNTr(unit, rval); 7718 } 7719 LOG_INFO(BSL_LS_SOC_DMA, 7720 (BSL_META_U(unit, 7721 "_soc_xgs3_mem_dma: table dma of %d entries " 7722 "of %d beats from 0x%x\n"), 7723 count, data_beats, start_addr)); 7724 7725 soc_cm_sflush(unit, buffer, WORDS2BYTES(data_beats) * count); 7726 /* Set beats. Clear table DMA abort,done and error bit. Start DMA */ 7727 #if (defined BCM_CMICM_SUPPORT) 7728 if(soc_feature(unit, soc_feature_cmicm)) { 7729 /* For CMICm retain Endianess etc... */ 7730 cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc)); 7731 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, 7732 BEATSf, data_beats); 7733 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ABORTf, 0); 7734 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ENf, 0); 7735 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, 7736 ENABLE_MULTIPLE_SBUS_CMDSf, 0); 7737 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc), cfg); 7738 /* Clearing EN clears stats */ 7739 7740 7741 #ifdef BCM_EXTND_SBUS_SUPPORT 7742 if (soc_feature(unit, soc_feature_new_sbus_format)) { 7743 rval = 0; 7744 /* Use TR3 style sbus access */ 7745 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr, 7746 &rval, EN_TR3_SBUS_STYLEf, 1); 7747 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr, 7748 &rval, 7749 SBUS_BLOCKIDf, SOC_BLOCK2SCH(unit, copyno)); 7750 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr, 7751 &rval, 7752 SBUS_ACCTYPEf, 7753 SOC_MEM_ACC_TYPE(unit, mem)); 7754 WRITE_CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr(unit, rval); 7755 } 7756 #endif 7757 } else 7758 #endif 7759 { 7760 cfg = 0; 7761 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, 7762 BEATSf, data_beats); 7763 } 7764 if (soc_feature(unit, soc_feature_multi_sbus_cmds)) { 7765 7766 if (soc->sbusCmdSpacing < 0) { 7767 spacing = data_beats > 7 ? data_beats + 1 : 8; 7768 } else { 7769 spacing = soc->sbusCmdSpacing; 7770 } 7771 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 7772 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XQPORT) || 7773 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GXPORT) || 7774 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SPORT) || 7775 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GPORT) || 7776 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_QGPORT) || 7777 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_LLS) || 7778 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU)) { 7779 spacing = 0; 7780 } 7781 7782 #ifdef BCM_KATANA_SUPPORT 7783 if (SOC_IS_KATANA(unit)) { 7784 /* disable MOR for EFP_TCAM and EGR_VLAN_XLATE */ 7785 if (mem == EFP_TCAMm || mem == EGR_VLAN_XLATEm) { 7786 spacing = 0; 7787 } 7788 } 7789 #endif 7790 7791 if (spacing) { 7792 #if (defined BCM_CMICM_SUPPORT) 7793 if(soc_feature(unit, soc_feature_cmicm)) { 7794 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, 7795 MULTIPLE_SBUS_CMD_SPACINGf, spacing); 7796 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, 7797 ENABLE_MULTIPLE_SBUS_CMDSf, 1); 7798 7799 } else 7800 #endif 7801 { 7802 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, 7803 MULTIPLE_SBUS_CMD_SPACINGf, spacing); 7804 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, 7805 ENABLE_MULTIPLE_SBUS_CMDSf, 1); 7806 } 7807 } 7808 } 7809 #if (defined BCM_CMICM_SUPPORT) 7810 if(soc_feature(unit, soc_feature_cmicm)) { 7811 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ENf, 1); 7812 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc), cfg); 7813 } else 7814 #endif 7815 { 7816 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ENf, 1); 7817 WRITE_CMIC_TABLE_DMA_CFGr(unit, cfg); 7818 } 7819 rv = SOC_E_TIMEOUT; 7820 if (soc->tableDmaIntrEnb) { 7821 #if (defined BCM_CMICM_SUPPORT) 7822 if(soc_feature(unit, soc_feature_cmicm)) { 7823 soc_cmicm_intr0_enable(unit, IRQ_CMCx_TDMA_DONE); 7824 if (TABLE_DMA_INTR_WAIT(unit, soc->tableDmaTimeout) < 0) { 7825 rv = SOC_E_TIMEOUT; 7826 } 7827 soc_cmicm_intr0_disable(unit, IRQ_CMCx_TDMA_DONE); 7828 7829 cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_STAT_OFFSET(cmc)); 7830 if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr, 7831 cfg, DONEf)) { 7832 rv = SOC_E_NONE; 7833 if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr, 7834 cfg, ERRORf)) { 7835 rv = SOC_E_FAIL; 7836 } 7837 } 7838 } else 7839 #endif 7840 { 7841 soc_intr_enable(unit, IRQ_TDMA_DONE); 7842 if (TABLE_DMA_INTR_WAIT(unit, soc->tableDmaTimeout) < 0) { 7843 rv = SOC_E_TIMEOUT; 7844 } 7845 soc_intr_disable(unit, IRQ_TDMA_DONE); 7846 7847 READ_CMIC_TABLE_DMA_CFGr(unit, &cfg); 7848 if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr, 7849 cfg, DONEf)) { 7850 rv = SOC_E_NONE; 7851 if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr, 7852 cfg, ERRORf)) { 7853 rv = SOC_E_FAIL; 7854 } 7855 } 7856 } 7857 } else { 7858 soc_timeout_t to; 7859 7860 soc_timeout_init(&to, soc->tableDmaTimeout, 10000); 7861 7862 do { 7863 #if (defined BCM_CMICM_SUPPORT) 7864 if(soc_feature(unit, soc_feature_cmicm)) { 7865 cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_STAT_OFFSET(cmc)); 7866 if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr, 7867 cfg, DONEf)) { 7868 rv = SOC_E_NONE; 7869 if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr, 7870 cfg, ERRORf)) { 7871 rv = SOC_E_FAIL; 7872 } 7873 break; 7874 } 7875 } else 7876 #endif 7877 { 7878 READ_CMIC_TABLE_DMA_CFGr(unit, &cfg); 7879 if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr, 7880 cfg, DONEf)) { 7881 rv = SOC_E_NONE; 7882 if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr, 7883 cfg, ERRORf)) { 7884 rv = SOC_E_FAIL; 7885 } 7886 break; 7887 } 7888 } 7889 } while(!(soc_timeout_check(&to))); 7890 } 7891 7892 if (rv < 0) { 7893 if (rv != SOC_E_TIMEOUT) { 7894 LOG_ERROR(BSL_LS_SOC_SOCMEM, 7895 (BSL_META_U(unit, 7896 "%s.%s failed(NAK)\n"), 7897 SOC_MEM_UFNAME(unit, mem), 7898 SOC_BLOCK_NAME(unit, copyno))); 7899 #ifdef BCM_TRIUMPH2_SUPPORT 7900 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 7901 SOC_IS_VALKYRIE2(unit)) { 7902 /* SCHAN nack */ 7903 sal_dpc(soc_triumph2_mem_nack, INT_TO_PTR(unit), 7904 INT_TO_PTR(start_addr), 0, 0, 0); 7905 } 7906 #endif /* BCM_TRIUMPH2_SUPPORT */ 7907 } else { 7908 soc_timeout_t to; 7909 7910 LOG_ERROR(BSL_LS_SOC_SOCMEM, 7911 (BSL_META_U(unit, 7912 "TableDmaTimeOut: %s.%s %s timeout\n"), 7913 SOC_MEM_UFNAME(unit, mem), 7914 SOC_BLOCK_NAME(unit, copyno), 7915 soc->tableDmaIntrEnb ? "interrupt" : "polling")); 7916 7917 #if (defined BCM_CMICM_SUPPORT) 7918 if(soc_feature(unit, soc_feature_cmicm)) { 7919 /* Abort Table DMA */ 7920 cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc)); 7921 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ENf, 0); 7922 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ABORTf, 1); 7923 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc), cfg); 7924 7925 /* Check the done bit to confirm */ 7926 soc_timeout_init(&to, soc->tableDmaTimeout, 0); 7927 while (1) { 7928 cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_STAT_OFFSET(cmc)); 7929 if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr, cfg, DONEf)) { 7930 break; 7931 } 7932 if (soc_timeout_check(&to)) { 7933 LOG_ERROR(BSL_LS_SOC_SOCMEM, 7934 (BSL_META_U(unit, 7935 "TableDmaTimeOut:_soc_xgs3_mem_dma, Abort Failed\n"))); 7936 break; 7937 } 7938 } 7939 } else 7940 #endif 7941 { 7942 /* Abort Table DMA */ 7943 READ_CMIC_TABLE_DMA_CFGr(unit, &cfg); 7944 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ENf, 0); 7945 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ABORTf, 1); 7946 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, DONEf, 0); 7947 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ERRORf, 0); 7948 WRITE_CMIC_TABLE_DMA_CFGr(unit, cfg); 7949 7950 /* Check the done bit to confirm */ 7951 soc_timeout_init(&to, soc->tableDmaTimeout, 0); 7952 while (1) { 7953 READ_CMIC_TABLE_DMA_CFGr(unit, &cfg); 7954 if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr, cfg, DONEf)) { 7955 break; 7956 } 7957 if (soc_timeout_check(&to)) { 7958 LOG_ERROR(BSL_LS_SOC_SOCMEM, 7959 (BSL_META_U(unit, 7960 "TableDmaTimeOut:_soc_xgs3_mem_dma, Abort Failed\n"))); 7961 break; 7962 } 7963 } 7964 } 7965 } 7966 } 7967 7968 soc_cm_sinval(unit, (void *)buffer, WORDS2BYTES(data_beats) * count); 7969 7970 #if defined(BCM_TRIUMPH3_SUPPORT) 7971 if (soc_feature(unit, soc_feature_esm_correction) && 7972 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 7973 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 7974 SOC_ESM_UNLOCK(unit); 7975 } 7976 #endif 7977 7978 TABLE_DMA_UNLOCK(unit); 7979 7980 if (cmd_mem != INVALIDm) { 7981 MEM_UNLOCK(unit, cmd_mem); 7982 } 7983 7984 return rv; 7985 } 7986 7987 /* 7988 * Function: 7989 * _soc_xgs3_mem_slam 7990 * Purpose: 7991 * DMA acceleration for soc_mem_write_range() on FB/ER 7992 * Parameters: 7993 * buffer -- must be pointer to sufficiently large 7994 * DMA-able block of memory 7995 * index_begin <= index_end - Forward direction 7996 * index_begin > index_end - Reverse direction 7997 */ 7998 7999 STATIC int 8000 _soc_xgs3_mem_slam(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, int copyno, 8001 int index_begin, int index_end, void *buffer) 8002 { 8003 soc_control_t *soc = SOC_CONTROL(unit); 8004 uint32 start_addr; 8005 uint32 count; 8006 uint32 data_beats; 8007 uint32 spacing; 8008 int rv = SOC_E_NONE; 8009 uint32 cfg, rval; 8010 uint8 at; 8011 #if (defined BCM_CMICM_SUPPORT) 8012 int cmc = SOC_PCI_CMC(unit); 8013 #endif 8014 8015 LOG_INFO(BSL_LS_SOC_DMA, 8016 (BSL_META_U(unit, 8017 "_soc_xgs3_mem_slam: unit %d" 8018 " mem %s.%s index %d-%d buffer %p\n"), 8019 unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno), 8020 index_begin, index_end, buffer)); 8021 8022 data_beats = soc_mem_entry_words(unit, mem); 8023 8024 if (index_begin > index_end) { 8025 /* coverity[negative_returns : FALSE] */ 8026 start_addr = soc_mem_addr_get(unit, mem, array_index, copyno, index_end, &at); 8027 count = index_begin - index_end + 1; 8028 } else { 8029 /* coverity[negative_returns : FALSE] */ 8030 start_addr = soc_mem_addr_get(unit, mem, array_index, copyno, index_begin, &at); 8031 count = index_end - index_begin + 1; 8032 } 8033 8034 if (!flags || (flags & SOC_MEM_WRITE_SET_ONLY)) { 8035 8036 #if (defined BCM_CMICM_SUPPORT) 8037 if(soc_feature(unit, soc_feature_cmicm)) { 8038 /* For CMICm retain Endianess etc... */ 8039 cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc)); 8040 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ABORTf, 0); 8041 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ENf, 0); 8042 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, 8043 ENABLE_MULTIPLE_SBUS_CMDSf, 0); 8044 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg); /* Clearing EN clears the stats */ 8045 8046 /* Set beats. Clear tslam DMA abort,done and error bit. Start DMA */ 8047 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, BEATSf, data_beats); 8048 8049 #if defined(BCM958525) 8050 /* Modulo count for 128B payload size */ 8051 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, 8052 REV_MODULO_COUNTf, (count % (32 / data_beats))); 8053 #else 8054 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, 8055 REV_MODULO_COUNTf, (count % (64 / data_beats))); 8056 #endif 8057 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, 8058 ORDERf, (index_begin > index_end) ? 1:0); 8059 8060 #ifdef BCM_EXTND_SBUS_SUPPORT 8061 if (soc_feature(unit, soc_feature_new_sbus_format)) { 8062 rval = 0; 8063 /* Use TR3 style sbus access */ 8064 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr, &rval, 8065 EN_TR3_SBUS_STYLEf, 1); 8066 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr, &rval, 8067 SBUS_BLOCKIDf, SOC_BLOCK2SCH(unit, copyno)); 8068 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr, &rval, 8069 SBUS_ACCTYPEf, SOC_MEM_ACC_TYPE(unit, mem)); 8070 WRITE_CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr(unit, rval); 8071 } 8072 #endif 8073 } else 8074 #endif 8075 { 8076 /* Set beats. Clear tslam DMA abort,done and error bit. Start DMA */ 8077 cfg = 0; 8078 #if defined(BCM958525) 8079 /* Modulo count for 128B payload size */ 8080 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, REV_MODULO_COUNTf, 8081 (count % (32 / data_beats))); 8082 #else 8083 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, REV_MODULO_COUNTf, 8084 (count % (64 / data_beats))); 8085 #endif 8086 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, BEATSf, data_beats); 8087 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, 8088 ORDERf, (index_begin > index_end) ? 1:0); 8089 } 8090 if (soc_feature(unit, soc_feature_multi_sbus_cmds)) { 8091 8092 if (soc->sbusCmdSpacing < 0) { 8093 spacing = data_beats > 7 ? data_beats + 1 : 8; 8094 } else { 8095 spacing = soc->sbusCmdSpacing; 8096 } 8097 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 8098 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XQPORT) || 8099 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GXPORT) || 8100 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XLPORT) || 8101 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SPORT) || 8102 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GPORT) || 8103 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_QGPORT) || 8104 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_LLS) || 8105 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU)) { 8106 spacing = 0; 8107 } 8108 8109 #ifdef BCM_KATANA_SUPPORT 8110 if (SOC_IS_KATANA(unit)) { 8111 /* disable MOR for EFP_TCAM and EGR_VLAN_XLATE */ 8112 if (mem == EFP_TCAMm || mem == EGR_VLAN_XLATEm) { 8113 spacing = 0; 8114 } 8115 } 8116 #endif 8117 8118 if (spacing) { 8119 #if (defined BCM_CMICM_SUPPORT) 8120 if(soc_feature(unit, soc_feature_cmicm)) { 8121 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, 8122 MULTIPLE_SBUS_CMD_SPACINGf, spacing); 8123 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, 8124 ENABLE_MULTIPLE_SBUS_CMDSf, 1); 8125 } else 8126 #endif 8127 { 8128 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, 8129 MULTIPLE_SBUS_CMD_SPACINGf, spacing); 8130 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, 8131 ENABLE_MULTIPLE_SBUS_CMDSf, 1); 8132 } 8133 } 8134 } 8135 8136 LOG_INFO(BSL_LS_SOC_DMA, 8137 (BSL_META_U(unit, 8138 "_soc_xgs3_mem_slam: tslam dma of %d entries " 8139 "of %d beats from 0x%x to index %d-%d\n"), 8140 count, data_beats, start_addr, index_begin, index_end)); 8141 8142 TSLAM_DMA_LOCK(unit); 8143 #if defined(BCM_TRIUMPH3_SUPPORT) 8144 if (soc_feature(unit, soc_feature_esm_correction) && 8145 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 8146 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 8147 SOC_ESM_LOCK(unit); 8148 } 8149 #endif 8150 soc_cm_sflush(unit, buffer, WORDS2BYTES(data_beats) * count); 8151 #if (defined BCM_CMICM_SUPPORT) 8152 if(soc_feature(unit, soc_feature_cmicm)) { 8153 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_PCIMEM_START_ADDR_OFFSET(cmc), 8154 soc_cm_l2p(unit, buffer)); 8155 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_SBUS_START_ADDR_OFFSET(cmc), start_addr); 8156 rval = 0; 8157 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_ENTRY_COUNTr, &rval, COUNTf, count); 8158 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_ENTRY_COUNT_OFFSET(cmc), rval); 8159 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg); 8160 } else 8161 #endif 8162 { 8163 WRITE_CMIC_SLAM_DMA_PCIMEM_START_ADDRr(unit, soc_cm_l2p(unit, buffer)); 8164 WRITE_CMIC_SLAM_DMA_SBUS_START_ADDRr(unit, start_addr); 8165 rval = 0; 8166 soc_reg_field_set(unit, CMIC_SLAM_DMA_ENTRY_COUNTr, &rval, COUNTf, count); 8167 if (soc_feature(unit, soc_feature_flexible_dma_steps) && 8168 soc_mem_index_count(unit, mem) > 1) { 8169 #if defined(BCM_TRIUMPH_SUPPORT) 8170 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) { 8171 int index0, index1, increment; 8172 soc_mem_t real_mem; 8173 8174 soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0); 8175 soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1); 8176 increment = _shr_popcount(index1 - index0 - 1); 8177 soc_reg_field_set(unit, CMIC_SLAM_DMA_ENTRY_COUNTr, &rval, 8178 SBUS_ADDR_INCREMENT_STEPf, increment); 8179 } 8180 #endif /* BCM_TRIUMPH_SUPPORT */ 8181 #if defined(BCM_TRIUMPH3_SUPPORT) 8182 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU) { 8183 int index0, index1, increment; 8184 soc_mem_t real_mem; 8185 8186 soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0); 8187 soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1); 8188 increment = _shr_popcount(index1 - index0 - 1); 8189 soc_reg_field_set(unit, CMIC_SLAM_DMA_ENTRY_COUNTr, &rval, 8190 SBUS_ADDR_INCREMENT_STEPf, increment); 8191 } 8192 #endif /* BCM_TRIUMPH3_SUPPORT */ 8193 } 8194 WRITE_CMIC_SLAM_DMA_ENTRY_COUNTr(unit, rval); 8195 WRITE_CMIC_SLAM_DMA_CFGr(unit, cfg); 8196 } 8197 } 8198 8199 if (!flags || (flags & SOC_MEM_WRITE_COMMIT_ONLY)) { 8200 cfg = 0; 8201 /* write ENf bit to SLAM_DMA_CFG register */ 8202 #if (defined BCM_CMICM_SUPPORT) 8203 if(soc_feature(unit, soc_feature_cmicm)) { 8204 cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc)); 8205 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ENf, 1); 8206 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg); 8207 } else 8208 #endif 8209 { 8210 READ_CMIC_SLAM_DMA_CFGr(unit, &cfg); 8211 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ENf, 1); 8212 WRITE_CMIC_SLAM_DMA_CFGr(unit, cfg); 8213 } 8214 } 8215 8216 if (!flags || (flags & SOC_MEM_WRITE_STATUS_ONLY)) { 8217 8218 rv = SOC_E_TIMEOUT; 8219 if (soc->tslamDmaIntrEnb) { 8220 8221 #if (defined BCM_CMICM_SUPPORT) 8222 if(soc_feature(unit, soc_feature_cmicm)) { 8223 soc_cmicm_intr0_enable(unit, IRQ_CMCx_TSLAM_DONE); 8224 if (TSLAM_DMA_INTR_WAIT(unit, soc->tslamDmaTimeout) < 0) { 8225 rv = SOC_E_TIMEOUT; 8226 } 8227 soc_cmicm_intr0_disable(unit, IRQ_CMCx_TSLAM_DONE); 8228 8229 cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_STAT_OFFSET(cmc)); 8230 if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, DONEf)) { 8231 rv = SOC_E_NONE; 8232 } 8233 if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, ERRORf)) { 8234 rv = SOC_E_FAIL; 8235 } 8236 } else 8237 #endif 8238 { 8239 soc_intr_enable(unit, IRQ_TSLAM_DONE); 8240 if (TSLAM_DMA_INTR_WAIT(unit, soc->tslamDmaTimeout) < 0) { 8241 rv = SOC_E_TIMEOUT; 8242 } 8243 soc_intr_disable(unit, IRQ_TSLAM_DONE); 8244 8245 READ_CMIC_SLAM_DMA_CFGr(unit, &cfg); 8246 if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, DONEf)) { 8247 rv = SOC_E_NONE; 8248 } 8249 if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, ERRORf)) { 8250 rv = SOC_E_FAIL; 8251 } 8252 } 8253 } else { 8254 soc_timeout_t to; 8255 8256 soc_timeout_init(&to, soc->tslamDmaTimeout, 10000); 8257 8258 do { 8259 #if (defined BCM_CMICM_SUPPORT) 8260 if(soc_feature(unit, soc_feature_cmicm)) { 8261 cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_STAT_OFFSET(cmc)); 8262 if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, ERRORf)) { 8263 rv = SOC_E_FAIL; 8264 break; 8265 } 8266 if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, DONEf)) { 8267 rv = SOC_E_NONE; 8268 break; 8269 } 8270 } else 8271 #endif 8272 { 8273 READ_CMIC_SLAM_DMA_CFGr(unit, &cfg); 8274 if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, ERRORf)) { 8275 rv = SOC_E_FAIL; 8276 break; 8277 } 8278 if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, DONEf)) { 8279 rv = SOC_E_NONE; 8280 break; 8281 } 8282 } 8283 } while (!(soc_timeout_check(&to))); 8284 } 8285 8286 if (rv < 0) { 8287 if (rv != SOC_E_TIMEOUT) { 8288 LOG_ERROR(BSL_LS_SOC_SOCMEM, 8289 (BSL_META_U(unit, 8290 "%s.%s failed(NAK)\n"), 8291 SOC_MEM_UFNAME(unit, mem), 8292 SOC_BLOCK_NAME(unit, copyno))); 8293 #ifdef BCM_TRIUMPH2_SUPPORT 8294 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 8295 SOC_IS_VALKYRIE2(unit)) { 8296 /* SCHAN nack */ 8297 soc_triumph2_mem_nack(INT_TO_PTR(unit), 8298 INT_TO_PTR(start_addr), 0, 0, 0); 8299 } 8300 #endif /* BCM_TRIUMPH2_SUPPORT */ 8301 } else { 8302 soc_timeout_t to; 8303 8304 LOG_ERROR(BSL_LS_SOC_SOCMEM, 8305 (BSL_META_U(unit, 8306 "SlamDmaTimeOut:%s.%s %s timeout\n"), 8307 SOC_MEM_UFNAME(unit, mem), 8308 SOC_BLOCK_NAME(unit, copyno), 8309 soc->tslamDmaIntrEnb ? "interrupt" : "polling")); 8310 8311 #if (defined BCM_CMICM_SUPPORT) 8312 if(soc_feature(unit, soc_feature_cmicm)) { 8313 /* Abort Tslam DMA */ 8314 cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc)); 8315 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ENf, 0); 8316 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ABORTf, 1); 8317 soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg); 8318 8319 /* Check the done bit to confirm */ 8320 soc_timeout_init(&to, soc->tslamDmaTimeout, 10000); 8321 while (1) { 8322 cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_STAT_OFFSET(cmc)); 8323 if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, DONEf)) { 8324 break; 8325 } 8326 if (soc_timeout_check(&to)) { 8327 LOG_ERROR(BSL_LS_SOC_SOCMEM, 8328 (BSL_META_U(unit, 8329 "SlamDmaTimeOut:_soc_xgs3_mem_slam, Abort Failed\n"))); 8330 break; 8331 } 8332 } 8333 } else 8334 #endif 8335 { 8336 /* Abort Tslam DMA */ 8337 READ_CMIC_SLAM_DMA_CFGr(unit, &cfg); 8338 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ENf, 0); 8339 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ABORTf, 1); 8340 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, DONEf, 0); 8341 soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ERRORf, 0); 8342 WRITE_CMIC_SLAM_DMA_CFGr(unit, cfg); 8343 8344 /* Check the done bit to confirm */ 8345 soc_timeout_init(&to, soc->tslamDmaTimeout, 10000); 8346 while (1) { 8347 READ_CMIC_SLAM_DMA_CFGr(unit, &cfg); 8348 if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, DONEf)) { 8349 break; 8350 } 8351 if (soc_timeout_check(&to)) { 8352 LOG_ERROR(BSL_LS_SOC_SOCMEM, 8353 (BSL_META_U(unit, 8354 "SlamDmaTimeOut:_soc_xgs3_mem_slam, Abort Failed\n"))); 8355 break; 8356 } 8357 } 8358 } 8359 } 8360 } 8361 #if defined(BCM_TRIUMPH3_SUPPORT) 8362 if (soc_feature(unit, soc_feature_esm_correction) && 8363 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 8364 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 8365 SOC_ESM_UNLOCK(unit); 8366 } 8367 #endif 8368 TSLAM_DMA_UNLOCK(unit); 8369 } 8370 8371 return rv; 8372 } 8373 8374 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 8375 || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 8376 8377 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8378 STATIC void 8379 _soc_mem_tcam_shift(int unit, uint32 *f1, uint32 *ipbm) 8380 { 8381 uint32 ipbm_105bit; 8382 uint32 f1_49bit; 8383 uint32 carrybit; 8384 uint32 value; 8385 uint32 next_carry; 8386 int word; 8387 8388 f1_49bit = (f1[ 1 ] >> 17) & 0x1; 8389 ipbm_105bit = (ipbm[ 3 ] >> 9 ) & 0x1; 8390 /*clear ipbm 105th bit*/ 8391 ipbm[ 3 ] &= ((1 << 9) - 1); 8392 /*clear f1 49 bit*/ 8393 f1[ 1 ] &= ((1 << 17) - 1); 8394 /*update f1 49th bit*/ 8395 f1 [ 1 ] |= (ipbm_105bit << 17); 8396 8397 carrybit = f1_49bit; 8398 for ( word = 0; word < 4; word++ ) { 8399 value = ipbm[ word ]; 8400 next_carry = (value & (1<<31)) ? 1 : 0 ; 8401 ipbm[ word ] = (value << 1) | carrybit; 8402 carrybit = next_carry; 8403 } 8404 } 8405 8406 STATIC void 8407 _soc_mem_fp_global_mask_tcam_shift(int unit, soc_mem_t mem, uint32 *xy_entry, 8408 int index_min, int index_max) 8409 { 8410 int index, count; 8411 void *buf; 8412 uint32 f1[SOC_MAX_MEM_FIELD_WORDS], ipbm[SOC_MAX_MEM_FIELD_WORDS]; 8413 8414 if (soc_feature(unit, soc_feature_tcam_shift) && 8415 ((mem == FP_GLOBAL_MASK_TCAMm) || 8416 (mem == FP_GLOBAL_MASK_TCAM_Xm) || 8417 (mem == FP_GLOBAL_MASK_TCAM_Ym))) { 8418 count = 0; 8419 for (index = index_min; index <= index_max; index++, count++) { 8420 buf = soc_mem_table_idx_to_pointer(unit, mem, void *, 8421 xy_entry, count); 8422 sal_memset(f1, 0, sizeof(f1)); 8423 sal_memset(ipbm, 0, sizeof(ipbm)); 8424 8425 /*update key part*/ 8426 soc_mem_field_get(unit, mem, buf, F1f, f1); 8427 soc_mem_field_get(unit, mem, buf, IPBMf, ipbm); 8428 8429 _soc_mem_tcam_shift(unit, f1, ipbm); 8430 8431 soc_mem_field_set(unit, mem, buf, F1f, f1); 8432 soc_mem_field_set(unit, mem, buf, IPBMf, ipbm); 8433 8434 /*update mask part*/ 8435 soc_mem_field_get(unit, mem, buf, F1_MASKf, f1); 8436 soc_mem_field_get(unit, mem, buf, IPBM_MASKf, ipbm); 8437 8438 _soc_mem_tcam_shift(unit, f1, ipbm); 8439 8440 soc_mem_field_set(unit, mem, buf, F1_MASKf, f1); 8441 soc_mem_field_set(unit, mem, buf, IPBM_MASKf, ipbm); 8442 } 8443 } 8444 } 8445 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 8446 8447 void 8448 _soc_mem_tcam_xy_to_dm(int unit, soc_mem_t mem, int count, 8449 uint32 *xy_entry, uint32 *dm_entry) 8450 { 8451 uint32 key[SOC_MAX_MEM_FIELD_WORDS], mask[SOC_MAX_MEM_FIELD_WORDS]; 8452 uint32 converted_key, converted_mask; 8453 uint32 xor_value; 8454 soc_field_t key_field[4], mask_field[4]; 8455 int bit_length[4], word_length[4], field_count; 8456 int index, i, word, data_words, data_bytes; 8457 soc_pbmp_t pbmp; 8458 int xy_lpt; 8459 8460 xor_value = soc_feature(unit, soc_feature_xy_tcam_28nm) ? 0 : 0xffffffff; 8461 xy_lpt = soc_feature(unit, soc_feature_xy_tcam_lpt) && 8462 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_TCAM_ENCODING_LPT); 8463 8464 if (mem == L3_DEFIPm || mem == L3_DEFIP_Xm || mem == L3_DEFIP_Ym || 8465 mem == L3_DEFIP_ONLYm || mem == L3_DEFIP_LEVEL1m || 8466 mem == L3_DEFIP_TCAM_LEVEL1m 8467 ) { 8468 if (SOC_MEM_FIELD_VALID(unit, mem, KEY0f)) { 8469 key_field[0] = KEY0f; 8470 key_field[1] = KEY1f; 8471 mask_field[0] = MASK0f; 8472 mask_field[1] = MASK1f; 8473 field_count = 2; 8474 } else { 8475 key_field[0] = KEYf; 8476 mask_field[0] = MASKf; 8477 field_count = 1; 8478 } 8479 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) || \ 8480 defined(BCM_TRIDENT2_SUPPORT) 8481 } else if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_128_ONLYm || 8482 mem == L3_DEFIP_PAIR_LEVEL1m) { 8483 if (SOC_IS_TOMAHAWK3(unit)) { 8484 key_field[0] = UPR_KEY0f; 8485 key_field[1] = UPR_KEY1f; 8486 key_field[2] = LWR_KEY0f; 8487 key_field[3] = LWR_KEY1f; 8488 mask_field[0] = UPR_MASK0f; 8489 mask_field[1] = UPR_MASK1f; 8490 mask_field[2] = LWR_MASK0f; 8491 mask_field[3] = LWR_MASK1f; 8492 field_count = 4; 8493 } else { 8494 key_field[0] = KEY0_UPRf; 8495 key_field[1] = KEY1_UPRf; 8496 key_field[2] = KEY0_LWRf; 8497 key_field[3] = KEY1_LWRf; 8498 mask_field[0] = MASK0_UPRf; 8499 mask_field[1] = MASK1_UPRf; 8500 mask_field[2] = MASK0_LWRf; 8501 mask_field[3] = MASK1_LWRf; 8502 field_count = 4; 8503 } 8504 #endif 8505 } else { 8506 if (SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) { 8507 key_field[0] = FULL_KEYf; 8508 mask_field[0] = FULL_MASKf; 8509 } else { 8510 key_field[0] = KEYf; 8511 mask_field[0] = MASKf; 8512 } 8513 field_count = 1; 8514 #ifdef BCM_SABER2_SUPPORT 8515 if (SOC_IS_SABER2(unit) && (mem == FP_TCAMm) && 8516 soc_feature(unit, soc_feature_xy_tcam_28nm) && 8517 !SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) { 8518 8519 /* Key field doesn't include F4 and double wide mode fields */ 8520 if (SOC_MEM_FIELD_VALID(unit, mem, F4f)) { 8521 key_field[field_count] = F4f; 8522 mask_field[field_count] = F4_MASKf; 8523 field_count += 1; 8524 } 8525 8526 if (SOC_MEM_FIELD_VALID(unit, mem, DOUBLE_WIDE_MODEf)) { 8527 key_field[field_count] = DOUBLE_WIDE_MODEf; 8528 mask_field[field_count] = DOUBLE_WIDE_MODE_MASKf; 8529 field_count += 1; 8530 } 8531 } 8532 #endif 8533 } 8534 for (i = 0; i < field_count; i++) { 8535 bit_length[i] = soc_mem_field_length(unit, mem, key_field[i]); 8536 word_length[i] = (bit_length[i] + 31) / 32; 8537 } 8538 data_words = soc_mem_entry_words(unit, mem); 8539 data_bytes = data_words * sizeof(uint32); 8540 for (index = 0; index < count; index++) { 8541 if (dm_entry != xy_entry) { 8542 sal_memcpy(dm_entry, xy_entry, data_bytes); 8543 } 8544 for (i = 0; i < field_count; i++) { 8545 soc_mem_field_get(unit, mem, xy_entry, key_field[i], key); 8546 soc_mem_field_get(unit, mem, xy_entry, mask_field[i], mask); 8547 for (word = 0; word < word_length[i]; word++) { 8548 /* 8549 * LPT -> XY 8550 * xy_x[1:0] = {(lpt_y[0] & lpt_x[0]), (lpt_y[1] & lpt_y[0])} 8551 * xy_y[1:0] = {(lpt_y[1] & lpt_x[1]), (lpt_x[1] & lpt_x[0])} 8552 */ 8553 if (xy_lpt) { 8554 converted_key = (((key[word] & mask[word]) << 1) & 0xaaaaaaaa) | 8555 ((mask[word] & (mask[word] >> 1)) & 0x55555555); 8556 converted_mask = ((key[word] & mask[word]) & 0xaaaaaaaa) | 8557 ((key[word] & (key[word] >> 1)) & 0x55555555); 8558 key[word] = converted_key; 8559 mask[word] = converted_mask; 8560 } 8561 /* 8562 * 40nm: 8563 * Encode: K0 = MASK & KEY 8564 * K1 = ~MASK | KEY 8565 * Decode: KEY = K0 8566 * MASK = K0 | ~K1 8567 * (encode) (decode) 8568 * KEY MASK K0 K1 KEY MASK 8569 * -------- ------ -------- 8570 * 0 0 0 1 0 0 8571 * 1 0 0 1 0 0 =====> info loss 8572 * 0 1 0 0 0 1 8573 * 1 1 1 1 1 1 8574 * 28nm: 8575 * Encode: K0 = MASK & KEY 8576 * K1 = MASK & ~KEY 8577 * Decode: KEY = K0 8578 * MASK = K0 | K1 8579 * KEY MASK K0 K1 KEY MASK 8580 * -------- ------ -------- 8581 * 0 0 0 0 0 0 8582 * 1 0 0 0 0 0 =====> info loss 8583 * 0 1 0 1 0 1 8584 * 1 1 1 0 1 1 8585 * Notes: 8586 * - Mask value of 1 means to compare against key 8587 * - K0 is in KEY field of the entry 8588 * - K1 is in MASK field of the entry 8589 */ 8590 mask[word] = key[word] | (mask[word] ^ xor_value); 8591 } 8592 if ((bit_length[i] & 0x1f) != 0) { 8593 if (xy_lpt) { 8594 key[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1; 8595 } 8596 mask[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1; 8597 } 8598 if (xy_lpt) { 8599 soc_mem_field_set(unit, mem, dm_entry, key_field[i], key); 8600 } 8601 soc_mem_field_set(unit, mem, dm_entry, mask_field[i], mask); 8602 } 8603 8604 /* Filter out the bits that is not implemented in the hardware, 8605 * hardware returns X=0 Y=0 which is D=0 M=1 after above conversion 8606 * following code will force such bits to D=0 M=0 */ 8607 if (SOC_IS_TD_TT(unit) && 8608 (mem == FP_GLOBAL_MASK_TCAM_Xm || 8609 mem == FP_GLOBAL_MASK_TCAM_Ym)) { 8610 soc_mem_pbmp_field_get(unit, mem, dm_entry, IPBM_MASKf, &pbmp); 8611 if (mem == FP_GLOBAL_MASK_TCAM_Xm) { 8612 SOC_PBMP_AND(pbmp, PBMP_XPIPE(unit)); 8613 } else { 8614 SOC_PBMP_AND(pbmp, PBMP_YPIPE(unit)); 8615 } 8616 soc_mem_pbmp_field_set(unit, mem, dm_entry, IPBM_MASKf, &pbmp); 8617 } 8618 8619 xy_entry += data_words; 8620 dm_entry += data_words; 8621 } 8622 } 8623 8624 void 8625 _soc_mem_tcam_dm_to_xy(int unit, soc_mem_t mem, int count, 8626 uint32 *dm_entry, uint32 *xy_entry, 8627 uint32 *cache_entry) 8628 { 8629 uint32 key[SOC_MAX_MEM_FIELD_WORDS], mask[SOC_MAX_MEM_FIELD_WORDS]; 8630 uint32 xor_value; 8631 uint32 converted_key, converted_mask; 8632 soc_field_t key_field[4], mask_field[4]; 8633 int bit_length[4], word_length[4], field_count; 8634 int index, i, word, data_words, data_bytes; 8635 int no_trans = FALSE; 8636 int xy_lpt; 8637 8638 if (!soc_feature(unit, soc_feature_xy_tcam_direct)) { 8639 /* Only clear the "don't care" key bits */ 8640 no_trans = TRUE; 8641 } 8642 xor_value = soc_feature(unit, soc_feature_xy_tcam_28nm) ? 0xffffffff : 0; 8643 xy_lpt = soc_feature(unit, soc_feature_xy_tcam_lpt) && 8644 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_TCAM_ENCODING_LPT); 8645 8646 if (mem == L3_DEFIPm || mem == L3_DEFIP_Xm || mem == L3_DEFIP_Ym || 8647 mem == L3_DEFIP_ONLYm || mem == L3_DEFIP_LEVEL1m || 8648 mem == L3_DEFIP_TCAM_LEVEL1m 8649 ) { 8650 if (SOC_MEM_FIELD_VALID(unit, mem, KEY0f)) { 8651 key_field[0] = KEY0f; 8652 key_field[1] = KEY1f; 8653 mask_field[0] = MASK0f; 8654 mask_field[1] = MASK1f; 8655 field_count = 2; 8656 } else { 8657 key_field[0] = KEYf; 8658 mask_field[0] = MASKf; 8659 field_count = 1; 8660 } 8661 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) || \ 8662 defined(BCM_TRIDENT2_SUPPORT) 8663 } else if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_128_ONLYm || 8664 mem == L3_DEFIP_PAIR_LEVEL1m) { 8665 if (SOC_IS_TOMAHAWK3(unit)) { 8666 key_field[0] = UPR_KEY0f; 8667 key_field[1] = UPR_KEY1f; 8668 key_field[2] = LWR_KEY0f; 8669 key_field[3] = LWR_KEY1f; 8670 mask_field[0] = UPR_MASK0f; 8671 mask_field[1] = UPR_MASK1f; 8672 mask_field[2] = LWR_MASK0f; 8673 mask_field[3] = LWR_MASK1f; 8674 field_count = 4; 8675 } else { 8676 key_field[0] = KEY0_UPRf; 8677 key_field[1] = KEY1_UPRf; 8678 key_field[2] = KEY0_LWRf; 8679 key_field[3] = KEY1_LWRf; 8680 mask_field[0] = MASK0_UPRf; 8681 mask_field[1] = MASK1_UPRf; 8682 mask_field[2] = MASK0_LWRf; 8683 mask_field[3] = MASK1_LWRf; 8684 field_count = 4; 8685 } 8686 #endif 8687 } else { 8688 if (SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) { 8689 key_field[0] = FULL_KEYf; 8690 mask_field[0] = FULL_MASKf; 8691 } else { 8692 key_field[0] = KEYf; 8693 mask_field[0] = MASKf; 8694 } 8695 field_count = 1; 8696 #ifdef BCM_SABER2_SUPPORT 8697 if (SOC_IS_SABER2(unit) && (mem == FP_TCAMm) && 8698 soc_feature(unit, soc_feature_xy_tcam_28nm) && 8699 !SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) { 8700 8701 /* Key field doesn't include F4 and double wide mode fields */ 8702 if (SOC_MEM_FIELD_VALID(unit, mem, F4f)) { 8703 key_field[field_count] = F4f; 8704 mask_field[field_count] = F4_MASKf; 8705 field_count += 1; 8706 } 8707 8708 if (SOC_MEM_FIELD_VALID(unit, mem, DOUBLE_WIDE_MODEf)) { 8709 key_field[field_count] = DOUBLE_WIDE_MODEf; 8710 mask_field[field_count] = DOUBLE_WIDE_MODE_MASKf; 8711 field_count += 1; 8712 } 8713 } 8714 #endif 8715 } 8716 for (i = 0; i < field_count; i++) { 8717 bit_length[i] = soc_mem_field_length(unit, mem, key_field[i]); 8718 word_length[i] = (bit_length[i] + 31) / 32; 8719 } 8720 data_words = soc_mem_entry_words(unit, mem); 8721 data_bytes = data_words * sizeof(uint32); 8722 for (index = 0; index < count; index++) { 8723 if (xy_entry != dm_entry) { 8724 sal_memcpy(xy_entry, dm_entry, data_bytes); 8725 } 8726 if (cache_entry) { 8727 sal_memcpy(cache_entry, dm_entry, data_bytes); 8728 } 8729 for (i = 0; i < field_count; i++) { 8730 soc_mem_field_get(unit, mem, dm_entry, key_field[i], key); 8731 soc_mem_field_get(unit, mem, dm_entry, mask_field[i], mask); 8732 if (cache_entry) { 8733 for (word = 0; word < word_length[i]; word++) { 8734 key[word] &= mask[word]; 8735 } 8736 soc_mem_field_set(unit, mem, cache_entry, key_field[i], key); 8737 } 8738 for (word = 0; word < word_length[i]; word++) { 8739 /* 8740 * 40nm: 8741 * Encode: K0 = MASK & KEY 8742 * K1 = ~MASK | KEY 8743 * Decode: KEY = K0 8744 * MASK = K0 | ~K1 8745 * (encode) (decode) 8746 * KEY MASK K0 K1 KEY MASK 8747 * -------- ------ -------- 8748 * 0 0 0 1 0 0 8749 * 1 0 0 1 0 0 =====> info loss 8750 * 0 1 0 0 0 1 8751 * 1 1 1 1 1 1 8752 * 28nm: 8753 * Encode: K0 = MASK & KEY 8754 * K1 = MASK & ~KEY 8755 * Decode: KEY = K0 8756 * MASK = K0 | K1 8757 * KEY MASK K0 K1 KEY MASK 8758 * -------- ------ -------- 8759 * 0 0 0 0 0 0 8760 * 1 0 0 0 0 0 =====> info loss 8761 * 0 1 0 1 0 1 8762 * 1 1 1 0 1 1 8763 * Notes: 8764 * - Mask value of 1 means to compare against key 8765 * - K0 is in KEY field of the entry 8766 * - K1 is in MASK field of the entry 8767 */ 8768 converted_key = key[word] & mask[word]; 8769 if (!no_trans) { 8770 converted_mask = (key[word] | ~mask[word]) ^ xor_value; 8771 mask[word] = converted_mask; 8772 } 8773 key[word] = converted_key; 8774 /* 8775 * XY -> LPT 8776 * lpt_x[1:0] = {(xy_y[1] | xy_y[0]), (xy_x[1] | xy_y[0])} 8777 * lpt_y[1:0] = {(xy_y[1] | xy_x[0]), (xy_x[1] | xy_x[0])} 8778 */ 8779 if (xy_lpt) { 8780 converted_key = ((mask[word] | (mask[word] << 1)) & 0xaaaaaaaa) | 8781 ((mask[word] | (key[word] >> 1)) & 0x55555555); 8782 converted_mask = ((mask[word] | (key[word] << 1)) & 0xaaaaaaaa) | 8783 ((key[word] | (key[word] >> 1)) & 0x55555555); 8784 key[word] = converted_key; 8785 mask[word] = converted_mask; 8786 } 8787 } 8788 if ((bit_length[i] & 0x1f) != 0) { 8789 if (xy_lpt) { 8790 key[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1; 8791 } 8792 mask[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1; 8793 } 8794 soc_mem_field_set(unit, mem, xy_entry, key_field[i], key); 8795 soc_mem_field_set(unit, mem, xy_entry, mask_field[i], mask); 8796 } 8797 dm_entry += data_words; 8798 xy_entry += data_words; 8799 if (cache_entry) { 8800 cache_entry += data_words; 8801 } 8802 } 8803 } 8804 8805 STATIC void 8806 _soc_mem_read_defip_index_map(int unit, soc_mem_t mem, int index, int *index2); 8807 8808 STATIC int 8809 _soc_mem_defip_index_is_invalid(int unit, soc_mem_t mem, int index); 8810 8811 #define MAX_TCAM_PROTECT_RANGES 32 8812 STATIC int 8813 _soc_mem_tcam_entry_preserve(int unit, soc_mem_t mem, int copyno, int index, 8814 int count, void *entry, soc_mem_t *aggr_mem, 8815 void **buffer) 8816 { 8817 int rv = SOC_E_NONE; 8818 int blk, entry_words, data_words, data_bytes, alloc_size, word_idx, i; 8819 int num_tcam_protect_ranges; 8820 int *index_min = NULL, *index_max = NULL, *split_count = NULL; 8821 uint32 *read_buf = NULL, *entry_ptr; 8822 int field_count, field_idx, idx, is_l3_defip = 0, wide = 0; 8823 soc_field_t fields[4]; 8824 int incr; 8825 8826 switch (mem) { 8827 case FP_GLOBAL_MASK_TCAMm: 8828 case FP_GLOBAL_MASK_TCAM_Xm: 8829 case FP_GLOBAL_MASK_TCAM_Ym: 8830 case FP_GM_FIELDSm: 8831 case FP_TCAMm: 8832 case FP_UDF_TCAMm: 8833 case EFP_TCAMm: 8834 case VFP_TCAMm: 8835 #if defined BCM_TOMAHAWK_SUPPORT 8836 case IFP_TCAMm: 8837 case IFP_TCAM_PIPE0m: 8838 case IFP_TCAM_PIPE1m: 8839 case IFP_TCAM_PIPE2m: 8840 case IFP_TCAM_PIPE3m: 8841 case IFP_TCAM_WIDEm: 8842 case IFP_TCAM_WIDE_PIPE0m: 8843 case IFP_TCAM_WIDE_PIPE1m: 8844 case IFP_TCAM_WIDE_PIPE2m: 8845 case IFP_TCAM_WIDE_PIPE3m: 8846 case FP_UDF_TCAM_PIPE0m: 8847 case FP_UDF_TCAM_PIPE1m: 8848 case FP_UDF_TCAM_PIPE2m: 8849 case FP_UDF_TCAM_PIPE3m: 8850 case IFP_LOGICAL_TABLE_SELECTm: 8851 case IFP_LOGICAL_TABLE_SELECT_PIPE0m: 8852 case IFP_LOGICAL_TABLE_SELECT_PIPE1m: 8853 case IFP_LOGICAL_TABLE_SELECT_PIPE2m: 8854 case IFP_LOGICAL_TABLE_SELECT_PIPE3m: 8855 case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLYm: 8856 case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE0m: 8857 case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE1m: 8858 case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE2m: 8859 case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE3m: 8860 case EXACT_MATCH_LOGICAL_TABLE_SELECTm: 8861 case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE0m: 8862 case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE1m: 8863 case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE2m: 8864 case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE3m: 8865 case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLYm: 8866 case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE0m: 8867 case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE1m: 8868 case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE2m: 8869 case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE3m: 8870 #endif /* BCM_TOMAHAWK_SUPPORT */ 8871 return SOC_E_NONE; 8872 case CPU_COS_MAP_ONLYm: 8873 *aggr_mem = CPU_COS_MAPm; 8874 break; 8875 case L2_USER_ENTRY_ONLYm: 8876 *aggr_mem = L2_USER_ENTRYm; 8877 break; 8878 case L3_DEFIP_128_ONLYm: 8879 *aggr_mem = L3_DEFIP_128m; /* will miss hit bit from one pipe */ 8880 break; 8881 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 8882 case L3_DEFIP_PAIR_128_ONLYm: 8883 *aggr_mem = L3_DEFIP_PAIR_128m; /* will miss hit bit from one pipe */ 8884 break; 8885 #endif 8886 case L3_DEFIP_ONLYm: 8887 *aggr_mem = L3_DEFIPm; /* will miss hit bit from one pipe */ 8888 break; 8889 case MY_STATION_TCAM_ENTRY_ONLYm: 8890 *aggr_mem = MY_STATION_TCAMm; 8891 break; 8892 case VLAN_SUBNET_ONLYm: 8893 *aggr_mem = VLAN_SUBNETm; 8894 break; 8895 default: 8896 *aggr_mem = mem; 8897 break; 8898 } 8899 8900 if (*aggr_mem != mem && count > 1) { 8901 /* Can't support DMA multiple entries on tcam only table */ 8902 return SOC_E_NONE; 8903 } 8904 8905 if (copyno == COPYNO_ALL) { 8906 SOC_MEM_BLOCK_ITER(unit, *aggr_mem, blk) { 8907 copyno = blk; 8908 break; 8909 } 8910 } 8911 8912 /* Check if any valid entry will be overwritten */ 8913 if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) { 8914 fields[0] = VALIDf; 8915 field_count = 1; 8916 } else if (SOC_MEM_FIELD_VALID(unit, mem, VALID0f)) { 8917 fields[0] = VALID0f; 8918 fields[1] = VALID1f; 8919 field_count = 2; 8920 } else if (SOC_MEM_FIELD_VALID(unit, mem, VALID0_LWRf)) { 8921 fields[0] = VALID0_LWRf; 8922 fields[1] = VALID1_LWRf; 8923 fields[2] = VALID0_UPRf; 8924 fields[3] = VALID1_UPRf; 8925 field_count = 4; 8926 } else { 8927 field_count = 0; 8928 } 8929 8930 num_tcam_protect_ranges = (SOC_CONTROL(unit)->l3_defip_max_tcams); 8931 8932 alloc_size = MAX_TCAM_PROTECT_RANGES * sizeof(int); 8933 index_min = (int *)sal_alloc(alloc_size, "index_min buffer"); 8934 index_max = (int *)sal_alloc(alloc_size, "index_max buffer"); 8935 split_count = (int *)sal_alloc(alloc_size, "split_count buffer"); 8936 read_buf = (uint32 *)sal_alloc(SOC_MAX_MEM_WORDS * sizeof(uint32), 8937 "read buffer"); 8938 if (NULL == index_min || NULL == index_max || 8939 NULL == split_count || NULL == read_buf) { 8940 rv = SOC_E_MEMORY; 8941 goto cleanup; 8942 } 8943 8944 sal_memset(index_min, -1, alloc_size); 8945 sal_memset(index_max, -1, alloc_size); 8946 sal_memset(split_count, 0, alloc_size); 8947 data_words = soc_mem_entry_words(unit, *aggr_mem); 8948 data_bytes = data_words * sizeof(uint32); 8949 if (mem == L3_DEFIPm || mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_ONLYm) { 8950 is_l3_defip = 1; 8951 } 8952 8953 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 8954 if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_LEVEL1m || 8955 mem == L3_DEFIP_PAIR_128_ONLYm) { 8956 is_l3_defip = 1; 8957 wide = 1; 8958 } 8959 #endif 8960 incr = soc_mem_index_count(unit, mem) / (num_tcam_protect_ranges >> wide); 8961 for (i = 0; i < count; i++) { 8962 if (is_l3_defip) { 8963 idx = (index + i) / incr; 8964 } else { 8965 idx = 0; 8966 split_count[idx] = count; 8967 index_min[idx] = index; 8968 index_max[idx] = soc_mem_index_max(unit, *aggr_mem); 8969 break; 8970 } 8971 if (idx >= (num_tcam_protect_ranges >> wide)) { 8972 rv = SOC_E_INTERNAL; 8973 goto cleanup; 8974 } 8975 8976 split_count[idx]++; 8977 8978 if (index_min[idx] != -1) { 8979 continue; 8980 } 8981 8982 index_min[idx] = index + i; 8983 index_max[idx] = (idx + 1) * incr - 1; 8984 8985 _soc_mem_read_defip_index_map(unit, mem, index_min[idx], &index_min[idx]); 8986 _soc_mem_read_defip_index_map(unit, mem, index_max[idx], &index_max[idx]); 8987 } 8988 8989 entry_words = soc_mem_entry_words(unit, mem); 8990 entry_ptr = entry; 8991 for (idx = 0; idx < num_tcam_protect_ranges; idx++) { 8992 if (index_min[idx] == -1) { 8993 continue; 8994 } 8995 8996 alloc_size = (index_max[idx] - index_min[idx] + 1) * data_bytes; 8997 buffer[idx] = soc_cm_salloc(unit, alloc_size + data_bytes, "shift buffer"); 8998 if (buffer[idx] == NULL) { 8999 rv = SOC_E_MEMORY; 9000 goto cleanup; 9001 } 9002 9003 /* After split, l3_defip tcam tables are good to use dma */ 9004 #ifdef BCM_SBUSDMA_SUPPORT 9005 if (soc_feature(unit, soc_feature_sbusdma)) { 9006 rv = _soc_mem_sbusdma_read(unit, *aggr_mem, copyno, index_min[idx], 9007 index_max[idx], 0, buffer[idx]); 9008 } else 9009 #endif 9010 { 9011 rv = _soc_xgs3_mem_dma(unit, *aggr_mem, 0, copyno, index_min[idx], 9012 index_max[idx], 0, buffer[idx]); 9013 } 9014 if (SOC_FAILURE(rv)) { 9015 goto cleanup; 9016 } 9017 9018 /* Zero the last entry */ 9019 _soc_mem_tcam_dm_to_xy(unit, *aggr_mem, 1, 9020 soc_mem_entry_null(unit, *aggr_mem), 9021 &((uint32 *)buffer[idx]) 9022 [alloc_size / sizeof(uint32)], NULL); 9023 9024 for (i = 0; i < split_count[idx]; i++) { 9025 /* Get the original entry */ 9026 sal_memcpy(read_buf, ((uint32 *)buffer[idx]) + (data_words * i), 9027 WORDS2BYTES(entry_words)); 9028 9029 /* Bit-wise 'and' the original entry with new entry */ 9030 for (word_idx = 0; word_idx < entry_words; word_idx++) { 9031 read_buf[word_idx] &= entry_ptr[word_idx]; 9032 } 9033 /* Find if original and new entry are both valid */ 9034 for (field_idx = 0; field_idx < field_count; field_idx++) { 9035 if (soc_mem_field32_get(unit, *aggr_mem, read_buf, 9036 fields[field_idx])) { 9037 break; 9038 } 9039 } 9040 if (field_idx != field_count) { 9041 break; 9042 } 9043 entry_ptr += entry_words; 9044 } 9045 if (i == split_count[idx]) { 9046 /* don't need to preserve entry */ 9047 soc_cm_sfree(unit, buffer[idx]); 9048 buffer[idx] = NULL; 9049 continue; 9050 } 9051 9052 #ifdef BCM_SBUSDMA_SUPPORT 9053 if (soc_feature(unit, soc_feature_sbusdma)) { 9054 rv = _soc_mem_sbusdma_write(unit, *aggr_mem, copyno, index_max[idx] + 1, 9055 index_min[idx] + 1, buffer[idx], FALSE, -1); 9056 } else 9057 #endif 9058 { 9059 rv = _soc_xgs3_mem_slam(unit, 0, *aggr_mem, 0, copyno, index_max[idx] + 1, 9060 index_min[idx] + 1, buffer[idx]); 9061 } 9062 9063 if (SOC_FAILURE(rv)) { 9064 goto cleanup; 9065 } 9066 9067 } 9068 9069 rv = SOC_E_NONE; 9070 9071 cleanup: 9072 if (SOC_FAILURE(rv)) { 9073 for (idx = 0; idx < num_tcam_protect_ranges; idx++) { 9074 if (buffer[idx]) { 9075 soc_cm_sfree(unit, buffer[idx]); 9076 buffer[idx] = NULL; 9077 } 9078 } 9079 } 9080 if (index_min) { 9081 sal_free(index_min); 9082 index_min = NULL; 9083 } 9084 if (index_max) { 9085 sal_free(index_max); 9086 index_max = NULL; 9087 } 9088 if (split_count) { 9089 sal_free(split_count); 9090 split_count = NULL; 9091 } 9092 if (read_buf) { 9093 sal_free(read_buf); 9094 read_buf = NULL; 9095 } 9096 return rv; 9097 } 9098 9099 STATIC int 9100 _soc_mem_tcam_entry_restore(int unit, soc_mem_t mem, int copyno, int index, 9101 int count, void **buffer) 9102 { 9103 int rv, rv2 = SOC_E_NONE; 9104 int blk, data_words; 9105 uint32 *buf_ptr; 9106 int num_tcam_protect_ranges; 9107 int index_min[MAX_TCAM_PROTECT_RANGES], index_max[MAX_TCAM_PROTECT_RANGES]; 9108 int split_count[MAX_TCAM_PROTECT_RANGES]; 9109 int i, idx, is_l3_defip = 0, wide = 0, incr; 9110 9111 num_tcam_protect_ranges = (SOC_CONTROL(unit)->l3_defip_max_tcams); 9112 9113 for (idx = 0; idx < num_tcam_protect_ranges; idx++) { 9114 if (buffer[idx]) { 9115 break; 9116 } 9117 } 9118 if (idx == num_tcam_protect_ranges) { 9119 return SOC_E_NONE; 9120 } 9121 9122 if (copyno == COPYNO_ALL) { 9123 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 9124 copyno = blk; 9125 break; 9126 } 9127 } 9128 9129 data_words = soc_mem_entry_words(unit, mem); 9130 sal_memset(index_min, -1, sizeof(index_min)); 9131 sal_memset(index_max, -1, sizeof(index_max)); 9132 sal_memset(split_count, 0, sizeof(split_count)); 9133 9134 if (mem == L3_DEFIPm || mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_ONLYm) { 9135 is_l3_defip = 1; 9136 } 9137 9138 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) 9139 if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_LEVEL1m || 9140 mem == L3_DEFIP_PAIR_128_ONLYm) { 9141 is_l3_defip = 1; 9142 wide = 1; 9143 } 9144 #endif 9145 9146 incr = soc_mem_index_count(unit, mem) / (num_tcam_protect_ranges >> wide); 9147 for (i = 0; i < count; i++) { 9148 if (is_l3_defip) { 9149 idx = (index + i) / incr; 9150 } else { 9151 idx = 0; 9152 split_count[idx] = count; 9153 index_min[idx] = index; 9154 index_max[idx] = soc_mem_index_max(unit, mem); 9155 break; 9156 } 9157 if (idx >= (num_tcam_protect_ranges >> wide)) { 9158 return SOC_E_INTERNAL; 9159 } 9160 9161 split_count[idx]++; 9162 9163 if (index_min[idx] != -1) { 9164 continue; 9165 } 9166 9167 index_min[idx] = index + i; 9168 index_max[idx] = (idx + 1) * incr - 1; 9169 9170 _soc_mem_read_defip_index_map(unit, mem, index_min[idx], &index_min[idx]); 9171 _soc_mem_read_defip_index_map(unit, mem, index_max[idx], &index_max[idx]); 9172 } 9173 9174 for (idx = 0; idx < num_tcam_protect_ranges; idx++) { 9175 if (index_min[idx] == -1) { 9176 continue; 9177 } 9178 if (buffer[idx] == NULL) { 9179 continue; 9180 } 9181 buf_ptr = &((uint32 *)buffer[idx])[split_count[idx] * data_words]; 9182 9183 #ifdef BCM_SBUSDMA_SUPPORT 9184 if (soc_feature(unit, soc_feature_sbusdma)) { 9185 /* coverity[negative_returns] */ 9186 rv = _soc_mem_sbusdma_write(unit, mem, copyno, index_min[idx] + split_count[idx], 9187 index_max[idx] + 1, buf_ptr, FALSE, -1); 9188 } else 9189 #endif 9190 { 9191 /* coverity[negative_returns] */ 9192 rv = _soc_xgs3_mem_slam(unit, 0, mem, 0, copyno, index_min[idx] + split_count[idx], 9193 index_max[idx] + 1, buf_ptr); 9194 } 9195 LOG_INFO(BSL_LS_SOC_SOCMEM, 9196 (BSL_META_U(unit, 9197 "Restore mem:%d from min+count:%-5d+%-2d to max:%-5d\n"), 9198 mem,index_min[idx], split_count[idx], index_max[idx])); 9199 soc_cm_sfree(unit, buffer[idx]); 9200 if (rv < 0) { /* Don't stop if rv < 0, but record rv. */ 9201 rv2 = rv; 9202 } 9203 } 9204 9205 return rv2; 9206 } 9207 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 9208 9209 /* 9210 * Function: 9211 * _soc_mem_dma_read 9212 * Purpose: 9213 * DMA acceleration for soc_mem_read_range() 9214 * With multiple CMC/channel support 9215 * Parameters: 9216 * buffer -- must be pointer to sufficiently large 9217 * DMA-able block of memory 9218 */ 9219 STATIC int 9220 _soc_mem_dma_read(int unit, soc_mem_t mem, unsigned array_index, int copyno, 9221 int index_min, int index_max, uint32 ser_flags, 9222 void *buffer, int vchan) 9223 { 9224 /* Remove assertions from here, because they are checked in calling 9225 * functions or intentionally excepted for SER correction 9226 * and Warm Boot. 9227 */ 9228 9229 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE 9230 if (SOC_IS_JERICHO_2_ONLY(unit) && soc_sand_is_emulation_system(unit) && _soc_jr2_is_2nd_core(unit, mem, copyno)) { 9231 /* for JR2 emulator, read from the first instance if the instance does not exist in emulation */ 9232 copyno = SOC_MEM_BLOCK_MIN(unit, mem); 9233 } 9234 #endif 9235 9236 #ifdef BCM_SBUSDMA_SUPPORT 9237 if (soc_feature(unit, soc_feature_sbusdma)) { 9238 SOC_IF_ERROR_RETURN 9239 (_soc_mem_array_sbusdma_read(unit, mem, array_index, 9240 copyno, index_min, index_max, 9241 ser_flags, buffer, vchan)); 9242 } else 9243 #endif 9244 { 9245 SOC_IF_ERROR_RETURN 9246 (_soc_xgs3_mem_dma(unit, mem, array_index, copyno, index_min, 9247 index_max, ser_flags, buffer)); 9248 } 9249 9250 if (0 != (ser_flags & _SOC_SER_FLAG_XY_READ)) { 9251 /* SER memscan logic must have the raw entries */ 9252 return SOC_E_NONE; 9253 } 9254 9255 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 9256 || defined(BCM_HURRICANE2_SUPPORT) 9257 if (soc_feature(unit, soc_feature_xy_tcam_direct) && 9258 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 9259 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 9260 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9261 _soc_mem_fp_global_mask_tcam_shift(unit, mem, buffer, index_min, index_max); 9262 #endif 9263 _soc_mem_tcam_xy_to_dm(unit, mem, index_max - index_min + 1, 9264 buffer, buffer); 9265 } 9266 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 9267 9268 return SOC_E_NONE; 9269 } 9270 9271 /* 9272 * Function: 9273 * _soc_mem_dma_write 9274 * Purpose: 9275 * DMA acceleration for soc_mem_write_range() 9276 * Parameters: 9277 * buffer -- must be pointer to sufficiently large 9278 * DMA-able block of memory 9279 * index_begin <= index_end - Forward direction 9280 * index_begin > index_end - Reverse direction 9281 */ 9282 STATIC int 9283 _soc_mem_dma_write(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, int copyno, 9284 int index_begin, int index_end, void *buffer, void *cache_buffer, 9285 int vchan) 9286 { 9287 int rv; 9288 void *buffer_ptr; 9289 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 9290 || defined(BCM_HURRICANE2_SUPPORT) 9291 int count, alloc_size; 9292 soc_mem_t aggr_mem = INVALIDm; 9293 void *shift_buffer[MAX_TCAM_PROTECT_RANGES] = {NULL}; 9294 #endif 9295 9296 if (SOC_HW_ACCESS_DISABLE(unit)) { 9297 return SOC_E_NONE; 9298 } 9299 9300 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 9301 9302 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE 9303 if (SOC_IS_JERICHO_2_ONLY(unit) && soc_sand_is_emulation_system(unit) && _soc_jr2_is_2nd_core(unit, mem, copyno)) { 9304 LOG_WARN(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, "_soc_mem_dma_write: mem instance %s.%s not in emulation, ignoring write\n"), 9305 SOC_MEM_NAME(unit,mem), SOC_BLOCK_NAME(unit, copyno))); 9306 return SOC_E_NONE; 9307 } 9308 #endif 9309 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 9310 9311 #ifndef BCM_WARM_BOOT_SUPPORT 9312 assert(soc_mem_index_valid(unit, mem, index_begin)); 9313 assert(soc_mem_index_valid(unit, mem, index_end)); 9314 #endif 9315 9316 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 9317 || defined(BCM_HURRICANE2_SUPPORT) 9318 if (soc_feature(unit, soc_feature_xy_tcam) && 9319 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 9320 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 9321 if (index_begin > index_end) { 9322 count = index_begin - index_end + 1; 9323 } else { 9324 count = index_end - index_begin + 1; 9325 } 9326 alloc_size = count * soc_mem_entry_words(unit, mem) * sizeof(uint32); 9327 buffer_ptr = soc_cm_salloc(unit, alloc_size, "converted buffer"); 9328 if (buffer_ptr == NULL) { 9329 return SOC_E_MEMORY; 9330 } 9331 _soc_mem_tcam_dm_to_xy(unit, mem, count, buffer, buffer_ptr, 9332 cache_buffer); 9333 9334 if (index_begin <= index_end && 9335 SOC_CONTROL(unit)->tcam_protect_write) { 9336 rv = _soc_mem_tcam_entry_preserve(unit, mem, copyno, index_begin, 9337 count, buffer_ptr, &aggr_mem, 9338 shift_buffer); 9339 if (SOC_FAILURE(rv)) { 9340 soc_cm_sfree(unit, buffer_ptr); 9341 return rv; 9342 } 9343 } 9344 } else 9345 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 9346 { 9347 buffer_ptr = buffer; 9348 } 9349 9350 #ifdef BCM_SBUSDMA_SUPPORT 9351 if (soc_feature(unit, soc_feature_sbusdma)) { 9352 rv = _soc_mem_array_sbusdma_write(unit, flags, mem, array_index, 9353 array_index, copyno, index_begin, 9354 index_end, buffer_ptr, FALSE, -1, 9355 vchan); 9356 } else 9357 #endif 9358 { 9359 rv = _soc_xgs3_mem_slam(unit, flags, mem, array_index, copyno, index_begin, 9360 index_end, buffer_ptr); 9361 } 9362 9363 if (SOC_E_FAIL == rv && 9364 soc_feature(unit, soc_feature_efp_meter_table_write_ignore_nack)) { 9365 if ((mem == EFP_METER_TABLEm || 9366 mem == EFP_METER_TABLE_PIPE0m || 9367 mem == EFP_METER_TABLE_PIPE1m || 9368 mem == EFP_METER_TABLE_PIPE2m || 9369 mem == EFP_METER_TABLE_PIPE3m || 9370 mem == EFP_METER_TABLE_Xm || 9371 mem == EFP_METER_TABLE_Ym)) { 9372 /* 9373 * Ignore the unexpected NACK during writing to EFP_METER_TABLExxx 9374 * since the error is not in the writen indexes and the write op can go through 9375 * successfully. 9376 */ 9377 rv = SOC_E_NONE; 9378 } 9379 } 9380 9381 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 9382 || defined(BCM_HURRICANE2_SUPPORT) 9383 if (soc_feature(unit, soc_feature_xy_tcam) && 9384 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 9385 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 9386 #ifdef INCLUDE_MEM_SCAN 9387 if (NULL != cache_buffer) { 9388 /* Update memscan TCAM cache if necessary */ 9389 soc_mem_scan_tcam_cache_update(unit, mem, 9390 index_begin, index_end, 9391 buffer_ptr); 9392 } 9393 #endif /* INCLUDE_MEM_SCAN */ 9394 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 9395 #ifdef BCM_WARM_BOOT_SUPPORT 9396 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) || 9397 SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) { 9398 int blk; 9399 9400 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 9401 if (copyno != COPYNO_ALL && copyno != blk) { 9402 continue; 9403 } 9404 soc_mem_overlay_tcam_update(unit, mem, blk, 9405 index_begin, index_end); 9406 } 9407 } 9408 #endif 9409 #endif 9410 soc_cm_sfree(unit, buffer_ptr); 9411 if (index_begin <= index_end && 9412 SOC_CONTROL(unit)->tcam_protect_write) { 9413 SOC_IF_ERROR_RETURN 9414 (_soc_mem_tcam_entry_restore(unit, aggr_mem, copyno, 9415 index_begin, 9416 index_end - index_begin + 1, 9417 shift_buffer)); 9418 } 9419 } 9420 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 9421 9422 return rv; 9423 } 9424 9425 9426 9427 9428 #if defined(BCM_FIREBOLT_SUPPORT) 9429 /* 9430 * Function: 9431 * _soc_xgs3_mem_clear_slam 9432 * Purpose: 9433 * soc_mem_clear acceleration using table DMA write (slam) 9434 */ 9435 STATIC int 9436 _soc_xgs3_mem_clear_slam(int unit, soc_mem_t mem, 9437 int copyno, void *null_entry) 9438 { 9439 int rv, chunk_size, chunk_entries, mem_size, entry_words; 9440 int index, index_end, index_min, index_max; 9441 uint32 *buf; 9442 9443 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) { 9444 return SOC_E_NONE; 9445 } 9446 #ifdef BCM_SBUSDMA_SUPPORT 9447 if (soc_feature(unit, soc_feature_sbusdma)) { 9448 uint32 *null_ptr; 9449 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 9450 || defined(BCM_HURRICANE2_SUPPORT) 9451 uint32 null_buf[SOC_MAX_MEM_WORDS]; 9452 if (soc_feature(unit, soc_feature_xy_tcam) && 9453 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 9454 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 9455 null_ptr = null_buf; 9456 _soc_mem_tcam_dm_to_xy(unit, mem, 1, null_entry, null_ptr, NULL); 9457 } else 9458 #endif /* defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) */ 9459 { 9460 null_ptr = null_entry; 9461 } 9462 return _soc_mem_sbusdma_clear(unit, mem, copyno, null_ptr); 9463 } 9464 #endif 9465 chunk_size = SOC_MEM_CLEAR_CHUNK_SIZE_GET(unit); 9466 index_min = soc_mem_index_min(unit, mem); 9467 index_max = soc_mem_index_max(unit, mem); 9468 entry_words = soc_mem_entry_words(unit, mem); 9469 mem_size = (index_max - index_min + 1) * entry_words * 4; 9470 if (mem_size < chunk_size) { 9471 chunk_size = mem_size; 9472 } 9473 9474 buf = soc_cm_salloc(unit, chunk_size, "mem_clear_buf"); 9475 if (buf == NULL) { 9476 return SOC_E_MEMORY; 9477 } 9478 9479 chunk_entries = chunk_size / (entry_words * 4); 9480 9481 if (null_entry == _soc_mem_entry_null_zeroes) { 9482 sal_memset(buf, 0, chunk_size); 9483 } else { 9484 for (index = 0; index < chunk_entries; index++) { 9485 sal_memcpy(buf + (index * entry_words), 9486 null_entry, entry_words * 4); 9487 } 9488 } 9489 9490 rv = SOC_E_NONE; 9491 for (index = index_min; index <= index_max; index += chunk_entries) { 9492 index_end = index + chunk_entries - 1; 9493 if (index_end > index_max) { 9494 index_end = index_max; 9495 } 9496 9497 rv = soc_mem_write_range(unit, mem, copyno, index, index_end, buf); 9498 if (rv < 0) { 9499 LOG_ERROR(BSL_LS_SOC_SOCMEM, 9500 (BSL_META_U(unit, 9501 "soc_mem_write_range: " 9502 "write %s.%s[%d-%d] failed: %s\n"), 9503 SOC_MEM_UFNAME(unit, mem), 9504 SOC_BLOCK_NAME(unit, copyno), 9505 index, index_end, soc_errmsg(rv))); 9506 break; 9507 } 9508 } 9509 9510 soc_cm_sfree(unit, buf); 9511 return rv; 9512 } 9513 9514 /* 9515 * Function: 9516 * _soc_xgs3_mem_clear_pipe 9517 * Purpose: 9518 * soc_mem_clear acceleration using pipeline table clear logic. 9519 * Much faster than table slam. Exists on XGS3. 9520 */ 9521 STATIC int 9522 _soc_xgs3_mem_clear_pipe(int unit, soc_mem_t mem, int blk, void *null_entry) 9523 { 9524 int rv, mementries, to_usec, to_rv; 9525 uint32 hwreset1, hwreset2, membase, memoffset, memstage; 9526 soc_timeout_t to; 9527 #ifdef BCM_EXTND_SBUS_SUPPORT 9528 uint32 memnum; 9529 #endif /* BCM_EXTND_SBUS_SUPPORT */ 9530 9531 #ifdef BCM_XGS_SUPPORT 9532 if (SOC_IS_XGS(unit)) { 9533 if (!SOC_MEM_CLEAR_HW_ACC(unit)) { 9534 return SOC_E_UNAVAIL; 9535 } 9536 } 9537 #endif /* BCM_XGS_SUPPORT */ 9538 if (null_entry != _soc_mem_entry_null_zeroes) { 9539 return SOC_E_UNAVAIL; 9540 } 9541 9542 /* Tomahawk cannot clear the vlan table with pipe for some reasons 9543 * Use DMA clear for now 9544 */ 9545 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 9546 switch (mem) { 9547 case VLAN_TABm: 9548 case VLAN_XLATEm: 9549 case EGR_VLAN_XLATEm: 9550 #ifdef BCM_TRIDENT3_SUPPORT 9551 case VLAN_XLATE_1_SINGLEm: 9552 case VLAN_XLATE_2_SINGLEm: 9553 case VLAN_XLATE_1_DOUBLEm: 9554 case VLAN_XLATE_2_DOUBLEm: 9555 case EGR_VLAN_XLATE_1_SINGLEm: 9556 case EGR_VLAN_XLATE_2_SINGLEm: 9557 case EGR_VLAN_XLATE_1_DOUBLEm: 9558 case EGR_VLAN_XLATE_2_DOUBLEm: 9559 #endif 9560 return SOC_E_UNAVAIL; 9561 } 9562 } 9563 9564 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) || SOC_HW_ACCESS_DISABLE(unit)) { 9565 return SOC_E_NONE; 9566 } 9567 if (SAL_BOOT_PLISIM) { 9568 if (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) { 9569 if (!(SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit))) { 9570 /* h/w acceleration is not implemented in some models */ 9571 return SOC_E_UNAVAIL; 9572 } 9573 } else { 9574 return SOC_E_UNAVAIL; 9575 } 9576 } 9577 9578 if (!SOC_REG_IS_VALID(unit, ING_HW_RESET_CONTROL_1r)) { 9579 return SOC_E_UNAVAIL; 9580 } 9581 9582 9583 #ifdef BCM_TRIUMPH_SUPPORT 9584 if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) { 9585 switch (mem) { 9586 case ING_PW_TERM_COUNTERSm: 9587 case EGR_IPFIX_SESSION_TABLEm: 9588 case EGR_IPFIX_EXPORT_FIFOm: 9589 return SOC_E_UNAVAIL; 9590 default: 9591 break; 9592 } 9593 } 9594 #if defined(BCM_TRIUMPH2_SUPPORT) 9595 else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 9596 SOC_IS_VALKYRIE2(unit)) { 9597 if (mem == LMEPm) { 9598 return SOC_E_UNAVAIL; 9599 } 9600 if (soc_feature(unit, soc_feature_ser_parity)) { 9601 SOC_IF_ERROR_RETURN 9602 (soc_triumph2_ser_mem_clear(unit, mem)); 9603 } 9604 } 9605 #endif /* BCM_TRIUMPH2_SUPPORT */ 9606 #if defined(BCM_ENDURO_SUPPORT) 9607 else if (SOC_IS_ENDURO(unit)) { 9608 if (mem == LMEPm || mem == LMEP_1m) { 9609 return SOC_E_UNAVAIL; 9610 } 9611 } 9612 #endif /* BCM_ENDURO_SUPPORT */ 9613 #if defined(BCM_TRIDENT_SUPPORT) 9614 else if (SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) { 9615 if ((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) || 9616 (SOC_MEM_INFO(unit, mem).index_max == 0)) { 9617 return SOC_E_UNAVAIL; 9618 } 9619 switch (mem) { 9620 case EGR_VLANm: 9621 return SOC_E_UNAVAIL; 9622 default: 9623 break; 9624 } 9625 } 9626 #endif /* BCM_TRIDENT_SUPPORT */ 9627 #ifdef BCM_TRIUMPH3_SUPPORT 9628 else if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 9629 if ((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) || 9630 (SOC_MEM_INFO(unit, mem).index_max == 0)) { 9631 return SOC_E_UNAVAIL; 9632 } 9633 if (SOC_IS_TRIUMPH3(unit)) { 9634 if (mem == EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm || 9635 mem == ING_DVP_2_TABLEm) { 9636 return SOC_E_UNAVAIL; 9637 } 9638 } 9639 } 9640 #endif /* BCM_TRIUMPH3_SUPPORT */ 9641 #ifdef BCM_KATANA2_SUPPORT 9642 else if (SOC_IS_KATANA2(unit)) { 9643 switch(mem) { 9644 /* WORK-AROUND:SDK-48233 9645 KT2 SW WAR: IP HW Mem Reset does not reset 9646 IARB_ING_PHYSICAL_PORT table */ 9647 case IARB_ING_PHYSICAL_PORTm: 9648 return SOC_E_UNAVAIL; 9649 default: 9650 break; 9651 } 9652 if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) { 9653 return SOC_E_UNAVAIL; 9654 } 9655 } 9656 #endif /* BCM_KATANA2_SUPPORT */ 9657 #ifdef BCM_KATANA_SUPPORT 9658 else if (SOC_IS_KATANA(unit)) { 9659 if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) { 9660 return SOC_E_UNAVAIL; 9661 } 9662 } 9663 #endif 9664 #ifdef BCM_HURRICANE2_SUPPORT 9665 else if (SOC_IS_HURRICANE2(unit)) { 9666 switch(mem) { 9667 case VLAN_SUBNETm: 9668 case VLAN_SUBNET_ONLYm: 9669 return SOC_E_UNAVAIL; 9670 default: 9671 break; 9672 } 9673 9674 if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) { 9675 SOC_IF_ERROR_RETURN 9676 (soc_hurricane2_ser_mem_clear(unit, mem)); 9677 } 9678 } 9679 #endif /* BCM_HURRICANE2_SUPPORT */ 9680 9681 #ifdef BCM_GREYHOUND_SUPPORT 9682 else if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 9683 SOC_IS_GREYHOUND2(unit)) { 9684 if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) { 9685 SOC_IF_ERROR_RETURN 9686 (soc_greyhound_ser_mem_clear(unit, mem)); 9687 } 9688 } 9689 #endif /* BCM_GREYHOUND_SUPPORT */ 9690 9691 #ifdef BCM_SABER2_SUPPORT 9692 if (SOC_IS_SABER2(unit)) { 9693 if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) { 9694 SOC_IF_ERROR_RETURN 9695 (soc_saber2_ser_mem_clear(unit, mem)); 9696 } 9697 } 9698 #endif /* BCM_SABER2_SUPPORT */ 9699 9700 #endif /* BCM_TRIUMPH_SUPPORT */ 9701 9702 if (SAL_BOOT_SIMULATION) { 9703 to_usec = 10000000; 9704 } else { 9705 to_usec = 50000; 9706 } 9707 #ifdef BCM_SHADOW_SUPPORT 9708 if (SOC_IS_SHADOW(unit) && (mem == ING_VLAN_TAG_ACTION_PROFILEm)) { 9709 return SOC_E_UNAVAIL; 9710 } 9711 9712 if (SOC_IS_SHADOW(unit)) { 9713 /* Reset HW Reset Control */ 9714 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, 0)); 9715 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, 0)); 9716 } 9717 #endif 9718 9719 rv = SOC_E_NONE; 9720 to_rv = SOC_E_NONE; 9721 membase = SOC_MEM_BASE(unit, mem); 9722 mementries = soc_mem_index_count(unit, mem); 9723 #ifdef BCM_EXTND_SBUS_SUPPORT 9724 memnum = 0; 9725 if (soc_feature(unit, soc_feature_new_sbus_format)) { 9726 if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_IPIPE) { 9727 memnum = SOC_MEM_ADDR_NUM_EXTENDED(membase); 9728 /* For KATANA2: ING_HW_RESET_CONTROL_1:: OFFSET 9729 26-bit starting offset of table for memory. 9730 This is {8-bit MEMSEL, 18-bit MEMIDX} 9731 Believe below condition should be out of "if BLK_IPIPE" condition 9732 */ 9733 if (SOC_IS_KATANA2(unit)) { 9734 memoffset = SOC_MEM_ADDR_OFFSET_EXTENDED(membase); 9735 } else { 9736 memoffset = SOC_MEM_ADDR_OFFSET_EXTENDED_IPIPE(membase); 9737 } 9738 } else { 9739 memoffset = SOC_MEM_ADDR_OFFSET_EXTENDED(membase); 9740 } 9741 memstage = SOC_MEM_ADDR_STAGE_EXTENDED(membase); 9742 } else 9743 #endif 9744 { 9745 memoffset = SOC_MEM_ADDR_OFFSET(membase); 9746 memstage = SOC_MEM_ADDR_STAGE(membase); 9747 } 9748 9749 switch (SOC_BLOCK_TYPE(unit, blk)) { 9750 case SOC_BLK_IPIPE: 9751 case SOC_BLK_IPIPE_HI: 9752 hwreset1 = 0; 9753 #ifdef BCM_EXTND_SBUS_SUPPORT 9754 if (soc_reg_field_valid(unit, ING_HW_RESET_CONTROL_1r, 9755 MEMORY_NUMBERf)) { 9756 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_1r, &hwreset1, 9757 MEMORY_NUMBERf, memnum); 9758 } 9759 #endif 9760 9761 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_1r, &hwreset1, 9762 OFFSETf, memoffset); 9763 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_1r, &hwreset1, 9764 STAGE_NUMBERf, memstage); 9765 hwreset2 = 0; 9766 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &hwreset2, 9767 COUNTf, mementries); 9768 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &hwreset2, 9769 VALIDf, 1); 9770 9771 rv = WRITE_ING_HW_RESET_CONTROL_1r(unit, hwreset1); 9772 if (rv < 0) { 9773 break; 9774 } 9775 rv = WRITE_ING_HW_RESET_CONTROL_2r(unit, hwreset2); 9776 if (rv < 0) { 9777 break; 9778 } 9779 9780 soc_timeout_init(&to, to_usec, 100); 9781 for (;;) { 9782 rv = READ_ING_HW_RESET_CONTROL_2r(unit, &hwreset2); 9783 if (rv < 0) { 9784 break; 9785 } 9786 if (soc_reg_field_get(unit, ING_HW_RESET_CONTROL_2r, hwreset2, 9787 DONEf)) { 9788 break; 9789 } 9790 if (soc_timeout_check(&to)) { 9791 to_rv = SOC_E_TIMEOUT; 9792 break; 9793 } 9794 } 9795 hwreset2 = 0; 9796 if (soc_reg_field_valid(unit, ING_HW_RESET_CONTROL_2r, CMIC_REQ_ENABLEf)) { 9797 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &hwreset2, 9798 CMIC_REQ_ENABLEf, 1); 9799 } 9800 rv = WRITE_ING_HW_RESET_CONTROL_2r(unit, hwreset2); 9801 if (rv < 0) { 9802 break; 9803 } 9804 rv = WRITE_ING_HW_RESET_CONTROL_1r(unit, 0); 9805 break; 9806 9807 case SOC_BLK_EPIPE: 9808 case SOC_BLK_EPIPE_HI: 9809 hwreset1 = 0; 9810 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_0r, &hwreset1, 9811 START_ADDRESSf, memoffset); 9812 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_0r, &hwreset1, 9813 STAGE_NUMBERf, memstage); 9814 hwreset2 = 0; 9815 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &hwreset2, 9816 COUNTf, mementries); 9817 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &hwreset2, 9818 VALIDf, 1); 9819 9820 rv = WRITE_EGR_HW_RESET_CONTROL_0r(unit, hwreset1); 9821 if (rv < 0) { 9822 break; 9823 } 9824 rv = WRITE_EGR_HW_RESET_CONTROL_1r(unit, hwreset2); 9825 if (rv < 0) { 9826 break; 9827 } 9828 9829 soc_timeout_init(&to, to_usec, 100); 9830 for (;;) { 9831 rv = READ_EGR_HW_RESET_CONTROL_1r(unit, &hwreset2); 9832 if (rv < 0) { 9833 break; 9834 } 9835 if (soc_reg_field_get(unit, EGR_HW_RESET_CONTROL_1r, hwreset2, 9836 DONEf)) { 9837 break; 9838 } 9839 if (soc_timeout_check(&to)) { 9840 to_rv = SOC_E_TIMEOUT; 9841 break; 9842 } 9843 } 9844 9845 rv = WRITE_EGR_HW_RESET_CONTROL_1r(unit, 0); 9846 if (rv < 0) { 9847 break; 9848 } 9849 rv = WRITE_EGR_HW_RESET_CONTROL_0r(unit, 0); 9850 break; 9851 9852 case SOC_BLK_ISM: 9853 hwreset1 = 0; 9854 soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_0r, &hwreset1, 9855 START_ADDRESSf, memoffset); 9856 soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_0r, &hwreset1, 9857 TABLE_IDf, memstage); 9858 hwreset2 = 0; 9859 soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_1r, &hwreset2, 9860 COUNTf, mementries); 9861 soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_1r, &hwreset2, 9862 VALIDf, 1); 9863 9864 rv = WRITE_ISM_HW_RESET_CONTROL_0r(unit, hwreset1); 9865 if (rv < 0) { 9866 break; 9867 } 9868 rv = WRITE_ISM_HW_RESET_CONTROL_1r(unit, hwreset2); 9869 if (rv < 0) { 9870 break; 9871 } 9872 9873 soc_timeout_init(&to, to_usec, 100); 9874 for (;;) { 9875 rv = READ_ISM_HW_RESET_CONTROL_1r(unit, &hwreset2); 9876 if (rv < 0) { 9877 break; 9878 } 9879 if (soc_reg_field_get(unit, ISM_HW_RESET_CONTROL_1r, hwreset2, 9880 DONEf)) { 9881 break; 9882 } 9883 if (soc_timeout_check(&to)) { 9884 to_rv = SOC_E_TIMEOUT; 9885 break; 9886 } 9887 } 9888 9889 rv = WRITE_ISM_HW_RESET_CONTROL_1r(unit, 0); 9890 if (rv < 0) { 9891 break; 9892 } 9893 rv = WRITE_ISM_HW_RESET_CONTROL_0r(unit, 0); 9894 break; 9895 9896 default: 9897 rv = SOC_E_UNAVAIL; 9898 break; 9899 } 9900 9901 return rv == SOC_E_NONE ? to_rv : rv; 9902 } 9903 #endif /* defined(BCM_FIREBOLT_SUPPORT) */ 9904 9905 #endif /* defined(BCM_XGS_SUPPORT) ... */ 9906 9907 /************************************************************************/ 9908 /* Routines for reading/writing all tables (except no write to ARL) */ 9909 /************************************************************************/ 9910 9911 /* 9912 * Function: _soc_mem_read_tcam_is_invalid 9913 * 9914 * Purpose: Called from within _soc_mem_read. If the read is attempting to 9915 * read from a tcam that makes no sense, we return without reading. 9916 * This is for cases like when a tcam is set to 512 width but the read 9917 * is misconfigured to read only the 2nd 256 bytes instead of the full 9918 * record. 9919 * 9920 * Returns: TRUE if the read call should terminate and return no data 9921 * FALSE if the read seems to be valid (and not a no-op tcam read) 9922 */ 9923 STATIC int 9924 _soc_mem_read_tcam_is_invalid(int unit, soc_mem_t mem, int index) 9925 { 9926 if (soc_feature(unit, soc_feature_field_stage_ingress_256_half_slice)) { 9927 if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm) { 9928 if ((index / 64) % 2) { 9929 return TRUE; 9930 } 9931 } 9932 } 9933 9934 #ifdef BCM_TRIDENT2PLUS_SUPPORT 9935 if (soc_feature(unit, soc_feature_field_stage_quarter_slice) 9936 && soc_feature(unit, soc_feature_field_quarter_slice_single_tcam) 9937 && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) { 9938 if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem) 9939 || (FP_GLOBAL_MASK_TCAMm == mem) 9940 || (FP_GLOBAL_MASK_TCAM_Xm == mem) 9941 || (FP_GLOBAL_MASK_TCAM_Ym == mem)) { 9942 if (index < (soc_mem_index_count(unit, mem) / 2)) { 9943 /* Slices of 2K entries. */ 9944 if (((index / 1024) % 2) || ((index / 512) % 2)) { 9945 return (TRUE); 9946 } 9947 } else { 9948 /* Slices of 1K entries. */ 9949 if (((index / 512) % 2) || ((index / 256) % 2)) { 9950 return (TRUE); 9951 } 9952 } 9953 } 9954 } 9955 #endif /* !BCM_TRIDENT2PLUS_SUPPORT */ 9956 9957 #ifdef BCM_APACHE_SUPPORT 9958 if (soc_feature(unit, soc_feature_field_stage_half_slice) 9959 && soc_feature(unit, soc_feature_field_half_slice_single_tcam) 9960 && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) { 9961 if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem) 9962 || (FP_GLOBAL_MASK_TCAMm == mem) 9963 || (FP_GLOBAL_MASK_TCAM_Xm == mem) 9964 || (FP_GLOBAL_MASK_TCAM_Ym == mem)) { 9965 if (index < (soc_mem_index_count(unit, mem) / 2)) { 9966 /* Slices of 1K entries. */ 9967 if ((index / 512) % 2) { 9968 return (TRUE); 9969 } 9970 } else { 9971 /* Slices of 512 entries. */ 9972 if ((index / 256) % 2) { 9973 return (TRUE); 9974 } 9975 } 9976 } 9977 } 9978 #endif /* !BCM_APACHE_SUPPORT */ 9979 #ifdef BCM_TOMAHAWK2_SUPPORT 9980 if (soc_feature(unit, soc_feature_field_stage_half_slice)) { 9981 if ((IFP_TCAMm == mem) || 9982 (IFP_TCAM_PIPE0m == mem) ||(IFP_TCAM_PIPE1m == mem) || 9983 (IFP_TCAM_PIPE2m == mem) || (IFP_TCAM_PIPE3m == mem)) { 9984 if ((index / 256) % 2) { 9985 return TRUE; 9986 } else { 9987 return FALSE; 9988 } 9989 } 9990 if ((IFP_TCAM_WIDEm == mem) || 9991 (IFP_TCAM_WIDE_PIPE0m == mem) ||(IFP_TCAM_WIDE_PIPE1m == mem) || 9992 (IFP_TCAM_WIDE_PIPE2m == mem) || (IFP_TCAM_WIDE_PIPE3m == mem)) { 9993 if ((index / 128) % 2) { 9994 return TRUE; 9995 } else { 9996 return FALSE; 9997 } 9998 } 9999 } 10000 if (soc_feature(unit, soc_feature_field_stage_quarter_slice)) { 10001 if ((IFP_TCAMm == mem) || 10002 (IFP_TCAM_PIPE0m == mem) ||(IFP_TCAM_PIPE1m == mem) || 10003 (IFP_TCAM_PIPE2m == mem) || (IFP_TCAM_PIPE3m == mem)) { 10004 if ((index / 128) % 4) { 10005 return TRUE; 10006 } else { 10007 return FALSE; 10008 } 10009 } 10010 if ((IFP_TCAM_WIDEm == mem) || 10011 (IFP_TCAM_WIDE_PIPE0m == mem) ||(IFP_TCAM_WIDE_PIPE1m == mem) || 10012 (IFP_TCAM_WIDE_PIPE2m == mem) || (IFP_TCAM_WIDE_PIPE3m == mem)) { 10013 if ((index / 64) % 4) { 10014 return TRUE; 10015 } else { 10016 return FALSE; 10017 } 10018 } 10019 } 10020 10021 #endif /* BCM_TOMAHAWK2_SUPPORT*/ 10022 if (soc_feature(unit, soc_feature_field_ingress_two_slice_types) 10023 && soc_feature(unit, soc_feature_field_stage_ingress_512_half_slice)){ 10024 if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm) { 10025 if (index < (soc_mem_index_count(unit, mem) / 2)) { 10026 if ((index / 256) % 2) { 10027 return TRUE; 10028 } 10029 } 10030 } 10031 } 10032 10033 if (soc_feature(unit, soc_feature_field_ingress_two_slice_types) 10034 && soc_feature(unit, soc_feature_field_slices8)) { 10035 if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm) { 10036 if (index >= (soc_mem_index_count(unit, mem) * 3 / 4)) { 10037 return TRUE; 10038 } 10039 } 10040 } 10041 10042 if (soc_feature(unit, soc_feature_field_stage_egress_256_half_slice)) { 10043 if (mem == EFP_TCAMm) { 10044 if ((index / 128) % 2) { 10045 return TRUE; 10046 } 10047 } 10048 } 10049 10050 if (soc_feature(unit, soc_feature_field_stage_egress_512_half_slice)) { 10051 if (mem == EFP_TCAMm) { 10052 if ((index / 256) % 2) { 10053 return TRUE; 10054 } 10055 } 10056 } 10057 10058 10059 10060 if (soc_feature(unit, soc_feature_field_stage_lookup_512_half_slice)) { 10061 if (mem == VFP_TCAMm) { 10062 if ((index / 128) % 2) { 10063 return TRUE; 10064 } 10065 } 10066 } 10067 10068 if (soc_feature(unit, soc_feature_field_stage_lookup_256_half_slice)) { 10069 if (mem == VFP_TCAMm) { 10070 if ((index / 64) % 2) { 10071 return TRUE; 10072 } 10073 } 10074 } 10075 10076 if (!(soc_feature(unit, 10077 soc_feature_field_stage_lookup_512_half_slice) || 10078 soc_feature(unit, 10079 soc_feature_field_stage_lookup_256_half_slice) || 10080 soc_feature(unit, 10081 soc_feature_field_stage_egress_256_half_slice) || 10082 soc_feature(unit, 10083 soc_feature_field_stage_ingress_256_half_slice))) { 10084 10085 if (!soc_feature(unit, soc_feature_field_stage_quarter_slice)) { 10086 if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm) { 10087 /* Do not access h/w for tcam index mapping to the holes */ 10088 if (soc_feature(unit, soc_feature_field_stage_half_slice) 10089 && (!soc_feature(unit, soc_feature_field_half_slice_single_tcam))) { 10090 if ((index/128) % 2) { 10091 return TRUE; 10092 } 10093 } else if (soc_feature(unit, 10094 soc_feature_field_slice_size128)) { 10095 if ((index/64) % 2) { 10096 return TRUE; 10097 } 10098 } 10099 } else if (mem == EFP_TCAMm) { 10100 /* Do not access h/w for tcam index mapping to the holes */ 10101 if (soc_feature(unit, soc_feature_field_stage_half_slice)) { 10102 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 10103 SOC_IS_VALKYRIE2(unit)) { 10104 if ((index/128) % 2) { 10105 return TRUE; 10106 } 10107 } 10108 } 10109 } 10110 } 10111 } 10112 10113 if (soc_feature(unit, soc_feature_field_stage_quarter_slice)) { 10114 /* Do not access h/w for tcam index mapping to the holes */ 10115 if (mem == EFP_TCAMm) { 10116 if ((SOC_IS_TRIUMPH3(unit)) && ((index/128) % 2)) { 10117 return TRUE; 10118 } 10119 } else if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm || 10120 mem == VFP_TCAMm) { 10121 if ((SOC_IS_TRIUMPH3(unit)) && (((index/128) % 2) || 10122 ((index/64) % 2))) { 10123 return TRUE; 10124 } 10125 } 10126 } 10127 10128 return FALSE; 10129 } 10130 10131 /* 10132 * Function: _soc_mem_read_tr3_tunnel_is_invalid 10133 * 10134 * Purpose: Called from within _soc_mem_read. On Triumph3, if attempting to 10135 * read from certain RX/TX tunnels in the XLPORT/XWPORT at index 10136 * 16 or above, return an indication that the read is invalid. 10137 * 10138 * Returns: TRUE if the read request is invalid and should return no data 10139 * FALSE if the read request seems okay and should continue on 10140 */ 10141 STATIC int 10142 _soc_mem_read_tr3_tunnel_is_invalid(int unit, soc_mem_t mem, int index, int copyno) 10143 { 10144 #if defined(BCM_TRIUMPH3_SUPPORT) 10145 if (SOC_IS_TRIUMPH3(unit)) { 10146 if (mem == PORT_EHG_RX_TUNNEL_DATAm || mem == PORT_EHG_RX_TUNNEL_MASKm || 10147 mem == PORT_EHG_TX_TUNNEL_DATAm) { 10148 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XLPORT) || 10149 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XWPORT)) { 10150 if (index > 15) { 10151 return TRUE; 10152 } 10153 } 10154 } 10155 } 10156 #endif /* BCM_TRIUMPH3_SUPPORT */ 10157 10158 return FALSE; 10159 } 10160 10161 /* 10162 * Function: _soc_mem_read_hercules 10163 * 10164 * Purpose: Called by _soc_mem_read. If the unit is a hercules, redirect the 10165 * request to the hercules mem read handler. 10166 * 10167 * Returns: TRUE if the request was intercepted and handled by hercules 10168 * FALSE if the request should proceed normally 10169 */ 10170 STATIC int 10171 _soc_mem_read_hercules(int unit, soc_mem_t mem, int copyno, int index, 10172 void *entry_data, int *rv) 10173 { 10174 #ifdef BCM_HERCULES_SUPPORT 10175 /* Handle Hercules' word read tables separately */ 10176 if (SOC_IS_HERCULES(unit) && 10177 (soc_mem_flags(unit, mem) & SOC_MEM_FLAG_WORDADR)) { 10178 *rv = soc_hercules_mem_read(unit, mem, copyno, index, entry_data); 10179 return TRUE; 10180 } 10181 #endif /* BCM_HERCULES_SUPPORT */ 10182 10183 return FALSE; 10184 } 10185 10186 /* 10187 * Function: _soc_mem_read_tr3_esm_unlock 10188 * 10189 * Purpose: Called by _soc_mem_read. On Triumph3, if ESM correction is enabled 10190 * and reading from the ESM or ETU blocks, release the ESM lock. 10191 */ 10192 STATIC void 10193 _soc_mem_read_tr3_esm_unlock(int unit, int copyno) 10194 { 10195 #if defined(BCM_TRIUMPH3_SUPPORT) 10196 if (soc_feature(unit, soc_feature_esm_correction) && 10197 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 10198 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 10199 10200 SOC_ESM_UNLOCK(unit); 10201 } 10202 #endif 10203 } 10204 10205 /* 10206 * Function: _soc_mem_read_tr3_esm_lock 10207 * 10208 * Purpose: Called by _soc_mem_read. On Triumph3, if ESM correction is enabled 10209 * and reading from the ESM or ETU blocks, take the ESM lock. 10210 */ 10211 STATIC void 10212 _soc_mem_read_tr3_esm_lock(int unit, int copyno) 10213 { 10214 #if defined(BCM_TRIUMPH3_SUPPORT) 10215 if (soc_feature(unit, soc_feature_esm_correction) && 10216 (copyno != COPYNO_ALL) && ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 10217 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 10218 10219 SOC_ESM_LOCK(unit); 10220 } 10221 #endif 10222 } 10223 10224 /* 10225 * Function: _soc_mem_read_cache_attempt 10226 * 10227 * Purpose: Called from within _soc_mem_read. If this memory is cached and 10228 * it makes sense to serve the read from the cache, then do so. Also 10229 * sets the variable cache_consistency_check=1 if the cache should be 10230 * checked at the end of the read for consistency. 10231 * 10232 * Returns: TRUE if the read was served from the cache 10233 * FALSE if it was not 10234 */ 10235 int 10236 _soc_mem_read_cache_attempt(int unit, uint32 flags, soc_mem_t mem, int copyno, 10237 int index, int array_index, void *entry_data, 10238 uint32 *entry_data_cache, 10239 uint32 *cache_consistency_check) 10240 { 10241 uint32 *cache; 10242 uint8 *vmap; 10243 int force_cache = 0; 10244 int entry_dw = soc_mem_entry_words(unit, mem); 10245 #ifdef BCM_DNX_SUPPORT 10246 int mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ? 10247 ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) 10248 : (array_index * soc_mem_index_count(unit, mem)); 10249 10250 #else 10251 int mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem); 10252 #endif 10253 int mem_array_cache_offset = mem_array_vmap_offset * entry_dw; 10254 10255 if ((flags & SOC_MEM_DONT_USE_CACHE) || 10256 (flags & SOC_MEM_DONT_MAP_INDEX)) { 10257 return FALSE; 10258 } 10259 10260 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 10261 force_cache = soc_mem_is_cache_only(unit, mem); 10262 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 10263 10264 /* Return data from cache if active */ 10265 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 10266 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 10267 10268 if (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_SER_WRITE_CACHE_RESTORE) && 10269 (cache != NULL) && CACHE_VMAP_TST(vmap, index + mem_array_vmap_offset) 10270 && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 10271 #ifdef INCLUDE_TCL 10272 /* Check contents of cache match device table */ 10273 if ((SOC_IS_TD_TT(unit) && 10274 (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_GM_FIELDSm)) || 10275 (!SOC_MEM_CACHE_COHERENCY_CHECK(unit)) || 10276 (flags & SOC_MEM_DONT_CONVERT_XY2DM)) { 10277 *cache_consistency_check = 0; 10278 } else if (force_cache) { 10279 *cache_consistency_check = 0; 10280 } else { 10281 *cache_consistency_check = 1; 10282 } 10283 10284 if (*cache_consistency_check) { 10285 sal_memcpy(entry_data_cache, cache + mem_array_cache_offset + 10286 index * entry_dw, entry_dw * 4); 10287 } else 10288 #endif 10289 { 10290 sal_memcpy(entry_data, cache + mem_array_cache_offset + 10291 index * entry_dw, entry_dw * 4); 10292 if (force_cache || (!SOC_CONTROL(unit)->force_read_through)) { 10293 return TRUE; 10294 } 10295 } 10296 } 10297 10298 return FALSE; 10299 } 10300 10301 int 10302 _soc_mem_alpm_read_cache(int unit, soc_mem_t mem, int copyno, 10303 int index, void *entry_data) 10304 { 10305 int rv = SOC_E_NONE; 10306 uint32 *cache; 10307 uint8 *vmap; 10308 int entry_dw = soc_mem_entry_words(unit, mem); 10309 10310 if (copyno == MEM_BLOCK_ANY || copyno == SOC_CORE_ALL) { 10311 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 10312 } 10313 10314 MEM_LOCK(unit, mem); 10315 10316 /* Return data from cache if active */ 10317 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 10318 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 10319 10320 if (cache != NULL 10321 && CACHE_VMAP_TST(vmap, index)) { 10322 sal_memcpy(entry_data, cache + index * entry_dw, entry_dw * 4); 10323 rv = SOC_E_NONE; 10324 } else { 10325 rv = SOC_E_DISABLED; 10326 } 10327 10328 MEM_UNLOCK(unit, mem); 10329 10330 return rv; 10331 } 10332 10333 /* 10334 * Function: _soc_mem_read_tr3_read_attempt 10335 * 10336 * Purpose: Called from within _soc_mem_read. On Triumph devices with the 10337 * "always drive dbus" feature, add special case handling to reads 10338 * from the ESM block. 10339 * 10340 * Returns: TRUE if the read was handled by this function 10341 * FALSE if this function did nothing 10342 */ 10343 STATIC int 10344 _soc_mem_read_tr3_read_attempt(int unit, soc_mem_t mem, int index, int copyno, 10345 void *entry_data, int *rv) 10346 { 10347 #ifdef BCM_TRIUMPH_SUPPORT 10348 if (soc_feature(unit, soc_feature_always_drive_dbus) && 10349 SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM && 10350 soc_mem_is_cam(unit, mem)) { 10351 10352 static const soc_field_t field_mask[] = 10353 {TMW0f, TMW1f, TMW2f, TMW3f, TMW4f, TMW5f}; 10354 static const soc_field_t field_data[] = 10355 {TDW0f, TDW1f, TDW2f, TDW3f, TDW4f, TDW5f}; 10356 10357 uint32 tmp_entry[SOC_MAX_MEM_WORDS]; 10358 uint32 sdata[SOC_MAX_MEM_WORDS], src_hit, dst_hit; 10359 soc_mem_t real_mem, defip_data_mem, src_hit_mem, dst_hit_mem, mask_mem; 10360 int raw_index, valid; 10361 int tcam_width, i; 10362 uint32 mask[4], data[4]; 10363 10364 *rv = soc_tcam_mem_index_to_raw_index(unit, mem, index, &real_mem, 10365 &raw_index); 10366 if (SOC_FAILURE(*rv)) { 10367 return TRUE; 10368 } 10369 switch (mem) { 10370 case EXT_ACL360_TCAM_DATAm: 10371 case EXT_ACL360_TCAM_DATA_IPV6_SHORTm: 10372 mask_mem = EXT_ACL360_TCAM_MASKm; 10373 break; 10374 case EXT_ACL432_TCAM_DATAm: 10375 case EXT_ACL432_TCAM_DATA_IPV6_LONGm: 10376 case EXT_ACL432_TCAM_DATA_L2_IPV4m: 10377 case EXT_ACL432_TCAM_DATA_L2_IPV6m: 10378 mask_mem = EXT_ACL432_TCAM_MASKm; 10379 break; 10380 default: 10381 mask_mem = INVALIDm; 10382 break; 10383 } 10384 10385 defip_data_mem = INVALIDm; 10386 src_hit_mem = INVALIDm; 10387 dst_hit_mem = INVALIDm; 10388 switch (real_mem) { 10389 case EXT_IPV4_DEFIPm: 10390 defip_data_mem = EXT_DEFIP_DATA_IPV4m; 10391 src_hit_mem = EXT_SRC_HIT_BITS_IPV4m; 10392 dst_hit_mem = EXT_DST_HIT_BITS_IPV4m; 10393 tcam_width = 1; 10394 break; 10395 case EXT_IPV6_64_DEFIPm: 10396 defip_data_mem = EXT_DEFIP_DATA_IPV6_64m; 10397 src_hit_mem = EXT_SRC_HIT_BITS_IPV6_64m; 10398 dst_hit_mem = EXT_DST_HIT_BITS_IPV6_64m; 10399 tcam_width = 1; 10400 break; 10401 case EXT_IPV6_128_DEFIPm: 10402 defip_data_mem = EXT_DEFIP_DATA_IPV6_128m; 10403 src_hit_mem = EXT_SRC_HIT_BITS_IPV6_128m; 10404 dst_hit_mem = EXT_DST_HIT_BITS_IPV6_128m; 10405 tcam_width = 2; 10406 break; 10407 case EXT_L2_ENTRY_TCAMm: 10408 case EXT_IPV4_DEFIP_TCAMm: 10409 case EXT_IPV6_64_DEFIP_TCAMm: 10410 tcam_width = 1; 10411 break; 10412 case EXT_IPV6_128_DEFIP_TCAMm: 10413 case EXT_ACL144_TCAMm: 10414 tcam_width = 2; 10415 break; 10416 case EXT_ACL288_TCAMm: 10417 tcam_width = 4; 10418 break; 10419 case EXT_ACL360_TCAM_DATAm: 10420 tcam_width = 5; 10421 break; 10422 case EXT_ACL432_TCAM_DATAm: 10423 tcam_width = 6; 10424 break; 10425 case EXT_L2_ENTRYm: 10426 default: 10427 tcam_width = 0; 10428 break; 10429 } 10430 10431 sal_memcpy(entry_data, soc_mem_entry_null(unit, real_mem), 10432 soc_mem_entry_words(unit, real_mem) * sizeof(uint32)); 10433 10434 if (defip_data_mem != INVALIDm) { 10435 *rv = soc_mem_read(unit, defip_data_mem, copyno, index, tmp_entry); 10436 if (SOC_FAILURE(*rv)) { 10437 return TRUE; 10438 } 10439 soc_mem_field_get(unit, defip_data_mem, tmp_entry, SDATAf, sdata); 10440 soc_mem_field_set(unit, real_mem, entry_data, SDATAf, sdata); 10441 } 10442 if (src_hit_mem != INVALIDm) { 10443 *rv = soc_mem_read(unit, src_hit_mem, copyno, index >> 5, 10444 tmp_entry); 10445 if (SOC_FAILURE(*rv)) { 10446 return TRUE; 10447 } 10448 src_hit = (soc_mem_field32_get(unit, src_hit_mem, tmp_entry, 10449 SRC_HITf) >> (index & 0x1f)) & 1; 10450 soc_mem_field32_set(unit, real_mem, entry_data, SRC_HITf, src_hit); 10451 } 10452 if (dst_hit_mem != INVALIDm) { 10453 *rv = soc_mem_read(unit, dst_hit_mem, copyno, index >> 5, 10454 tmp_entry); 10455 if (SOC_FAILURE(*rv)) { 10456 return TRUE; 10457 } 10458 dst_hit = (soc_mem_field32_get(unit, dst_hit_mem, tmp_entry, 10459 DST_HITf) >> (index & 0x1f)) & 1; 10460 soc_mem_field32_set(unit, real_mem, entry_data, DST_HITf, dst_hit); 10461 } 10462 if (mask_mem != INVALIDm) { 10463 sal_memcpy(tmp_entry, soc_mem_entry_null(unit, mask_mem), 10464 soc_mem_entry_words(unit, mask_mem) * sizeof(uint32)); 10465 } 10466 if (tcam_width) { 10467 for (i = 0; i < tcam_width; i++) { 10468 *rv = soc_tcam_read_entry(unit, TCAM_PARTITION_RAW, 10469 raw_index + i, mask, data, &valid); 10470 if (SOC_FAILURE(*rv)) { 10471 return TRUE; 10472 } 10473 mask[0] = mask[3]; 10474 mask[3] = mask[1]; 10475 mask[1] = mask[2]; 10476 mask[2] = mask[3]; 10477 if (mask_mem == INVALIDm) { 10478 soc_mem_field_set(unit, real_mem, entry_data, 10479 field_mask[i], mask); 10480 } else { 10481 soc_mem_field_set(unit, mask_mem, tmp_entry, 10482 field_mask[i], mask); 10483 } 10484 data[0] = data[3]; 10485 data[3] = data[1]; 10486 data[1] = data[2]; 10487 data[2] = data[3]; 10488 soc_mem_field_set(unit, real_mem, entry_data, field_data[i], 10489 data); 10490 } 10491 if (mask_mem != INVALIDm) { 10492 *rv = soc_mem_write(unit, mask_mem, copyno, 0, tmp_entry); 10493 } 10494 return TRUE; 10495 } 10496 } 10497 #endif /* BCM_TRIUMPH_SUPPORT */ 10498 10499 return FALSE; 10500 } 10501 10502 /* 10503 * Function: _soc_mem_read_td2_xpipe_tbl_attempt 10504 * 10505 * Purpose: Called within _soc_mem_read. On Trident2, intercept reads from 10506 * the X/Y pipes and serve them from memory. 10507 * 10508 * Returns: TRUE if this function handled the read request 10509 * FALSE if it did not. 10510 */ 10511 STATIC int 10512 _soc_mem_read_td2_xpipe_tbl_attempt(int unit, soc_mem_t mem, int index, 10513 void *entry_data, int *rv) 10514 { 10515 #ifdef BCM_TRIDENT2_SUPPORT 10516 /* For MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1, do not read hardware table. */ 10517 if (SOC_IS_TRIDENT2(unit)) { 10518 if (mem == MMU_INTFI_XPIPE_FC_MAP_TBL0m || 10519 mem == MMU_INTFI_XPIPE_FC_MAP_TBL1m || 10520 mem == MMU_INTFI_YPIPE_FC_MAP_TBL0m || 10521 mem == MMU_INTFI_YPIPE_FC_MAP_TBL1m){ 10522 10523 *rv = soc_trident2_fc_map_shadow_entry_get(unit, mem, index, 10524 entry_data); 10525 return TRUE; 10526 } 10527 } 10528 #endif 10529 10530 return FALSE; 10531 } 10532 10533 /* 10534 * Function: _soc_mem_read_defip_index_map 10535 * 10536 * Purpose: Called from within _soc_mem_read and write. On many devices, we 10537 * have to DEFIP table access, converting the requested index 10538 * into the actual hardware value "index2." 10539 * 10540 * Returns: nothing, but index2 is set as output. 10541 */ 10542 STATIC void 10543 _soc_mem_read_defip_index_map(int unit, soc_mem_t mem, int index, int *index2) 10544 { 10545 *index2 = index; 10546 10547 #if defined(BCM_FIREBOLT_SUPPORT) 10548 #if defined(SOC_MEM_L3_DEFIP_WAR) || defined(BCM_TRIUMPH3_SUPPORT) || \ 10549 defined(BCM_ENDURO_SUPPORT)|| defined(BCM_KATANA2_SUPPORT) || \ 10550 defined(BCM_KATANA_SUPPORT) 10551 if (soc_feature(unit, soc_feature_l3_defip_map) && 10552 (mem == L3_DEFIPm || 10553 mem == L3_DEFIP_LEVEL1m || 10554 mem == L3_DEFIP_ONLYm || 10555 mem == L3_DEFIP_DATA_ONLYm || 10556 mem == L3_DEFIP_HIT_ONLY_Xm || 10557 mem == L3_DEFIP_HIT_ONLY_Ym || 10558 mem == L3_DEFIP_HIT_ONLYm)) { 10559 #ifdef BCM_TRIUMPH3_SUPPORT 10560 if ((SOC_IS_TRIUMPH3(unit)) || ((SOC_IS_HELIX4(unit)) && 10561 (!soc_feature(unit, soc_feature_l3_256_defip_table))) ) { 10562 *index2 = soc_tr3_l3_defip_index_map(unit, mem, index); 10563 } else 10564 #endif /* BCM_TRIUMPH3_SUPPORT */ 10565 #ifdef BCM_KATANA_SUPPORT 10566 if (SOC_IS_KATANA(unit)) { 10567 *index2 = soc_kt_l3_defip_index_map(unit, mem, index); 10568 } else 10569 #endif /* BCM_KATANA_SUPPORT */ 10570 #ifdef BCM_KATANA2_SUPPORT 10571 if (SOC_IS_KATANA2(unit)) { 10572 *index2 = soc_kt2_l3_defip_index_map(unit, mem, index); 10573 } else 10574 #endif /* BCM_KATANA2_SUPPORT */ 10575 #if defined(BCM_TRIDENT2_SUPPORT) 10576 if (SOC_IS_TD2_TT2(unit)) { 10577 *index2 = soc_trident2_l3_defip_index_map(unit, mem, index); 10578 } else 10579 #endif /* BCM_TRIDENT2_SUPPORT */ 10580 #if defined(BCM_ENDURO_SUPPORT) 10581 if (SOC_IS_ENDURO(unit)) { 10582 *index2 = soc_enduro_l3_defip_index_map(unit, mem, index); 10583 } else 10584 #endif /* BCM_ENDURO_SUPPORT */ 10585 { 10586 #ifdef SOC_MEM_L3_DEFIP_WAR 10587 *index2 = soc_fb_l3_defip_index_map(unit, index); 10588 #endif /* SOC_MEM_L3_DEFIP_WAR */ 10589 } 10590 } 10591 #endif /* SOC_MEM_L3_DEFIP_WAR || BCM_TRIUMPH3_SUPPORT */ 10592 #endif /* BCM_FIREBOLT_SUPPORT */ 10593 10594 #ifdef BCM_TRIUMPH2_SUPPORT 10595 if (soc_feature(unit, soc_feature_l3_defip_hole) && 10596 (mem == L3_DEFIPm || 10597 mem == L3_DEFIP_ONLYm || 10598 mem == L3_DEFIP_DATA_ONLYm || 10599 mem == L3_DEFIP_HIT_ONLYm)) { 10600 *index2 = soc_tr2_l3_defip_index_map(unit, index); 10601 } 10602 #endif /* BCM_TRIUMPH2_SUPPORT */ 10603 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \ 10604 defined(BCM_KATANA_SUPPORT) 10605 if (soc_feature(unit, soc_feature_l3_defip_map) && 10606 (mem == L3_DEFIP_PAIR_128m || 10607 mem == L3_DEFIP_PAIR_LEVEL1m || 10608 mem == L3_DEFIP_PAIR_128_ONLYm || 10609 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 10610 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 10611 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 10612 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 10613 #if defined(BCM_TRIUMPH3_SUPPORT) 10614 if ((SOC_IS_TRIUMPH3(unit)) || ((SOC_IS_HELIX4(unit)) && 10615 (!soc_feature(unit, soc_feature_l3_256_defip_table))) ) { 10616 *index2 = soc_tr3_l3_defip_index_map(unit, mem, index); 10617 } 10618 #endif /* BCM_TRIUMPH3_SUPPORT */ 10619 #if defined(BCM_TRIDENT2_SUPPORT) 10620 if SOC_IS_TD2_TT2(unit) { 10621 *index2 = soc_trident2_l3_defip_index_map(unit, mem, index); 10622 } 10623 #endif /* BCM_TRIDENT2_SUPPORT */ 10624 #ifdef BCM_KATANA_SUPPORT 10625 if (SOC_IS_KATANA(unit)) { 10626 *index2 = soc_kt_l3_defip_index_map(unit, mem, index); 10627 } 10628 #endif /* BCM_KATANA_SUPPORT */ 10629 #ifdef BCM_KATANA2_SUPPORT 10630 if (SOC_IS_KATANA2(unit)) { 10631 *index2 = soc_kt2_l3_defip_index_map(unit, mem, index); 10632 } 10633 #endif /* BCM_KATANA2_SUPPORT */ 10634 } 10635 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPPORT*/ 10636 } 10637 10638 10639 /* 10640 * Function: _soc_mem_defip_index_is_invalid 10641 * 10642 * Purpose: Called from within _soc_mem_read and write. This function is used to check 10643 * if this physical index is invalid for this mem view. 10644 * 10645 * Returns: TRUE if the index is invalid 10646 * FALSE if the index is valid 10647 */ 10648 STATIC int 10649 _soc_mem_defip_index_is_invalid(int unit, soc_mem_t mem, int index) 10650 { 10651 int index_max = soc_mem_index_max(unit, mem); 10652 int index_for_check = index; 10653 soc_mem_t defip_mem = L3_DEFIPm, defip_pair_mem = L3_DEFIP_PAIR_128m; 10654 10655 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 10656 defip_mem = L3_DEFIP_LEVEL1m; 10657 defip_pair_mem = L3_DEFIP_PAIR_LEVEL1m; 10658 } 10659 10660 if (soc_feature(unit, soc_feature_l3_defip_map)) { 10661 if (mem == defip_mem || 10662 #ifdef BCM_TOMAHAWK3_SUPPORT 10663 mem == L3_DEFIP_LEVEL1_HIT_ONLYm || 10664 #endif 10665 mem == L3_DEFIP_ONLYm || 10666 mem == L3_DEFIP_DATA_ONLYm || 10667 mem == L3_DEFIP_HIT_ONLY_Xm || 10668 mem == L3_DEFIP_HIT_ONLY_Ym || 10669 mem == L3_DEFIP_HIT_ONLYm) { 10670 index_max = soc_mem_index_count(unit, defip_mem) + 10671 soc_mem_index_count(unit, defip_pair_mem) * 2 - 1; 10672 10673 if (soc_feature(unit, soc_feature_l3_1k_defip_table)) { 10674 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 10675 int num_tcams = soc_mem_index_count(unit, defip_pair_mem) ? 1 : 0; 10676 10677 index_max = soc_mem_index_count(unit, defip_mem) + 10678 num_tcams * 2 * tcam_size; 10679 } 10680 } else if (mem == defip_pair_mem || 10681 mem == L3_DEFIP_PAIR_128_ONLYm || 10682 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 10683 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 10684 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 10685 mem == L3_DEFIP_PAIR_128_HIT_ONLYm) { 10686 index_max = soc_mem_index_count(unit, defip_mem) / 2 + 10687 soc_mem_index_count(unit, defip_pair_mem); 10688 index_max--; 10689 } 10690 } 10691 10692 if (index_for_check < 0 || index_for_check > index_max) { 10693 if (!(SOC_DEFIP_HOLE_RANGE_CHECK(unit, mem, index))) { 10694 LOG_ERROR(BSL_LS_SOC_SOCMEM, 10695 (BSL_META_U(unit, 10696 "invalid index %d for memory %s\n"), 10697 index_for_check, SOC_MEM_NAME(unit, mem))); 10698 return TRUE; 10699 } 10700 } 10701 10702 return FALSE; 10703 } 10704 10705 /* 10706 * Function: _soc_mem_read_tr_response_word_update 10707 * 10708 * Purpose: Called from within _soc_mem_read. When reading certain tables on 10709 * TRIUMPH devices with ESM support, the schan response will have a 10710 * response word in it. If so, set the resp_word variable. 10711 * 10712 * Returns: nothing, but resp_word may be updated 10713 * 10714 * Note: 10715 * We probably should invent SOC_MEM_FLAG_HAS_RESP_WORD in regsfile 10716 * for such tables (or define a bit in S-chan message header if 10717 * hardware can do that) 10718 */ 10719 STATIC void 10720 _soc_mem_read_tr_response_word_update(int unit, soc_mem_t mem, 10721 int *resp_word) 10722 { 10723 #ifdef BCM_TRIUMPH_SUPPORT 10724 if ((!SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM) && 10725 soc_feature(unit, soc_feature_esm_support)) { 10726 switch (mem) { 10727 case EXT_L2_ENTRYm: 10728 case EXT_L2_ENTRY_TCAMm: 10729 case EXT_L2_ENTRY_DATAm: 10730 case EXT_DEFIP_DATAm: 10731 case EXT_IPV4_DEFIP_TCAMm: 10732 case EXT_IPV4_DEFIPm: 10733 case EXT_IPV6_64_DEFIP_TCAMm: 10734 case EXT_IPV6_64_DEFIPm: 10735 case EXT_IPV6_128_DEFIP_TCAMm: 10736 case EXT_IPV6_128_DEFIPm: 10737 case EXT_FP_POLICYm: 10738 case EXT_FP_CNTRm: 10739 case EXT_FP_CNTR8m: 10740 case EXT_ACL144_TCAMm: 10741 case EXT_ACL288_TCAMm: 10742 case EXT_ACL360_TCAM_DATAm: /* not for MASK portion */ 10743 case EXT_ACL432_TCAM_DATAm: /* not for MASK portion */ 10744 /* and following software invented tables as well */ 10745 case EXT_DEFIP_DATA_IPV4m: 10746 case EXT_DEFIP_DATA_IPV6_64m: 10747 case EXT_DEFIP_DATA_IPV6_128m: 10748 case EXT_FP_POLICY_ACL288_L2m: 10749 case EXT_FP_POLICY_ACL288_IPV4m: 10750 case EXT_FP_POLICY_ACL360_IPV6_SHORTm: 10751 case EXT_FP_POLICY_ACL432_IPV6_LONGm: 10752 case EXT_FP_POLICY_ACL144_L2m: 10753 case EXT_FP_POLICY_ACL144_IPV4m: 10754 case EXT_FP_POLICY_ACL144_IPV6m: 10755 case EXT_FP_POLICY_ACL432_L2_IPV4m: 10756 case EXT_FP_POLICY_ACL432_L2_IPV6m: 10757 case EXT_FP_CNTR_ACL288_L2m: 10758 case EXT_FP_CNTR_ACL288_IPV4m: 10759 case EXT_FP_CNTR_ACL360_IPV6_SHORTm: 10760 case EXT_FP_CNTR_ACL432_IPV6_LONGm: 10761 case EXT_FP_CNTR_ACL144_L2m: 10762 case EXT_FP_CNTR_ACL144_IPV4m: 10763 case EXT_FP_CNTR_ACL144_IPV6m: 10764 case EXT_FP_CNTR_ACL432_L2_IPV4m: 10765 case EXT_FP_CNTR_ACL432_L2_IPV6m: 10766 case EXT_FP_CNTR8_ACL288_L2m: 10767 case EXT_FP_CNTR8_ACL288_IPV4m: 10768 case EXT_FP_CNTR8_ACL360_IPV6_SHORTm: 10769 case EXT_FP_CNTR8_ACL432_IPV6_LONGm: 10770 case EXT_FP_CNTR8_ACL144_L2m: 10771 case EXT_FP_CNTR8_ACL144_IPV4m: 10772 case EXT_FP_CNTR8_ACL144_IPV6m: 10773 case EXT_FP_CNTR8_ACL432_L2_IPV4m: 10774 case EXT_FP_CNTR8_ACL432_L2_IPV6m: 10775 case EXT_ACL288_TCAM_L2m: 10776 case EXT_ACL288_TCAM_IPV4m: 10777 case EXT_ACL360_TCAM_DATA_IPV6_SHORTm: 10778 case EXT_ACL432_TCAM_DATA_IPV6_LONGm: 10779 case EXT_ACL144_TCAM_L2m: 10780 case EXT_ACL144_TCAM_IPV4m: 10781 case EXT_ACL144_TCAM_IPV6m: 10782 case EXT_ACL432_TCAM_DATA_L2_IPV4m: 10783 case EXT_ACL432_TCAM_DATA_L2_IPV6m: 10784 #ifdef BCM_TRIUMPH3_SUPPORT 10785 if (SOC_IS_TRIUMPH3(unit)) { 10786 break; 10787 } 10788 #endif /* BCM_TRIUMPH3_SUPPORT */ 10789 *resp_word = 1; 10790 break; 10791 default: 10792 break; 10793 } 10794 } 10795 #endif /* BCM_TRIUMPH_SUPPORT */ 10796 } 10797 10798 STATIC void 10799 _soc_mem_acc_type_swap(int unit, schan_header_t *header) { 10800 int acc_type_swap = 0, acc_type_old = 0; 10801 10802 if (soc_feature(unit, soc_feature_sbus_format_v4)) { 10803 acc_type_old = header->v4.acc_type; 10804 } else if (soc_feature(unit, soc_feature_new_sbus_format)) { 10805 acc_type_old = header->v3.acc_type; 10806 } else { 10807 acc_type_old = header->v2.src_blk; 10808 } 10809 10810 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 10811 if (acc_type_old == _SOC_MEM_ADDR_ACC_TYPE_PIPE_1) { 10812 acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0; 10813 } else { 10814 acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_1; 10815 } 10816 } else { 10817 if (acc_type_old == _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y) { 10818 acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X; 10819 } else { 10820 acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y; 10821 } 10822 } 10823 10824 if (soc_feature(unit, soc_feature_sbus_format_v4)) { 10825 header->v4.acc_type = acc_type_swap; 10826 } else if (soc_feature(unit, soc_feature_new_sbus_format)) { 10827 header->v3.acc_type = acc_type_swap; 10828 } else { 10829 header->v2.src_blk = acc_type_swap; 10830 } 10831 } 10832 10833 /* 10834 * Function: _soc_mem_read_ser_correct 10835 * 10836 * Purpose: Called from within _soc_mem_read. If there was a error reading, 10837 * try to use SER to correct it. 10838 * 10839 * Returns: TRUE if the error was corrected, 10840 * FALSE if it was not. 10841 */ 10842 STATIC int 10843 _soc_mem_read_ser_correct(int unit, uint32 flags, soc_mem_t mem, int copyno, 10844 int index, void *entry_data, 10845 schan_msg_t *schan_msg, schan_msg_t *schan_msg_cpy, 10846 int resp_word, int *rv, int *all_done) 10847 { 10848 uint32 *cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 10849 uint8 *vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 10850 int entry_dw = soc_mem_entry_words(unit, mem); 10851 int allow_intr = SOC_IS_SAND(unit) ? 1 : 0; 10852 10853 if (!SOC_SER_CORRECTION_SUPPORT(unit)) { 10854 return FALSE; 10855 } 10856 10857 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 10858 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 10859 defined(BCM_GREYHOUND_SUPPORT) 10860 do { 10861 uint8 *corrupt = NULL; 10862 10863 /* Record error index for TCAM table */ 10864 if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 10865 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 10866 corrupt = SOC_MEM_STATE(unit, mem).corrupt[copyno]; 10867 if (corrupt != NULL) { 10868 TCAM_CORRUPT_MAP_SET(corrupt, index); 10869 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 10870 (BSL_META_U(unit, 10871 "Mem[%s] index[%d] " 10872 "TCAM parity error indicating bit is set.\n"), 10873 SOC_MEM_NAME(unit, mem), index)); 10874 } 10875 } 10876 } while (0); 10877 #endif 10878 10879 if (flags & SOC_MEM_SCHAN_ERR_RETURN) { 10880 return FALSE; 10881 } 10882 10883 if (cache != NULL && CACHE_VMAP_TST(vmap, index) 10884 && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 10885 sal_memcpy(entry_data, cache + index * entry_dw, entry_dw * 4); 10886 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10887 (BSL_META_U(unit, 10888 "Unit:%d Mem[%s] index[%d] " 10889 "Force fetch data from cache.\n"), 10890 unit, SOC_MEM_NAME(unit, mem), index)); 10891 } else if (SOC_IS_TD2_TT2(unit) && 10892 soc_feature(unit, soc_feature_two_ingress_pipes) && 10893 (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 10894 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 10895 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIPm || 10896 mem == L3_DEFIP_PAIR_128m || 10897 mem == L3_DEFIP_LEVEL1m || 10898 mem == L3_DEFIP_PAIR_LEVEL1m || 10899 mem == L3_DEFIP_ALPM_LEVEL2m || 10900 mem == L3_DEFIP_ALPM_LEVEL3m)) { 10901 /* Fetch data from other pipe */ 10902 _soc_mem_acc_type_swap(unit, &(schan_msg_cpy->readcmd.header)); 10903 10904 *rv = soc_schan_op(unit, schan_msg_cpy, 2, 1 + entry_dw + resp_word, allow_intr); 10905 if (SOC_FAILURE(*rv)) { 10906 return TRUE; 10907 } 10908 10909 sal_memcpy(schan_msg, schan_msg_cpy, sizeof(*schan_msg)); 10910 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10911 (BSL_META_U(unit, 10912 "Unit:%d Mem[%s] index[%d] " 10913 "Force fetch data from other pipe.\n"), 10914 unit, SOC_MEM_NAME(unit, mem), index)); 10915 return TRUE; 10916 } else { 10917 void *null_entry = soc_mem_entry_null(unit, mem); 10918 sal_memcpy(entry_data, null_entry, entry_dw * 4); 10919 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10920 (BSL_META_U(unit, 10921 "Unit:%d Mem[%s] index[%d] " 10922 "Force fetch null data.\n"), 10923 unit, SOC_MEM_NAME(unit, mem), index)); 10924 return TRUE; 10925 } 10926 10927 return FALSE; 10928 } 10929 10930 /* 10931 * Function: _soc_mem_read_td_tt_byte_len_update 10932 * 10933 * Purpose: Called within _soc_mem_read. On Trident/titan chips, the expected 10934 * data length from certain memories has to be set as a special case. 10935 * 10936 * Returns: Nothing, but may alter the data_byte_len variable if necessary. 10937 */ 10938 STATIC void 10939 _soc_mem_read_td_tt_byte_len_update(int unit, soc_mem_t mem, int entry_dw, 10940 int *data_byte_len) 10941 { 10942 #ifdef BCM_TRIDENT_SUPPORT 10943 if (SOC_IS_TD_TT(unit)) { 10944 if (mem == ESBS_PORT_TO_PIPE_MAPPINGm || 10945 mem == ISBS_PORT_TO_PIPE_MAPPINGm) { 10946 *data_byte_len = entry_dw * 4; 10947 } 10948 } 10949 #endif /* BCM_TRIDENT_SUPPORT */ 10950 } 10951 10952 /* 10953 * Function: soc_mem_dst_blk_update 10954 * 10955 * Purpose: Called within _soc_mem_read/write. In certain configurations, the 10956 * destination block for schan requests must be calculated as a 10957 * special case and not read directly from the regsfile. 10958 * 10959 * Returns: Nothing, but may alter the dst_blk variable if necessary. 10960 */ 10961 void 10962 soc_mem_dst_blk_update(int unit, int copyno, int maddr, int *dst_blk) 10963 { 10964 *dst_blk = 0; 10965 10966 #if defined(BCM_EXTND_SBUS_SUPPORT) || defined(BCM_SAND_SUPPORT) 10967 10968 if (soc_feature(unit, soc_feature_new_sbus_format)) { 10969 *dst_blk = SOC_BLOCK2SCH(unit, copyno); 10970 } else 10971 10972 #endif 10973 { 10974 #if defined(BCM_XGS3_SWITCH_SUPPORT) ||\ 10975 defined(BCM_SAND_SUPPORT) 10976 /* required on XGS3. Optional on other devices */ 10977 *dst_blk = ((maddr >> SOC_BLOCK_BP) & 0xf) | 10978 (((maddr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 10979 #endif /* BCM_XGS3_SWITCH_SUPPORT || BCM_SAND_SUPPORT */ 10980 } 10981 } 10982 10983 #ifdef HR3LITE_LPM_WAR 10984 /* 10985 * Function: _soc_mem_hr3_lpm_hit_shadow_update 10986 * 10987 * Purpose: Called by _soc_mem_read_schan_msg_send(). 10988 * This function is used to sync-up the correct LPM-HIT entry on 10989 * HR3-Lite device. LPM table in HR3-Lite support 64 entries only, 10990 * but LPM-TCAM on entry between 32~63 can only be hit with 10991 * LPM-DATA on entry between 512~543 and the hit status is updated 10992 * by HW on LPM-HIT entry 512~543 as well. 10993 * 10994 * Returns: SOC_E_xxx 10995 */ 10996 10997 STATIC int 10998 _soc_mem_hr3_lpm_hit_shadow_update(int unit, soc_mem_t mem, int copyno, 10999 int index, void *lpm_entry_data, unsigned array_index) 11000 { 11001 defip_entry_t *lpm_entry; 11002 defip_hit_only_entry_t lpm_hit_entry; 11003 int defip_hit_size = 0; 11004 int lpm_hit_shadow_index = -1; 11005 schan_msg_t schan_msg; 11006 int opcode, err; 11007 int resp_word = 0; 11008 int entry_dw = soc_mem_entry_words(unit, L3_DEFIP_HIT_ONLYm); 11009 int rv = SOC_E_NONE; 11010 int src_blk, dst_blk, acc_type, data_byte_len; 11011 uint32 maddr; 11012 uint8 at; 11013 uint32 new_hit = 0, old_hit = 0; 11014 11015 if (soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit)) { 11016 if ((NEED_HR3LITE_LPM_SHADOW(mem)) && (mem != L3_DEFIP_DATA_ONLYm)) { 11017 lpm_hit_shadow_index = HR3LITE_LPM_HIT_INDEX2(index); 11018 } 11019 } 11020 11021 if (lpm_hit_shadow_index == -1) { 11022 /* no sync-up process is required */ 11023 return SOC_E_NONE; 11024 } 11025 11026 LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, 11027 "HR3-Lite LPM_WAR:update LPM(%s,idx=%d) HIT from entry(%d)!\n"), 11028 SOC_MEM_NAME(unit, mem),index, lpm_hit_shadow_index)); 11029 /* init entry data buf */ 11030 defip_hit_size = sizeof(defip_hit_only_entry_t); 11031 sal_memset(&lpm_hit_entry, 0, defip_hit_size); 11032 11033 sal_memset(&schan_msg, 0, sizeof(schan_msg_t)); 11034 11035 /* Setup S-Channel command packet */ 11036 schan_msg_clear(&schan_msg); 11037 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 11038 acc_type = SOC_MEM_ACC_TYPE(unit, L3_DEFIP_HIT_ONLYm); 11039 data_byte_len = 4; 11040 11041 maddr = soc_mem_addr_get(unit, L3_DEFIP_HIT_ONLYm, array_index, 11042 copyno, lpm_hit_shadow_index, &at); 11043 schan_msg.readcmd.address = maddr; 11044 11045 soc_mem_dst_blk_update(unit, copyno, maddr, &dst_blk); 11046 _soc_mem_read_tr_response_word_update(unit, mem, &resp_word); 11047 11048 soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG, 11049 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 11050 11051 /* 11052 * Write onto S-Channel "memory read" command packet consisting of header 11053 * word + address word, and read back header word + entry_dw data words. 11054 */ 11055 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 11056 LOG_WARN(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11057 "soc_mem_read: assert will fail for memory %s\n"), 11058 SOC_MEM_NAME(unit, L3_DEFIP_HIT_ONLYm))); 11059 } 11060 11061 rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, 0); 11062 11063 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 11064 &err, NULL, NULL); 11065 if (opcode != READ_MEMORY_ACK_MSG || err != 0) { 11066 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11067 "soc_mem_read: Mem(%s) invalid S-Channel reply, " 11068 "expected READ_MEMORY_ACK:, opcode %d\n"), 11069 SOC_MEM_NAME(unit,L3_DEFIP_HIT_ONLYm), opcode)); 11070 soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word); 11071 rv = SOC_E_INTERNAL; 11072 return rv; 11073 } 11074 11075 sal_memcpy(&lpm_hit_entry, 11076 resp_word ? schan_msg.genresp.data : schan_msg.readresp.data, 11077 entry_dw * sizeof (uint32)); 11078 11079 /* sync-up hit field */ 11080 new_hit = soc_L3_DEFIP_HIT_ONLYm_field32_get(unit, &lpm_hit_entry, HITf); 11081 if (mem == L3_DEFIP_HIT_ONLYm) { 11082 old_hit = soc_L3_DEFIP_HIT_ONLYm_field32_get(unit, lpm_entry_data, HITf); 11083 /* sync-up the HIT field */ 11084 sal_memcpy(lpm_entry_data, &lpm_hit_entry, entry_dw * sizeof (uint32)); 11085 } else if (mem == L3_DEFIPm) { 11086 lpm_entry = lpm_entry_data; 11087 old_hit = soc_L3_DEFIPm_field32_get(unit, lpm_entry, HITf); 11088 /* sync-up the HIT field */ 11089 soc_L3_DEFIPm_field32_set(unit, lpm_entry, HITf, new_hit); 11090 } 11091 LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, 11092 "HR3-Lite LPM_WAR:update LPM(%s,idx=%d) new_hit=%d, old_hit=%d\n"), 11093 SOC_MEM_NAME(unit, mem),index, new_hit, old_hit)); 11094 11095 return rv; 11096 } 11097 #endif /* HR3LITE_LPM_WAR */ 11098 11099 #ifdef BCM_TOMAHAWK3_SUPPORT 11100 /* 11101 * Function: _soc_th3_mem_read_schan_msg_send 11102 * 11103 * Purpose: Called within _soc_mem_read. Construct and send a schan message 11104 * holding the read requests, and parse the response. If an error 11105 * happens, try to correct with SER. 11106 * 11107 * Returns: Standard BCM_E_* code 11108 */ 11109 STATIC int 11110 _soc_th3_mem_read_schan_msg_send(int unit, uint32 flags, soc_mem_t mem, int copyno, 11111 int index, void *entry_data, unsigned array_index, 11112 int remapped_index, int acc_type) 11113 { 11114 schan_msg_t schan_msg, schan_msg_cpy; 11115 int opcode, err; 11116 int resp_word = 0; 11117 int entry_dw = soc_mem_entry_words(unit, mem); 11118 int rv = SOC_E_NONE; 11119 int allow_intr = 0; 11120 int src_blk, dst_blk, data_byte_len; 11121 uint32 maddr; 11122 uint8 at; 11123 sal_memset(&schan_msg, 0, sizeof(schan_msg_t)); 11124 11125 /* Setup S-Channel command packet */ 11126 schan_msg_clear(&schan_msg); 11127 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 11128 data_byte_len = 4; 11129 11130 maddr = soc_mem_addr_get(unit, mem, array_index, copyno, remapped_index, 11131 &at); 11132 schan_msg.readcmd.address = maddr; 11133 11134 _soc_mem_read_td_tt_byte_len_update(unit, mem, entry_dw, &data_byte_len); 11135 soc_mem_dst_blk_update(unit, copyno, maddr, &dst_blk); 11136 _soc_mem_read_tr_response_word_update(unit, mem, &resp_word); 11137 11138 soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG, 11139 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 11140 11141 /* 11142 * Write onto S-Channel "memory read" command packet consisting of header 11143 * word + address word, and read back header word + entry_dw data words. 11144 */ 11145 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 11146 LOG_WARN(BSL_LS_SOC_SOCMEM, 11147 (BSL_META_U(unit, 11148 "soc_mem_read: assert will fail for memory %s\n"), 11149 SOC_MEM_NAME(unit, mem))); 11150 } 11151 11152 rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, allow_intr); 11153 if (SOC_FAILURE(rv)) { 11154 int all_done = FALSE; 11155 _soc_mem_read_ser_correct(unit, flags, mem, copyno, index, entry_data, 11156 &schan_msg, &schan_msg_cpy, resp_word, &rv, 11157 &all_done); 11158 if (SOC_FAILURE(rv) || all_done) { 11159 return rv; 11160 } 11161 } 11162 11163 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 11164 &err, NULL, NULL); 11165 if (opcode != READ_MEMORY_ACK_MSG || err != 0) { 11166 { 11167 LOG_ERROR(BSL_LS_SOC_SOCMEM, 11168 (BSL_META_U(unit, 11169 "soc_mem_read: " 11170 "Mem(%s) " 11171 "invalid S-Channel reply, expected READ_MEMORY_ACK:, opcode %d\n"), 11172 SOC_MEM_NAME(unit,mem), opcode)); 11173 soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word); 11174 rv = SOC_E_INTERNAL; 11175 return rv; 11176 } 11177 } 11178 sal_memcpy(entry_data, 11179 resp_word ? schan_msg.genresp.data : schan_msg.readresp.data, 11180 entry_dw * sizeof (uint32)); 11181 #ifdef USE_VALGRIND_CLIENT_REQUESTS 11182 VALGRIND_MAKE_MEM_DEFINED(entry_data, entry_dw * sizeof (uint32)); 11183 #endif /* USE_VALGRIND_CLIENT_REQUESTS */ 11184 11185 return rv; 11186 } 11187 #endif 11188 /* 11189 * Function: _soc_mem_read_schan_msg_send 11190 * 11191 * Purpose: Called within _soc_mem_read. Construct and send a schan message 11192 * holding the read requests, and parse the response. If an error 11193 * happens, try to correct with SER. 11194 * 11195 * Returns: Standard BCM_E_* code 11196 */ 11197 STATIC int 11198 _soc_mem_read_schan_msg_send(int unit, uint32 flags, soc_mem_t mem, int copyno, 11199 int index, void *entry_data, unsigned array_index, 11200 int remapped_index) 11201 { 11202 schan_msg_t schan_msg, schan_msg_cpy; 11203 int opcode, err; 11204 int resp_word = 0; 11205 int entry_dw = soc_mem_entry_words(unit, mem); 11206 int rv = SOC_E_NONE; 11207 int allow_intr = SOC_IS_SAND(unit) ? 1 : 0; 11208 int src_blk, dst_blk, acc_type, data_byte_len; 11209 uint32 maddr; 11210 uint8 at; 11211 11212 sal_memset(&schan_msg, 0, sizeof(schan_msg_t)); 11213 11214 /* Setup S-Channel command packet */ 11215 schan_msg_clear(&schan_msg); 11216 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 11217 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 11218 data_byte_len = 4; 11219 11220 maddr = soc_mem_addr_get(unit, mem, array_index, copyno, remapped_index, 11221 &at); 11222 schan_msg.readcmd.address = maddr; 11223 11224 _soc_mem_read_td_tt_byte_len_update(unit, mem, entry_dw, &data_byte_len); 11225 soc_mem_dst_blk_update(unit, copyno, maddr, &dst_blk); 11226 _soc_mem_read_tr_response_word_update(unit, mem, &resp_word); 11227 11228 soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG, 11229 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 11230 11231 /* 11232 * Write onto S-Channel "memory read" command packet consisting of header 11233 * word + address word, and read back header word + entry_dw data words. 11234 */ 11235 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 11236 LOG_WARN(BSL_LS_SOC_SOCMEM, 11237 (BSL_META_U(unit, 11238 "soc_mem_read: assert will fail for memory %s\n"), 11239 SOC_MEM_NAME(unit, mem))); 11240 } 11241 11242 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 11243 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg)); 11244 } 11245 rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, allow_intr); 11246 if (SOC_FAILURE(rv)) { 11247 int all_done = FALSE; 11248 _soc_mem_read_ser_correct(unit, flags, mem, copyno, index, entry_data, 11249 &schan_msg, &schan_msg_cpy, resp_word, &rv, 11250 &all_done); 11251 if (SOC_FAILURE(rv) || all_done) { 11252 return rv; 11253 } 11254 } 11255 11256 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 11257 &err, NULL, NULL); 11258 if (opcode != READ_MEMORY_ACK_MSG || err != 0) { 11259 { 11260 LOG_ERROR(BSL_LS_SOC_SOCMEM, 11261 (BSL_META_U(unit, 11262 "soc_mem_read: " 11263 "Mem(%s) " 11264 "invalid S-Channel reply, expected READ_MEMORY_ACK:, opcode %d\n"),SOC_MEM_NAME(unit,mem), opcode)); 11265 soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word); 11266 rv = SOC_E_INTERNAL; 11267 return rv; 11268 } 11269 } 11270 sal_memcpy(entry_data, 11271 resp_word ? schan_msg.genresp.data : schan_msg.readresp.data, 11272 entry_dw * sizeof (uint32)); 11273 #ifdef USE_VALGRIND_CLIENT_REQUESTS 11274 VALGRIND_MAKE_MEM_DEFINED(entry_data, entry_dw * sizeof (uint32)); 11275 #endif /* USE_VALGRIND_CLIENT_REQUESTS */ 11276 11277 #ifdef HR3LITE_LPM_WAR 11278 /* if target table is HR3-Lite's LPM, HIT bit is updated by HW from 11279 * LPM-HIT table and for HR3-Lite's LPM entry 32~63 this HIT bit needs 11280 * WAR to sync-up correct HIT from LPM-HIT entry 512~543. 11281 */ 11282 if (soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit) && 11283 NEED_HR3LITE_LPM_SHADOW(mem)) { 11284 rv = _soc_mem_hr3_lpm_hit_shadow_update(unit, 11285 mem, copyno, index, entry_data, array_index); 11286 } 11287 #endif /* HR3LITE_LPM_WAR */ 11288 11289 return rv; 11290 } 11291 11292 /* 11293 * Function: _soc_mem_read_tcam_to_dm_format 11294 * 11295 * Purpose: On certain devices, data from TCAMs and the ETU block has to be 11296 * converted from X-Y format to D-M format. 11297 */ 11298 STATIC void _soc_mem_read_tcam_to_dm_format(int unit, soc_mem_t mem, int copyno, 11299 soc_mem_info_t *meminfo, uint32 flags, 11300 void *entry_data) 11301 { 11302 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 11303 || defined(BCM_HURRICANE2_SUPPORT) 11304 if (soc_feature(unit, soc_feature_xy_tcam_direct) && 11305 (meminfo->flags & SOC_MEM_FLAG_CAM) && 11306 (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM)) && 11307 (!(flags & SOC_MEM_DONT_CONVERT_XY2DM))) { 11308 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 11309 _soc_mem_fp_global_mask_tcam_shift(unit, mem, entry_data, 0, 0); 11310 #endif 11311 _soc_mem_tcam_xy_to_dm(unit, mem, 1, entry_data, entry_data); 11312 } 11313 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 11314 11315 #ifdef BCM_TRIUMPH3_SUPPORT 11316 /* convert X-Y data of esm external tcam table reads to D-M format */ 11317 if (soc_feature(unit, soc_feature_etu_support) && 11318 SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU) { 11319 11320 uint32 key[SOC_MAX_MEM_FIELD_WORDS], mask[SOC_MAX_MEM_FIELD_WORDS]; 11321 soc_field_t key_field[4], mask_field[4]; 11322 int field_count=0, bit_length, word_length, i, word; 11323 11324 switch (mem) { 11325 case EXT_L2_ENTRY_TCAMm: 11326 case EXT_L2_ENTRY_TCAM_WIDEm: 11327 case EXT_IPV4_TCAMm: 11328 case EXT_IPV6_64_TCAMm: 11329 case EXT_IPV4_DEFIPm: 11330 case EXT_IPV4_DEFIP_TCAMm: 11331 case EXT_IPV4_UCASTm: 11332 case EXT_IPV4_UCAST_TCAMm: 11333 case EXT_IPV4_UCAST_WIDEm: 11334 case EXT_IPV4_UCAST_WIDE_TCAMm: 11335 case EXT_IPV6_64_DEFIPm: 11336 case EXT_IPV6_64_DEFIP_TCAMm: 11337 case EXT_ACL80_TCAMm: 11338 key_field[0] = TDW0f; 11339 mask_field[0] = TMW0f; 11340 field_count = 1; 11341 break; 11342 11343 case EXT_IPV6_128_TCAMm: 11344 case EXT_IPV6_128_DEFIPm: 11345 case EXT_IPV6_128_DEFIP_TCAMm: 11346 case EXT_IPV6_128_UCASTm: 11347 case EXT_IPV6_128_UCAST_TCAMm: 11348 case EXT_IPV6_128_UCAST_WIDEm: 11349 case EXT_IPV6_128_UCAST_WIDE_TCAMm: 11350 case EXT_ACL160_TCAMm: 11351 case EXT_ACL144_TCAM_L2m: 11352 case EXT_ACL144_TCAM_IPV4m: 11353 case EXT_ACL144_TCAM_IPV6m: 11354 key_field[0] = TDW0f; 11355 key_field[1] = TDW1f; 11356 mask_field[0] = TMW0f; 11357 mask_field[1] = TMW1f; 11358 field_count = 2; 11359 break; 11360 11361 case EXT_ACL288_TCAM_L2m: 11362 case EXT_ACL288_TCAM_IPV4m: 11363 case EXT_ACL432_TCAM_DATA_L2_IPV4m: 11364 case EXT_ACL320_TCAMm: 11365 key_field[0] = TDW0f; 11366 key_field[1] = TDW1f; 11367 key_field[2] = TDW2f; 11368 key_field[3] = TDW3f; 11369 mask_field[0] = TMW0f; 11370 mask_field[1] = TMW1f; 11371 mask_field[2] = TMW2f; 11372 mask_field[3] = TMW3f; 11373 field_count = 4; 11374 break; 11375 11376 11377 #ifdef fix_later 11378 case EXT_ACL360_TCAM_DATA_IPV6_SHORTm: 11379 case EXT_ACL432_TCAM_DATA_IPV6_LONGm: 11380 case EXT_ACL432_TCAM_DATA_L2_IPV6m: 11381 case EXT_ACL432_TCAM_MASKm: 11382 case EXT_ACL360_TCAM_MASK_IPV6_SHORTm: 11383 case EXT_ACL432_TCAM_MASK_IPV6_LONGm: 11384 case EXT_ACL432_TCAM_MASK_L2_IPV6m: 11385 case EXT_ACL480_TCAM_DATAm: 11386 case EXT_ACL480_TCAM_MASKm: 11387 key_field[0] = TDW0f; 11388 key_field[1] = TDW1f; 11389 key_field[2] = TDW2f; 11390 key_field[3] = TDW3f; 11391 mask_field[0] = TMW0f; 11392 mask_field[1] = TMW1f; 11393 mask_field[2] = TMW2f; 11394 mask_field[3] = TMW3f; 11395 field_count = 6; 11396 break; 11397 #endif 11398 } 11399 for (i = 0; i < field_count; i++) { 11400 soc_mem_field_get(unit, mem, entry_data, key_field[i], key); 11401 soc_mem_field_get(unit, mem, entry_data, mask_field[i], mask); 11402 bit_length = soc_mem_field_length(unit, mem, key_field[i]); 11403 word_length = (bit_length + 31) / 32; 11404 for (word = 0; word < word_length; word++) { 11405 /* save data word first */ 11406 mask[word] = ~(key[word] | mask[word]); 11407 } 11408 if ((bit_length & 0x1f) != 0) { 11409 mask[word - 1] &= (1 << (bit_length & 0x1f)) - 1; 11410 } 11411 soc_mem_field_set(unit, mem, entry_data, mask_field[i], mask); 11412 soc_mem_field_set(unit, mem, entry_data, key_field[i], key); 11413 } 11414 } 11415 #endif /* BCM_TRIUMPH3_SUPPORT */ 11416 11417 } 11418 11419 void soc_mem_parity_field_clear(int unit, int mem, 11420 void* entry_data, void *entry_data_cache) 11421 { 11422 /* Heuristic to clear parity/ecc bits */ 11423 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITYf); 11424 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITYf); 11425 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_0f); 11426 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_1f); 11427 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_2f); 11428 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_3f); 11429 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_Af); 11430 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_Bf); 11431 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_LOWERf); 11432 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_UPPERf); 11433 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P0f); 11434 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P1f); 11435 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P2f); 11436 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P3f); 11437 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P0f); 11438 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P1f); 11439 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P2f); 11440 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P3f); 11441 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P0f); 11442 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P1f); 11443 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P2f); 11444 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P3f); 11445 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCf); 11446 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_FIELDf); 11447 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_0f); 11448 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_1f); 11449 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_2f); 11450 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_3f); 11451 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_4f); 11452 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCPf); 11453 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP0f); 11454 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP1f); 11455 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP2f); 11456 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP3f); 11457 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP4f); 11458 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP5f); 11459 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP6f); 11460 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP7f); 11461 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_0f); 11462 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_1f); 11463 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_2f); 11464 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_3f); 11465 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_4f); 11466 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC0f); 11467 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC1f); 11468 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC2f); 11469 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC3f); 11470 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY0f); 11471 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY1f); 11472 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY2f); 11473 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY3f); 11474 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_0f); 11475 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_1f); 11476 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_2f); 11477 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_3f); 11478 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_4f); 11479 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P0f); 11480 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P1f); 11481 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P2f); 11482 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P3f); 11483 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P0f); 11484 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P1f); 11485 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P2f); 11486 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P3f); 11487 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P0f); 11488 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P1f); 11489 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P2f); 11490 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P3f); 11491 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P0f); 11492 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P1f); 11493 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P2f); 11494 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P3f); 11495 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P4f); 11496 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P5f); 11497 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P6f); 11498 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P7f); 11499 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P0f); 11500 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P1f); 11501 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P2f); 11502 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P3f); 11503 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P4f); 11504 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P5f); 11505 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P6f); 11506 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P7f); 11507 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P0f); 11508 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P1f); 11509 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P2f); 11510 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P3f); 11511 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P4f); 11512 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P5f); 11513 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P6f); 11514 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P7f); 11515 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_0f); 11516 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_1f); 11517 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_2f); 11518 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_3f); 11519 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_0f); 11520 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_1f); 11521 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_2f); 11522 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_3f); 11523 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_0f); 11524 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_1f); 11525 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_2f); 11526 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_3f); 11527 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEYf); 11528 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASKf); 11529 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK_UPRf); 11530 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK_LWRf); 11531 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY_UPRf); 11532 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY_LWRf); 11533 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY1f); 11534 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY0f); 11535 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK1f); 11536 _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK0f); 11537 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECC0f); 11538 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECC1f); 11539 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECCP0f); 11540 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECCP1f); 11541 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_PARITY0f); 11542 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_PARITY1f); 11543 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_TCAM_PARITY_MASKf); 11544 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_TCAM_PARITY_KEYf); 11545 _SOC_ENTRY_PARITY_CLEAR(unit, mem, UPR_TCAM_PARITY_MASKf); 11546 _SOC_ENTRY_PARITY_CLEAR(unit, mem, UPR_TCAM_PARITY_KEYf); 11547 11548 /* Clear hit bits */ 11549 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITf); 11550 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT0f); 11551 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT1f); 11552 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_0f); 11553 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_1f); 11554 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_2f); 11555 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_3f); 11556 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_0f); 11557 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_1f); 11558 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_2f); 11559 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_3f); 11560 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_0f); 11561 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_1f); 11562 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_2f); 11563 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_3f); 11564 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDAf); 11565 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSAf); 11566 _SOC_ENTRY_PARITY_CLEAR(unit, mem, B0_HITf); 11567 _SOC_ENTRY_PARITY_CLEAR(unit, mem, B1_HITf); 11568 _SOC_ENTRY_PARITY_CLEAR(unit, mem, L3_HIT_DCMf); 11569 _SOC_ENTRY_PARITY_CLEAR(unit, mem, L3_HIT_PMf); 11570 _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_BITSf); 11571 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_HIT0f); 11572 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_HIT1f); 11573 /* Clear hardware-modified fields in meter tables */ 11574 _SOC_ENTRY_PARITY_CLEAR(unit, mem, BUCKETCOUNTf); 11575 _SOC_ENTRY_PARITY_CLEAR(unit, mem, REFRESHCOUNTf); 11576 11577 /* Clear parity/ecc bits on svm_meter_table */ 11578 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_EXCESSf); 11579 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_EXCESSf); 11580 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_EXCESSf); 11581 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_COMMITTEDf); 11582 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_COMMITTEDf); 11583 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_COMMITTEDf); 11584 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_LRNf); 11585 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_LRNf); 11586 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_LRNf); 11587 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_CONFIGf); 11588 _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_CONFIGf); 11589 _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_CONFIGf); 11590 /* Clear hardware-modified fields in svm_meter_table */ 11591 _SOC_ENTRY_PARITY_CLEAR(unit, mem, LRNf); /* LAST_REFRESH_NUMBERf */ 11592 _SOC_ENTRY_PARITY_CLEAR(unit, mem, COMMITTEDf); /* COMMITTED_BUCKETCOUNTf */ 11593 _SOC_ENTRY_PARITY_CLEAR(unit, mem, EXCESSf); /* EXCESS_BUCKETCOUNTf */ 11594 } 11595 11596 /* 11597 * Function: _soc_mem_read_cache_check_clear 11598 * 11599 * Purpose: Called from _soc_mem_read. After a read has accessed the cache, 11600 * some cleanup may be necessary. Perform that here. 11601 */ 11602 STATIC void 11603 _soc_mem_read_cache_check_clear(int unit, int mem, int index, int copyno, 11604 void *entry_data, void *entry_data_cache) 11605 { 11606 #ifdef INCLUDE_TCL 11607 int entry_dw = soc_mem_entry_words(unit, mem); 11608 #ifdef BCM_TOMAHAWK3_SUPPORT 11609 uint16 dev_id; 11610 uint8 rev_id; 11611 11612 soc_cm_get_id(unit, &dev_id, &rev_id); 11613 if (dev_id == BCM56983_DEVICE_ID) { 11614 return; 11615 } 11616 #endif 11617 /* Some exceptions */ 11618 if ((SOC_IS_KATANA2(unit) || SOC_IS_TD_TT(unit) || 11619 SOC_IS_TD2_TT2(unit)) && (mem == EGR_VLANm)) { 11620 return; 11621 } 11622 11623 /* Heuristic to check if entry is valid */ 11624 _SOC_ENTRY_VALID_CHECK(unit, mem, VALIDf); 11625 _SOC_ENTRY_VALID_CHECK(unit, mem, VALID_0f); 11626 _SOC_ENTRY_VALID_CHECK(unit, mem, BASE_VALIDf); 11627 _SOC_ENTRY_VALID_CHECK(unit, mem, BASE_VALID_0f); 11628 11629 soc_mem_parity_field_clear(unit, mem, entry_data, entry_data_cache); 11630 11631 if (sal_memcmp(entry_data_cache, entry_data, 11632 entry_dw * sizeof (uint32)) != 0) { 11633 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityError, unit)) { 11634 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11635 "soc_mem_read unit %d: %s.%s[%d]: cache: "), 11636 unit, SOC_MEM_NAME(unit, mem), 11637 SOC_BLOCK_NAME(unit, copyno), index)); 11638 soc_mem_entry_dump(unit, mem, entry_data_cache, 11639 BSL_ERROR|BSL_LS_SOC_SOCMEM); 11640 11641 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11642 "\n"))); 11643 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11644 "soc_mem_read unit %d: %s.%s[%d]: Device: "), 11645 unit, SOC_MEM_NAME(unit, mem), 11646 SOC_BLOCK_NAME(unit, copyno), index)); 11647 soc_mem_entry_dump(unit, mem, entry_data, BSL_ERROR|BSL_LS_SOC_SOCMEM); 11648 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11649 "\n"))); 11650 } 11651 11652 } 11653 #endif 11654 } 11655 11656 11657 /* 11658 * Function: 11659 * _soc_mem_read 11660 * Purpose: 11661 * Read a memory internal to the SOC. 11662 * Notes: 11663 * GBP/CBP memory should only accessed when MMU is in DEBUG mode. 11664 */ 11665 STATIC int 11666 _soc_mem_read(int unit, uint32 flags, soc_mem_t mem, 11667 /* in memory arrays this is the element index in the array, otherwise 0 */ 11668 unsigned array_index, 11669 int copyno, int index, void *entry_data) 11670 { 11671 soc_mem_info_t *meminfo; 11672 int index2; 11673 int rv, rv2 = SOC_E_NONE; 11674 uint32 entry_data_cache[SOC_MAX_MEM_FIELD_WORDS]; 11675 uint32 cache_consistency_check = 0; 11676 int ok = TRUE; 11677 int entry_num_max = 0; 11678 #ifdef BCM_TOMAHAWK3_SUPPORT 11679 int j = 0, k = 0, l = 0; 11680 uint16 dev_id; 11681 uint8 rev_id; 11682 int acc_type; 11683 int dw = 0; 11684 uint32 *entry = NULL; 11685 void *entry_data1; 11686 int entry_size; 11687 #endif 11688 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 11689 11690 if (!soc_mem_is_valid(unit, mem)) { 11691 return SOC_E_MEMORY; 11692 } 11693 11694 #ifdef BCM_SAND_SUPPORT 11695 /* 11696 * Write onto S-Channel "memory read" command packet consisting of header 11697 * word + address word, and read back header word + soc_mem_entry_words() data words. 11698 */ 11699 if (soc_mem_entry_words(unit, mem) + 2 > CMIC_SCHAN_WORDS(unit)) { 11700 if (SOC_IS_SAND(unit)) 11701 { 11702 rv = _soc_mem_array_wide_read(unit, flags, mem, array_index, copyno, index, entry_data); 11703 return rv; 11704 } 11705 } 11706 #endif 11707 11708 if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm || 11709 mem == EFP_TCAMm || mem == VFP_TCAMm || 11710 mem == FP_GLOBAL_MASK_TCAM_Xm || mem == FP_GLOBAL_MASK_TCAM_Ym || 11711 mem == FP_GM_FIELDSm) { 11712 if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) { 11713 return SOC_E_NONE; 11714 } 11715 } 11716 11717 meminfo = &SOC_MEM_INFO(unit, mem); 11718 11719 if (copyno == MEM_BLOCK_ANY || copyno == SOC_CORE_ALL) { 11720 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 11721 } 11722 11723 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 11724 LOG_WARN(BSL_LS_SOC_SOCMEM, 11725 (BSL_META_U(unit, 11726 "soc_mem_read: invalid block %d for memory %s\n"), 11727 copyno, SOC_MEM_NAME(unit, mem))); 11728 return SOC_E_PARAM; 11729 } 11730 11731 if (_soc_mem_read_tr3_tunnel_is_invalid(unit, mem, index, copyno) == TRUE) { 11732 return SOC_E_NONE; 11733 } 11734 11735 /* 11736 * When checking index, check for 0 instead of soc_mem_index_min. 11737 * Diagnostics need to read/write index 0 of Strata ARL and GIRULE. 11738 */ 11739 if ((flags & SOC_MEM_DONT_MAP_INDEX) && 11740 (mem == L3_DEFIPm || 11741 mem == L3_DEFIP_LEVEL1m || 11742 mem == L3_DEFIP_ONLYm || 11743 mem == L3_DEFIP_DATA_ONLYm || 11744 mem == L3_DEFIP_HIT_ONLY_Xm || 11745 mem == L3_DEFIP_HIT_ONLY_Ym || 11746 mem == L3_DEFIP_HIT_ONLYm || 11747 mem == L3_DEFIP_PAIR_128m || 11748 mem == L3_DEFIP_PAIR_LEVEL1m || 11749 mem == L3_DEFIP_PAIR_128_ONLYm || 11750 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 11751 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 11752 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 11753 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 11754 if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) { 11755 return SOC_E_PARAM; 11756 } 11757 } else { 11758 entry_num_max = soc_mem_index_max(unit, mem); 11759 11760 if (index < 0 || index > entry_num_max) { 11761 if (!(SOC_DEFIP_HOLE_RANGE_CHECK(unit, mem, index))) { 11762 LOG_ERROR(BSL_LS_SOC_SOCMEM, 11763 (BSL_META_U(unit, 11764 "soc_mem_read: invalid index %d for memory %s\n"), 11765 index, SOC_MEM_NAME(unit, mem))); 11766 return SOC_E_PARAM; 11767 } 11768 } 11769 } 11770 11771 if (_soc_mem_read_hercules(unit, mem, copyno, index, 11772 entry_data, &rv) == TRUE) { 11773 return rv; 11774 } 11775 11776 rv = SOC_E_NONE; 11777 11778 #ifdef ALPM_ENABLE 11779 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 11780 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 11781 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 11782 mem == L3_DEFIP_ALPM_RAWm) { 11783 SOC_ALPM_LPM_LOCK(unit); 11784 } else 11785 #endif 11786 { 11787 MEM_LOCK(unit, mem); 11788 } 11789 _soc_mem_read_tr3_esm_lock(unit, copyno); 11790 11791 if (_soc_mem_read_cache_attempt(unit, flags, mem, copyno, index, 11792 array_index, entry_data, 11793 entry_data_cache, 11794 &cache_consistency_check)) { 11795 ok = FALSE; 11796 } 11797 #ifdef CRASH_RECOVERY_SUPPORT 11798 /* Use crash recovery defined callback for access*/ 11799 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 11800 { 11801 if(Hw_Log_List[unit].Access_cb.mem_read) 11802 { 11803 if(ok && Hw_Log_List[unit].Access_cb.mem_read(unit, mem, 11804 array_index, copyno, 11805 index, entry_data)) { 11806 ok = FALSE; 11807 } 11808 } 11809 } 11810 /* enable hw reads and writes */ 11811 #endif /* CRASH_RECOVERY_SUPPORT */ 11812 11813 if (ok && _soc_mem_read_tr3_read_attempt(unit, mem, index, copyno, 11814 entry_data, &rv) == TRUE) { 11815 ok = FALSE; 11816 } 11817 11818 if (ok && _soc_mem_read_td2_xpipe_tbl_attempt(unit, mem, index, entry_data, 11819 &rv) == TRUE) { 11820 ok = FALSE; 11821 } 11822 11823 if (ok) { 11824 index2 = index; 11825 if (!(flags & SOC_MEM_DONT_MAP_INDEX)) { 11826 _soc_mem_read_defip_index_map(unit, mem, index, &index2); 11827 } 11828 11829 #ifdef BCM_TOMAHAWK3_SUPPORT 11830 /* For 56983 Lower die SKU, the data split is converted into 4 unique 11831 reads and the data is ORed to get the final read value 11832 */ 11833 soc_cm_get_id (unit, &dev_id, &rev_id); 11834 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 11835 if (acc_type == 14 && (dev_id == BCM56983_DEVICE_ID)) { 11836 dw = soc_mem_entry_words(unit, mem); 11837 entry_size = dw * sizeof(uint32); 11838 entry = sal_alloc(entry_size, "entry_size"); 11839 sal_memset((void *)entry, 0, sizeof(uint32) * dw); 11840 sal_memset(entry_data, 0, sizeof(uint32) * dw); 11841 entry_data1 = entry; 11842 l = sizeof(uint32); 11843 for (j = 0; j < 4; j++) { 11844 switch(j) { 11845 case 0 : acc_type = 0; 11846 break; 11847 case 1 : acc_type = 1; 11848 break; 11849 case 2 : acc_type = 6; 11850 break; 11851 case 3 : acc_type = 7; 11852 break; 11853 } 11854 rv2 = _soc_th3_mem_read_schan_msg_send(unit, flags, mem, copyno, index, 11855 entry_data1, array_index, index2, acc_type); 11856 if (SOC_SUCCESS(rv2)) { 11857 _soc_mem_read_tcam_to_dm_format(unit, mem, copyno, meminfo, flags, 11858 entry_data1); 11859 } 11860 for (k = 0; k < dw; k++) { 11861 *(uint32 *)((uint8 *)entry_data + l*k) = 11862 *(uint32 *)((uint8 *)entry_data + l*k) | 11863 *(uint32 *)((uint8 *)entry_data1 + l*k); 11864 *(uint32 *) ((uint8 *)entry_data1 + l*k) = 0; 11865 } 11866 } 11867 11868 if (entry) { 11869 sal_free(entry); 11870 } 11871 } else 11872 #endif 11873 { 11874 11875 rv2 = _soc_mem_read_schan_msg_send(unit, flags, mem, copyno, index, 11876 entry_data, array_index, index2); 11877 if (SOC_SUCCESS(rv2)) { 11878 _soc_mem_read_tcam_to_dm_format(unit, mem, copyno, meminfo, flags, 11879 entry_data); 11880 } 11881 } 11882 } 11883 11884 /* All done. Cleanup time. */ 11885 11886 _soc_mem_read_tr3_esm_unlock(unit, copyno); 11887 #ifdef ALPM_ENABLE 11888 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 11889 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 11890 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 11891 mem == L3_DEFIP_ALPM_RAWm) { 11892 SOC_ALPM_LPM_UNLOCK(unit); 11893 } else 11894 #endif 11895 { 11896 MEM_UNLOCK(unit, mem); 11897 } 11898 11899 11900 if (cache_consistency_check) { 11901 _soc_mem_read_cache_check_clear(unit, mem, index, copyno, entry_data, 11902 entry_data_cache); 11903 } 11904 11905 if (NULL != meminfo->snoop_cb) { 11906 if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) { 11907 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ, 11908 copyno, index, index, entry_data, 11909 meminfo->snoop_user_data); 11910 } 11911 if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) { 11912 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT, 11913 copyno, index, index, entry_data, 11914 meminfo->snoop_user_data); 11915 } 11916 } 11917 11918 if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) { 11919 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11920 "soc_mem_read unit %d: %s.%s[%d]: "), 11921 unit, SOC_MEM_NAME(unit, mem), 11922 SOC_BLOCK_NAME(unit, copyno), index)); 11923 soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM); 11924 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 11925 "\n"))); 11926 } 11927 11928 if (ok && (flags & SOC_MEM_SCHAN_ERR_RETURN)) { 11929 return rv2; /* we executed _soc_mem_read_schan_msg_send and we need to 11930 return NACK in case of failure */ 11931 } else { 11932 if ((SOC_FAILURE(rv2)) && cache_consistency_check) { 11933 sal_memcpy(entry_data, entry_data_cache, 11934 soc_mem_entry_words(unit, mem) * sizeof (uint32)); 11935 } 11936 /* we did not execute _soc_mem_read_schan_msg_send */ 11937 return rv; 11938 } 11939 } 11940 11941 /* Wrapper routine with a 'flags' param for better access control */ 11942 int 11943 soc_mem_read_extended(int unit, uint32 flags, soc_mem_t mem, 11944 /* in memory arrays this is the element index in the array, otherwise 0 */ 11945 unsigned array_index, int copyno, 11946 int index, void *entry_data) 11947 { 11948 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 11949 11950 return _soc_mem_read(unit, flags, mem, array_index, copyno, index, 11951 entry_data); 11952 } 11953 11954 /* 11955 * Function: 11956 * soc_mem_pipe_select_read 11957 * Purpose: 11958 * Read a memory internal to the SOC. 11959 * Notes: 11960 * GBP/CBP memory should only accessed when MMU is in DEBUG mode. 11961 */ 11962 int 11963 soc_mem_pipe_select_read(int unit, 11964 uint32 flags, 11965 soc_mem_t mem, 11966 int copyno, 11967 int acc_type, 11968 int index, 11969 void *entry_data) 11970 { 11971 schan_msg_t schan_msg; 11972 int entry_dw = soc_mem_entry_words(unit, mem); 11973 soc_mem_info_t *meminfo; 11974 int index_valid; 11975 uint8 at; 11976 int index2; 11977 uint32 maddr; 11978 int rv, allow_intr = 0; 11979 int resp_word = 0; 11980 int src_blk, dst_blk, data_byte_len; 11981 int opcode, err; 11982 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 11983 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 11984 defined(BCM_GREYHOUND_SUPPORT) 11985 uint8 *corrupt = NULL; 11986 #endif 11987 int entry_num_max = 0; 11988 11989 if (!soc_feature(unit, soc_feature_two_ingress_pipes)) { 11990 /* Not a relevant device */ 11991 return SOC_E_UNAVAIL; 11992 } 11993 11994 if (!soc_mem_is_valid(unit, mem)) { 11995 return SOC_E_MEMORY; 11996 } 11997 11998 meminfo = &SOC_MEM_INFO(unit, mem); 11999 12000 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12001 12002 if (copyno == MEM_BLOCK_ANY) { 12003 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 12004 } 12005 12006 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 12007 LOG_WARN(BSL_LS_SOC_SOCMEM, 12008 (BSL_META_U(unit, 12009 "soc_mem_pipe_select_read: invalid block %d for memory %s\n"), 12010 copyno, SOC_MEM_NAME(unit, mem))); 12011 return SOC_E_PARAM; 12012 } 12013 12014 /* 12015 * When checking index, check for 0 instead of soc_mem_index_min. 12016 * Diagnostics need to read/write index 0 of Strata ARL and GIRULE. 12017 */ 12018 if ((flags & SOC_MEM_DONT_MAP_INDEX) && 12019 (mem == L3_DEFIPm || 12020 mem == L3_DEFIP_LEVEL1m || 12021 mem == L3_DEFIP_ONLYm || 12022 mem == L3_DEFIP_DATA_ONLYm || 12023 mem == L3_DEFIP_HIT_ONLY_Xm || 12024 mem == L3_DEFIP_HIT_ONLY_Ym || 12025 mem == L3_DEFIP_HIT_ONLYm || 12026 mem == L3_DEFIP_PAIR_128m || 12027 mem == L3_DEFIP_PAIR_LEVEL1m || 12028 mem == L3_DEFIP_PAIR_128_ONLYm || 12029 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 12030 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 12031 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 12032 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 12033 if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) { 12034 return SOC_E_PARAM; 12035 } 12036 } else { 12037 entry_num_max = soc_mem_index_max(unit, mem); 12038 12039 index_valid = (index >= 0 && 12040 index <= entry_num_max); 12041 12042 if (!index_valid) { 12043 LOG_ERROR(BSL_LS_SOC_SOCMEM, 12044 (BSL_META_U(unit, 12045 "soc_mem_pipe_select_read: invalid index %d for memory %s acc_type %d\n"), 12046 index, SOC_MEM_NAME(unit, mem), acc_type)); 12047 return SOC_E_PARAM; 12048 } 12049 } 12050 12051 #ifdef BCM_TRIDENT2PLUS_SUPPORT 12052 if (SOC_IS_TD2P_TT2P(unit)) { 12053 if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem) 12054 || (FP_GLOBAL_MASK_TCAMm == mem) 12055 || (FP_GLOBAL_MASK_TCAM_Xm == mem) 12056 || (FP_GLOBAL_MASK_TCAM_Ym == mem)) { 12057 if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) { 12058 return SOC_E_NONE; 12059 } 12060 } 12061 } 12062 #endif 12063 12064 rv = SOC_E_NONE; 12065 12066 #ifdef ALPM_ENABLE 12067 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 12068 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 12069 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 12070 mem == L3_DEFIP_ALPM_RAWm) { 12071 SOC_ALPM_LPM_LOCK(unit); 12072 } else 12073 #endif 12074 { 12075 MEM_LOCK(unit, mem); 12076 } 12077 12078 /* Setup S-Channel command packet */ 12079 schan_msg_clear(&schan_msg); 12080 12081 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 12082 data_byte_len = 4; 12083 #ifdef BCM_TRIDENT_SUPPORT 12084 if (SOC_IS_TD_TT(unit)) { 12085 if (mem == ESBS_PORT_TO_PIPE_MAPPINGm || 12086 mem == ISBS_PORT_TO_PIPE_MAPPINGm) { 12087 data_byte_len = entry_dw * 4; 12088 } 12089 } 12090 #endif /* BCM_TRIDENT_SUPPORT */ 12091 12092 index2 = index; 12093 12094 12095 #if defined(BCM_TRIDENT2_SUPPORT) 12096 if (SOC_IS_TD2_TT2(unit) && 12097 soc_feature(unit, soc_feature_l3_defip_map) && 12098 (mem == L3_DEFIPm || 12099 mem == L3_DEFIP_LEVEL1m || 12100 mem == L3_DEFIP_ONLYm || 12101 mem == L3_DEFIP_DATA_ONLYm || 12102 mem == L3_DEFIP_HIT_ONLY_Xm || 12103 mem == L3_DEFIP_HIT_ONLY_Ym || 12104 mem == L3_DEFIP_HIT_ONLYm || 12105 mem == L3_DEFIP_PAIR_128m || 12106 mem == L3_DEFIP_PAIR_LEVEL1m || 12107 mem == L3_DEFIP_PAIR_128_ONLYm || 12108 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 12109 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 12110 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 12111 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 12112 if (!(flags & SOC_MEM_DONT_MAP_INDEX)) { 12113 index2 = soc_trident2_l3_defip_index_map(unit, mem, index); 12114 } 12115 } 12116 #endif /* BCM_TRIDENT2_SUPPORT */ 12117 maddr = soc_mem_addr_get(unit, mem, 0, copyno, index2, &at); 12118 #if defined(BCM_EXTND_SBUS_SUPPORT) 12119 if (!soc_feature(unit, soc_feature_new_sbus_format) && 12120 (acc_type != 0)) { 12121 /* Override ACC_TYPE in address */ 12122 maddr &= ~(_SOC_MEM_ADDR_ACC_TYPE_MASK << 12123 _SOC_MEM_ADDR_ACC_TYPE_SHIFT); 12124 maddr |= (acc_type & _SOC_MEM_ADDR_ACC_TYPE_MASK) << 12125 _SOC_MEM_ADDR_ACC_TYPE_SHIFT; 12126 } 12127 #endif /* BCM_EXTND_SBUS_SUPPORT */ 12128 schan_msg.readcmd.address = maddr; 12129 12130 dst_blk = 0; 12131 #if defined(BCM_EXTND_SBUS_SUPPORT) 12132 if (soc_feature(unit, soc_feature_new_sbus_format)) { 12133 dst_blk = SOC_BLOCK2SCH(unit, copyno); 12134 } else 12135 #endif 12136 { 12137 #if defined(BCM_XGS3_SWITCH_SUPPORT) 12138 /* required on XGS3. Optional on other devices */ 12139 dst_blk = ((maddr >> SOC_BLOCK_BP) & 0xf) | 12140 (((maddr >> SOC_BLOCK_MSB_BP) & 0x1) << 4); 12141 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 12142 } 12143 12144 soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG, 12145 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 12146 12147 /* 12148 * Write onto S-Channel "memory read" command packet consisting of header 12149 * word + address word, and read back header word + entry_dw data words. 12150 */ 12151 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 12152 LOG_WARN(BSL_LS_SOC_SOCMEM, 12153 (BSL_META_U(unit, 12154 "soc_mem_read: assert will fail for memory %s\n"), 12155 SOC_MEM_NAME(unit, mem))); 12156 } 12157 rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, allow_intr); 12158 if (SOC_FAILURE(rv)) { 12159 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 12160 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 12161 defined(BCM_GREYHOUND_SUPPORT) 12162 if (SOC_SER_CORRECTION_SUPPORT(unit)) { 12163 /* Record error index for TCAM table */ 12164 if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 12165 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 12166 corrupt = SOC_MEM_STATE(unit, mem).corrupt[copyno]; 12167 if (corrupt != NULL) { 12168 TCAM_CORRUPT_MAP_SET(corrupt, index); 12169 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 12170 (BSL_META_U(unit, 12171 "Mem[%s] index[%d] " 12172 "TCAM parity error indicating bit is set.\n"), 12173 SOC_MEM_NAME(unit, mem), index)); 12174 } 12175 } 12176 } 12177 #endif 12178 goto done; 12179 } 12180 12181 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 12182 &err, NULL, NULL); 12183 if (opcode != READ_MEMORY_ACK_MSG || err != 0) { 12184 LOG_ERROR(BSL_LS_SOC_SOCMEM, 12185 (BSL_META_U(unit, 12186 "soc_mem_pipe_select_read: Mem(%s) " 12187 "invalid S-Channel reply, expected READ_MEMORY_ACK:, opcode %d\n"), 12188 SOC_MEM_NAME(unit, mem), opcode)); 12189 soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word); 12190 rv = SOC_E_INTERNAL; 12191 goto done; 12192 } 12193 12194 sal_memcpy(entry_data, 12195 resp_word ? schan_msg.genresp.data : schan_msg.readresp.data, 12196 entry_dw * sizeof (uint32)); 12197 12198 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 12199 if (soc_feature(unit, soc_feature_xy_tcam_direct) && 12200 (meminfo->flags & SOC_MEM_FLAG_CAM) && 12201 (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM)) && 12202 (!(flags & SOC_MEM_DONT_CONVERT_XY2DM))) { 12203 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 12204 _soc_mem_fp_global_mask_tcam_shift(unit, mem, entry_data, 0, 0); 12205 #endif 12206 _soc_mem_tcam_xy_to_dm(unit, mem, 1, entry_data, entry_data); 12207 } 12208 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 12209 12210 done: 12211 12212 #ifdef ALPM_ENABLE 12213 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 12214 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 12215 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 12216 mem == L3_DEFIP_ALPM_RAWm) { 12217 SOC_ALPM_LPM_UNLOCK(unit); 12218 } else 12219 #endif 12220 { 12221 MEM_UNLOCK(unit, mem); 12222 } 12223 12224 if (NULL != meminfo->snoop_cb) { 12225 if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) { 12226 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ, 12227 copyno, index, index, entry_data, 12228 meminfo->snoop_user_data); 12229 } 12230 if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) { 12231 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT, 12232 copyno, index, index, entry_data, 12233 meminfo->snoop_user_data); 12234 } 12235 } 12236 12237 if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) { 12238 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 12239 "soc_mem_read unit %d: %s.%s[%d]: "), 12240 unit, SOC_MEM_NAME(unit, mem), 12241 SOC_BLOCK_NAME(unit, copyno), index)); 12242 soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM); 12243 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 12244 "\n"))); 12245 } 12246 12247 return rv; 12248 } 12249 12250 #ifdef BCM_KATANA2_SUPPORT 12251 STATIC int 12252 _soc_mem_read_kt2(int unit, 12253 soc_mem_t mem, 12254 int copyno, 12255 int index, 12256 void *entry_data) 12257 { 12258 int rv = SOC_E_FAIL; 12259 12260 uint32 rval; 12261 uint16 dev_id; 12262 uint8 rev_id; 12263 12264 soc_cm_get_id(unit, &dev_id, &rev_id); 12265 if (SOC_IS_KATANA2(unit) && 12266 (rev_id == BCM56450_B1_REV_ID) && 12267 (SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) && 12268 (mem == ING_PHYSICAL_PORT_TABLEm)) { 12269 12270 READ_ING_Q_BEGINr(unit, &rval); 12271 soc_reg_field_set(unit, ING_Q_BEGINr, &rval, 12272 ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf, 1); 12273 WRITE_ING_Q_BEGINr(unit, rval); 12274 LOG_VERBOSE(BSL_LS_SOC_COMMON, 12275 (BSL_META_U(unit, "READ PKT_DISABLE=1\n"))); 12276 12277 rv = soc_mem_array_read(unit, mem, 0, copyno, index, entry_data); 12278 soc_reg_field_set(unit, ING_Q_BEGINr, &rval, 12279 ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf, 0); 12280 WRITE_ING_Q_BEGINr(unit, rval); 12281 LOG_VERBOSE(BSL_LS_SOC_COMMON, 12282 (BSL_META_U(unit, "READ PKT_DISABLE=0\n"))); 12283 } else { 12284 return soc_mem_array_read(unit, mem, 0, copyno, index, entry_data); 12285 } 12286 12287 return rv; 12288 } 12289 #endif 12290 12291 int 12292 soc_mem_read(int unit, soc_mem_t mem, int copyno, int index, void *entry_data) 12293 { 12294 int rv; 12295 #ifdef BCM_TRIDENT3_SUPPORT 12296 soc_mem_t phy_mem; 12297 #endif 12298 12299 #ifdef BCM_TRIDENT3_SUPPORT 12300 if (soc_feature(unit, soc_feature_flex_flow)) { 12301 if (SOC_MEM_IS_VIEW(unit, mem)) { 12302 rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem); 12303 if (rv != SOC_E_NONE) { 12304 return rv; 12305 } 12306 mem = phy_mem; 12307 } 12308 } 12309 #endif 12310 12311 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12312 12313 _SOC_MEM_REPLACE_MEM(unit, mem); 12314 12315 #ifdef BCM_KATANA2_SUPPORT 12316 if (SOC_IS_KATANA2(unit)) { 12317 rv = _soc_mem_read_kt2(unit, mem, copyno, index, entry_data); 12318 } else 12319 #endif 12320 { 12321 rv = soc_mem_array_read(unit, mem, 0, copyno, index, entry_data); 12322 } 12323 12324 return rv; 12325 } 12326 12327 int 12328 soc_mem_read_no_cache(int unit, 12329 uint32 flags, 12330 soc_mem_t mem, 12331 unsigned array_index, 12332 int copyno, 12333 int index, 12334 void *entry_data) 12335 { 12336 int rv; 12337 12338 _SOC_MEM_REPLACE_MEM(unit, mem); 12339 flags |= SOC_MEM_DONT_USE_CACHE; 12340 12341 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12342 12343 MEM_LOCK(unit, mem); 12344 rv = soc_mem_array_read_flags(unit, mem, array_index, copyno, 12345 index, entry_data, flags); 12346 MEM_UNLOCK(unit, mem); 12347 12348 return rv; 12349 } 12350 12351 STATIC int 12352 _soc_mem_trident_egr_vlan_read(int unit, soc_mem_t mem, unsigned array_index, 12353 int copyno, int index, void *entry_data, int *rv) 12354 { 12355 #ifdef BCM_TRIDENT_SUPPORT 12356 uint32 entry_data_y[SOC_MAX_MEM_WORDS]; 12357 soc_pbmp_t pbmp_x, pbmp_y; 12358 12359 if (!SOC_IS_TRIDENT(unit) && !SOC_IS_TITAN(unit)) { 12360 return FALSE; 12361 } 12362 12363 if (mem != EGR_VLANm) { 12364 return FALSE; 12365 } 12366 12367 soc_trident_pipe_select(unit, TRUE, 1); /* Y pipe */ 12368 *rv = _soc_mem_read(unit, 0, mem, array_index, copyno, index, entry_data_y); 12369 if (SOC_FAILURE(*rv)) { 12370 return TRUE; 12371 } 12372 12373 soc_trident_pipe_select(unit, TRUE, 0); /* X pipe */ 12374 *rv = _soc_mem_read(unit, 0, mem, array_index, copyno, index, entry_data); 12375 if (SOC_FAILURE(*rv)) { 12376 return TRUE; 12377 } 12378 12379 soc_mem_pbmp_field_get(unit, mem, entry_data, PORT_BITMAPf, &pbmp_x); 12380 soc_mem_pbmp_field_get(unit, mem, entry_data_y, PORT_BITMAPf, &pbmp_y); 12381 SOC_PBMP_OR(pbmp_x, pbmp_y); 12382 soc_mem_pbmp_field_set(unit, mem, entry_data, PORT_BITMAPf, &pbmp_x); 12383 soc_mem_pbmp_field_get(unit, mem, entry_data, UT_PORT_BITMAPf, &pbmp_x); 12384 soc_mem_pbmp_field_get(unit, mem, entry_data_y, UT_PORT_BITMAPf, &pbmp_y); 12385 SOC_PBMP_OR(pbmp_x, pbmp_y); 12386 soc_mem_pbmp_field_set(unit, mem, entry_data, UT_PORT_BITMAPf, &pbmp_x); 12387 12388 return TRUE; 12389 #endif /* BCM_TRIDENT_SUPPORT */ 12390 12391 return FALSE; 12392 } 12393 12394 int 12395 soc_mem_array_read_extended(int unit, uint32 flags, 12396 soc_mem_t mem, unsigned array_index, 12397 int copyno, int index, void *entry_data) 12398 { 12399 int rv = SOC_E_NONE; 12400 12401 /* Use user defined callback for access */ 12402 if (SOC_INFO(unit).reg_access.mem_read) { 12403 return SOC_INFO(unit).reg_access.mem_read(unit, mem, array_index, 12404 copyno, index, entry_data); 12405 } 12406 12407 if (_soc_mem_trident_egr_vlan_read(unit, mem, array_index, copyno, index, 12408 entry_data, &rv) == TRUE) { 12409 return rv; 12410 } 12411 12412 return _soc_mem_read(unit, flags, mem, array_index, copyno, index, entry_data); 12413 } 12414 12415 int 12416 soc_mem_read_physical_index(int unit, uint32 flags, soc_mem_t mem, 12417 int copyno, int index, void *entry_data) 12418 { 12419 int rv; 12420 12421 _SOC_MEM_REPLACE_MEM(unit, mem); 12422 12423 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12424 12425 #ifdef BCM_KATANA2_SUPPORT 12426 if (SOC_IS_KATANA2(unit)) { 12427 rv = _soc_mem_read_kt2(unit, mem, copyno, index, entry_data); 12428 } else 12429 #endif 12430 { 12431 rv = soc_mem_array_read_extended(unit, flags, mem, 0, copyno, 12432 index, entry_data); 12433 } 12434 12435 return rv; 12436 } 12437 12438 /* 12439 * Function: soc_mem_array_read 12440 * Purpose: Read a memory array internal to the SOC. 12441 */ 12442 int 12443 soc_mem_array_read(int unit, soc_mem_t mem, unsigned array_index, 12444 int copyno, int index, void *entry_data) 12445 { 12446 int rv = SOC_E_NONE; 12447 12448 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12449 12450 /* Use user defined callback for access */ 12451 if (SOC_INFO(unit).reg_access.mem_read) { 12452 return SOC_INFO(unit).reg_access.mem_read(unit, mem, array_index, 12453 copyno, index, entry_data); 12454 } 12455 12456 if (_soc_mem_trident_egr_vlan_read(unit, mem, array_index, copyno, index, 12457 entry_data, &rv) == TRUE) { 12458 return rv; 12459 } 12460 12461 return _soc_mem_read(unit, 0, mem, array_index, copyno, index, entry_data); 12462 } 12463 12464 /* 12465 * Function: 12466 * soc_mem_read_range 12467 * Purpose: 12468 * Read a range of chip's memory 12469 */ 12470 12471 int 12472 soc_mem_read_range(int unit, soc_mem_t mem, int copyno, 12473 int index_min, int index_max, void *buffer) 12474 { 12475 int rv; 12476 12477 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12478 12479 rv = soc_mem_read_range_multi_cmc(unit, mem, copyno, index_min, index_max, buffer, -1); 12480 12481 return rv; 12482 } 12483 12484 /* 12485 * Function: 12486 * soc_mem_read_range_multi_cmc 12487 * Purpose: 12488 * Read a range of chip's memory 12489 * With multiple CMC/channel support 12490 * Parameters: 12491 * buffer -- Pointer to block of sufficiently large memory. 12492 * Notes: 12493 * Table DMA only works on tables whose entry is less than 12494 * SOC_MEM_DMA_MAX_DATA_BEATS words long. 12495 * 12496 * Table DMA has a minimum transaction size of 4 words, so if the 12497 * table entry is 1 or 2 words, then the count of words is modified 12498 * to keep this alignment. For the remainder of the entries, this 12499 * function reads in the remainder of the data through mem_read 12500 * without using DMA. 12501 */ 12502 12503 int 12504 soc_mem_read_range_multi_cmc(int unit, soc_mem_t mem, int copyno, 12505 int index_min, int index_max, void *buffer, 12506 int vchan) 12507 { 12508 int rc; 12509 int force_cache = 0; 12510 12511 #ifdef SOC_MEM_DEBUG_SPEED 12512 int count = (index_max > index_min) ? 12513 (index_max - index_min + 1) : 12514 (index_min - index_max + 1); 12515 12516 sal_usecs_t start_time; 12517 int diff_time; 12518 12519 start_time = sal_time_usecs(); 12520 #endif 12521 12522 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 12523 force_cache = soc_mem_is_cache_only(unit, mem); 12524 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 12525 12526 /* COVERITY: Intentional, stack use of 4064 bytes */ 12527 /* coverity[stack_use_callee_max : FALSE] */ 12528 /* coverity[stack_use_return : FALSE] */ 12529 12530 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12531 12532 if ((SOC_WARM_BOOT(unit) && SOC_CONTROL(unit)->dma_from_mem_cache) || 12533 (force_cache && !SOC_MEM_TEST_SKIP_CACHE(unit))) { 12534 uint32 *cache; 12535 uint8 *vmap; 12536 int entry_dw, entry_sz, start, indexes; 12537 12538 if (copyno == MEM_BLOCK_ANY) { 12539 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 12540 } 12541 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 12542 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 12543 if ((cache != NULL && force_cache) || 12544 (cache != NULL && CACHE_VMAP_TST(vmap, 0) && 12545 !_SOC_MEM_CHK_L2_MEM(mem) && !SOC_MEM_TEST_SKIP_CACHE(unit))) { 12546 entry_dw = soc_mem_entry_words(unit, mem); 12547 entry_sz = entry_dw * sizeof(uint32); 12548 start = index_min > index_max ? index_max : index_min; 12549 indexes = (index_max > index_min) ? 12550 (index_max - index_min + 1) : (index_min - index_max + 1); 12551 sal_memcpy(buffer, cache + (start * entry_dw), indexes * entry_sz); 12552 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 12553 (BSL_META_U(unit, 12554 "Mem[%s] " 12555 "DMA data from cache.\n"), 12556 SOC_MEM_NAME(unit, mem))); 12557 return SOC_E_NONE; 12558 } 12559 } 12560 rc = soc_mem_array_read_range_multi_cmc(unit, mem, 0, copyno, index_min, 12561 index_max, buffer, vchan); 12562 #ifdef SOC_MEM_DEBUG_SPEED 12563 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 12564 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 12565 (BSL_META_U(unit, 12566 "Total dma read time: %d usecs, [%d nsecs per op]\n"), 12567 diff_time, diff_time*1000/count)); 12568 #endif 12569 return rc; 12570 } 12571 12572 /* 12573 * Function: 12574 * soc_mem_array_read_range 12575 * Purpose: 12576 * Read a range of chip's memory 12577 * Parameters: 12578 * buffer -- Pointer to block of sufficiently large memory. 12579 * For Draco DMA operations, this memory must be 12580 * DMA-able 12581 * Notes: 12582 * Table DMA only works on tables whose entry is less than 12583 * SOC_MEM_DMA_MAX_DATA_BEATS words long. 12584 * 12585 * Table DMA has a minimum transaction size of 4 words, so if the 12586 * table entry is 1 or 2 words, then the count of words is modified 12587 * to keep this alignment. For the remainder of the entries, this 12588 * function reads in the remainder of the data through mem_read 12589 * without using DMA. 12590 */ 12591 12592 int 12593 soc_mem_array_read_range(int unit, soc_mem_t mem, unsigned array_index, 12594 int copyno, int index_min, int index_max, void *buffer) 12595 { 12596 int rv; 12597 12598 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12599 12600 rv = soc_mem_array_read_range_multi_cmc(unit, mem, array_index, 12601 copyno, index_min, index_max, buffer, -1); 12602 12603 return rv; 12604 } 12605 12606 #ifdef BROADCOM_DEBUG 12607 12608 static int soc_dma_debug_property_get(int unit) 12609 { 12610 if (0 == _soc_dma_debug_op[unit]) { 12611 _soc_dma_debug_enable[unit] = 12612 soc_property_get(unit, "dma_mem_debug_enable", 0); 12613 _soc_dma_debug_op[unit] = 1; 12614 } 12615 return _soc_dma_debug_enable[unit]; 12616 } 12617 12618 #endif 12619 12620 /* 12621 * Function: 12622 * soc_mem_array_read_range_multi_cmc 12623 * Purpose: 12624 * Read a range of chip's memory 12625 * With multiple CMC/channel support 12626 */ 12627 12628 int 12629 soc_mem_array_read_range_multi_cmc(int unit, soc_mem_t mem, unsigned array_index, 12630 int copyno, int index_min, int index_max, void *buffer, int vchan) 12631 { 12632 int index; 12633 int count; 12634 void *buf; 12635 uint16 dev_id; 12636 uint8 rev_id; 12637 #ifdef BROADCOM_DEBUG 12638 shared_block_t *p = NULL; 12639 int length = 0; 12640 #endif 12641 #if defined(BCM_SAND_SUPPORT) && !defined(ADAPTER_SERVER_MODE) 12642 int rv; 12643 int entry_dw; 12644 entry_dw = soc_mem_entry_words(unit, mem); 12645 #endif 12646 12647 if (!soc_mem_is_valid(unit, mem)) { 12648 return SOC_E_MEMORY; 12649 } 12650 12651 if (copyno == MEM_BLOCK_ANY) { 12652 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 12653 } 12654 if (copyno == COPYNO_ALL) { 12655 return SOC_E_INTERNAL; 12656 } 12657 12658 soc_cm_get_id(unit, &dev_id, &rev_id); 12659 12660 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12661 12662 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 12663 assert(soc_mem_index_valid(unit, mem, index_min)); 12664 12665 if ((SOC_IS_DEFIP_HOLE_MEM(unit, mem))) { 12666 assert(soc_r2p_defip_mem_index_valid(unit, mem, index_max)); 12667 } else { 12668 assert(soc_mem_index_valid(unit, mem, index_max)); 12669 } 12670 12671 assert(index_min <= index_max); 12672 assert(buffer != NULL); 12673 #ifdef BROADCOM_DEBUG 12674 if (soc_dma_debug_property_get(unit)) { 12675 p = (shared_block_t *) (((char*)buffer) - 12676 ( (((char*)&(((shared_block_t*)0)->user_data[0]))) - ((char*)(shared_block_t*)0) )); 12677 if (soc_cm_shared_good_range(unit, p)) { 12678 if (SHARED_GOOD_START(p) && SHARED_GOOD_END_DEBUG(p)) { 12679 length = WORDS2BYTES(soc_mem_entry_words(unit, mem)) * 12680 (index_max - index_min + 1); 12681 if (length > p->size) { 12682 LOG_WARN(BSL_LS_SOC_SOCMEM, 12683 (BSL_META_U(unit, 12684 "Suspicious DMA length: " 12685 "Desc:%s: Size:%u: length:%u\n"), 12686 p->description, p->size, length)); 12687 } 12688 } 12689 } else if (soc_mem_dmaable(unit, mem, copyno)) { 12690 LOG_ERROR(BSL_LS_SOC_SOCMEM, 12691 (BSL_META_U(unit, 12692 "ERROR:ATTN: Address:%p:" 12693 "probably not in shared memory region \n"), 12694 p)); 12695 } 12696 } 12697 #endif 12698 12699 count = 0; 12700 12701 /* coverity[var_tested_neg : FALSE] */ 12702 LOG_INFO(BSL_LS_SOC_SOCMEM, 12703 (BSL_META_U(unit, 12704 "soc_mem_array_read_range: unit %d memory %s.%s [%d:%d]\n"), 12705 unit, SOC_MEM_UFNAME(unit, mem), 12706 SOC_BLOCK_NAME(unit, copyno), 12707 index_min, index_max)); 12708 12709 /* If device is gone fill buffer with null entries. */ 12710 if (SOC_IS_DETACHING(unit)) { 12711 buf = buffer; 12712 for (index = index_min; index <= index_max; index++, count++) { 12713 buf = soc_mem_table_idx_to_pointer(unit, mem, void *, 12714 buffer, count); 12715 sal_memcpy(buf, soc_mem_entry_null(unit, mem), 12716 soc_mem_entry_bytes(unit, mem)); 12717 } 12718 return (SOC_E_NONE); 12719 } 12720 12721 #if defined(BCM_SAND_SUPPORT) && !defined(ADAPTER_SERVER_MODE) 12722 /* 12723 * Write onto S-Channel "memory read" command packet consisting of header 12724 * word + address word, and read back header word + entry_dw data words. 12725 */ 12726 if ((SOC_IS_SAND(unit)) && (entry_dw + 2 > CMIC_SCHAN_WORDS(unit))) 12727 { 12728 buf = buffer; 12729 for (index = index_min; index <= index_max; index++, count++) 12730 { 12731 buf = soc_mem_table_idx_to_pointer(unit, mem, void*, buffer, count); 12732 rv = _soc_mem_array_wide_read(unit, SOC_MEM_NO_FLAGS, mem, array_index, MEM_BLOCK_ALL, index, buf); 12733 if (SOC_FAILURE(rv)) { 12734 LOG_ERROR(BSL_LS_SOC_COMMON, 12735 (BSL_META_U(unit, 12736 "Read mem %s[%d][%d] error.\n"), 12737 SOC_MEM_NAME(unit, mem), array_index, index)); 12738 } 12739 } 12740 return (SOC_E_NONE); 12741 } 12742 #endif 12743 12744 #if defined(BCM_XGS_SWITCH_SUPPORT) ||\ 12745 defined(BCM_SAND_SUPPORT) 12746 /* coverity[negative_returns : FALSE] */ 12747 if (soc_mem_dmaable(unit, mem, copyno) && (dev_id != BCM56983_DEVICE_ID)) { 12748 #if defined (BCM_XGS3_SWITCH_SUPPORT) ||\ 12749 defined(BCM_SAND_SUPPORT) 12750 12751 if (SOC_IS_XGS3_SWITCH(unit) || 12752 SOC_IS_SAND(unit)) { 12753 int rv; 12754 soc_mem_info_t *meminfo; 12755 12756 meminfo = &SOC_MEM_INFO(unit, mem); 12757 rv = _soc_mem_dma_read(unit, mem, array_index, copyno, index_min, 12758 index_max, 0, buffer, vchan); 12759 12760 if (SOC_FAILURE(rv)) { 12761 if (rv == SOC_E_FAIL && SOC_SER_CORRECTION_SUPPORT(unit)) { 12762 LOG_VERBOSE(BSL_LS_SOC_COMMON, 12763 (BSL_META_U(unit, 12764 "Mem[%s] " 12765 "DMA fallback to pio.\n"), 12766 SOC_MEM_NAME(unit, mem))); 12767 goto _dma_fall_back_pio; 12768 } 12769 return rv; 12770 } 12771 12772 if (NULL != meminfo->snoop_cb) { 12773 if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) { 12774 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ, 12775 copyno, index_min, index_max, buffer, 12776 meminfo->snoop_user_data); 12777 } 12778 if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) { 12779 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT, 12780 copyno, index_min, index_max, buffer, 12781 meminfo->snoop_user_data); 12782 } 12783 } 12784 return SOC_E_NONE; 12785 } 12786 #endif /* BCM_XGS3_SWITCH_SUPPORT || 12787 defined(BCM_88750_SUPPORT) */ 12788 } 12789 _dma_fall_back_pio: 12790 #endif /* (BCM_XGS_SWITCH_SUPPORT) || 12791 defined(BCM_88750_SUPPORT) || 12792 defined(BCM_PETRA_SUPPORT) */ 12793 /* For the rest of entries, do direct read */ 12794 for (index = index_min; index <= index_max; index++, count++) { 12795 12796 if (SOC_DEFIP_HOLE_INDEX_RANGE(unit, mem, index)) { 12797 /* This is not valid index to be read */ 12798 continue; 12799 } 12800 12801 buf = soc_mem_table_idx_to_pointer(unit, mem, void *, 12802 buffer, count); 12803 SOC_IF_ERROR_RETURN(soc_mem_array_read(unit, mem, array_index, copyno, 12804 index, buf)); 12805 } 12806 12807 return SOC_E_NONE; 12808 } 12809 12810 int soc_mem_array_read_flags(int unit, soc_mem_t mem, unsigned array_index, 12811 int copyno, int index, void *entry_data, int flags) 12812 { 12813 int rv, orig_flag; 12814 12815 if (!soc_mem_is_valid(unit, mem)) { 12816 return SOC_E_MEMORY; 12817 } 12818 12819 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12820 12821 orig_flag = SOC_MEM_FORCE_READ_THROUGH(unit); 12822 12823 if(flags & SOC_MEM_DONT_USE_CACHE) { 12824 SOC_MEM_FORCE_READ_THROUGH_SET(unit, 1); 12825 } 12826 12827 rv = soc_mem_array_read_extended(unit, flags, mem, array_index, 12828 copyno, index, entry_data); 12829 12830 SOC_MEM_FORCE_READ_THROUGH_SET(unit, orig_flag); 12831 12832 return rv; 12833 } 12834 12835 /* 12836 * Function: 12837 * soc_mem_ser_read_range 12838 * Purpose: 12839 * Read a range of chip's memory for SER detection 12840 * Parameters: 12841 * buffer -- Pointer to block of sufficiently large memory. 12842 * Notes: 12843 * Table DMA only works on tables whose entry is less than 12844 * SOC_MEM_DMA_MAX_DATA_BEATS words long. 12845 * 12846 * Table DMA has a minimum transaction size of 4 words, so if the 12847 * table entry is 1 or 2 words, then the count of words is modified 12848 * to keep this alignment. For the remainder of the entries, this 12849 * function reads in the remainder of the data through mem_read 12850 * without using DMA. 12851 */ 12852 int 12853 soc_mem_ser_read_range(int unit, soc_mem_t mem, int copyno, 12854 int index_min, int index_max, uint32 ser_flags, 12855 void *buffer) 12856 { 12857 int rv, index, pipe_acc, count; 12858 void *buf; 12859 if (!soc_mem_is_valid(unit, mem)) { 12860 return SOC_E_MEMORY; 12861 } 12862 12863 if (copyno == MEM_BLOCK_ANY) { 12864 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 12865 } 12866 if (copyno == COPYNO_ALL) { 12867 return SOC_E_INTERNAL; 12868 } 12869 12870 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 12871 12872 /* Skip assertions here because they should have been checked 12873 * during mem scan init. */ 12874 assert(buffer != NULL); 12875 12876 if (0 == (ser_flags & _SOC_SER_FLAG_NO_DMA)) { 12877 rv = _soc_mem_dma_read(unit, mem, 0, copyno, index_min, 12878 index_max, ser_flags, buffer, -1); 12879 } else { 12880 /* Trigger the slow path iteration below */ 12881 rv = SOC_E_FAIL; 12882 } 12883 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 12884 if (SOC_E_NONE == rv) { 12885 _soc_mem_fp_global_mask_tcam_shift(unit, mem, buffer, 0, 12886 index_max - index_min); 12887 } 12888 #endif 12889 12890 if (SOC_E_FAIL == rv) { 12891 if (ser_flags & _SOC_SER_FLAG_DMA_ERR_RETURN) { 12892 return rv; 12893 } 12894 /* Scan the table by individual reads to trigger SER correction */ 12895 pipe_acc = (ser_flags & _SOC_SER_FLAG_ACC_TYPE_MASK); 12896 count = 0; 12897 for (index = index_min; index <= index_max; index++, count++) { 12898 12899 buf = soc_mem_table_idx_to_pointer(unit, mem, void *, 12900 buffer, count); 12901 if (0 != (ser_flags & _SOC_SER_FLAG_MULTI_PIPE)) { 12902 /* For multiple-pipe devices, soc_mem_pipe_select_read 12903 * expects a non-zero acc_type parameter. 12904 * If _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y is not configured, 12905 * A default acc_type should be specified. 12906 */ 12907 if ((pipe_acc == 0) && 12908 !(soc_feature(unit, 12909 soc_feature_unique_acc_type_access))) { 12910 12911 pipe_acc = SOC_MEM_ACC_TYPE(unit, mem); 12912 } 12913 if (0 != (ser_flags & _SOC_SER_FLAG_XY_READ)) { 12914 rv = soc_mem_pipe_select_read(unit, SOC_MEM_DONT_CONVERT_XY2DM, 12915 mem, copyno, pipe_acc, index, buf); 12916 } else { 12917 rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS, 12918 mem, copyno, pipe_acc, index, buf); 12919 } 12920 12921 } else { 12922 #ifdef BCM_TRIDENT_SUPPORT 12923 if ((SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) && 12924 (mem == EGR_VLANm)) { 12925 rv = soc_mem_array_read(unit, mem, 0, copyno, index, buf); 12926 } else 12927 #endif 12928 { 12929 if (0 != (ser_flags & _SOC_SER_FLAG_XY_READ)) { 12930 rv = soc_mem_read_extended(unit, 12931 SOC_MEM_DONT_CONVERT_XY2DM | SOC_MEM_DONT_USE_CACHE, 12932 mem, 0, copyno, index, buf); 12933 } else { 12934 rv = soc_mem_read_extended(unit, SOC_MEM_DONT_USE_CACHE, 12935 mem, 0, copyno, index, buf); 12936 } 12937 } 12938 } 12939 if (SOC_E_FAIL == rv) { 12940 /* We're expecting this to fail, that triggers the 12941 * correction logic. */ 12942 rv = SOC_E_NONE; 12943 } else if (SOC_FAILURE(rv)) { 12944 return rv; 12945 } 12946 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 12947 _soc_mem_fp_global_mask_tcam_shift(unit, mem, buf, 0, 0); 12948 #endif 12949 } 12950 rv = SOC_E_NONE; 12951 } 12952 12953 return rv; 12954 } 12955 12956 #ifdef BCM_ESW_SUPPORT 12957 /* 12958 * Function: 12959 * soc_mem_is_dynamic 12960 * Purpose: 12961 * Determine if a memory contains fields that will be updated by hardware. 12962 * Parameters: 12963 * Notes: 12964 * N/A 12965 */ 12966 int 12967 soc_mem_is_dynamic(int unit, soc_mem_t mem) 12968 { 12969 if (SOC_MEM_FIELD_VALID(unit, mem, PARITYf)|| 12970 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITYf)|| 12971 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_0f)|| 12972 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_1f)|| 12973 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_2f)|| 12974 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_3f)|| 12975 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_Af)|| 12976 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_Bf)|| 12977 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_LOWERf)|| 12978 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_UPPERf)|| 12979 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P0f)|| 12980 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P1f)|| 12981 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P2f)|| 12982 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P3f)|| 12983 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P0f)|| 12984 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P1f)|| 12985 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P2f)|| 12986 SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P3f)|| 12987 SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P0f)|| 12988 SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P1f)|| 12989 SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P2f)|| 12990 SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P3f)|| 12991 SOC_MEM_FIELD_VALID(unit, mem, ECCf)|| 12992 SOC_MEM_FIELD_VALID(unit, mem, ECC_FIELDf)|| 12993 SOC_MEM_FIELD_VALID(unit, mem, ECC_0f)|| 12994 SOC_MEM_FIELD_VALID(unit, mem, ECC_1f)|| 12995 SOC_MEM_FIELD_VALID(unit, mem, ECC_2f)|| 12996 SOC_MEM_FIELD_VALID(unit, mem, ECC_3f)|| 12997 SOC_MEM_FIELD_VALID(unit, mem, ECC_4f)|| 12998 SOC_MEM_FIELD_VALID(unit, mem, ECCPf)|| 12999 SOC_MEM_FIELD_VALID(unit, mem, ECCP0f)|| 13000 SOC_MEM_FIELD_VALID(unit, mem, ECCP1f)|| 13001 SOC_MEM_FIELD_VALID(unit, mem, ECCP2f)|| 13002 SOC_MEM_FIELD_VALID(unit, mem, ECCP3f)|| 13003 SOC_MEM_FIELD_VALID(unit, mem, ECCP4f)|| 13004 SOC_MEM_FIELD_VALID(unit, mem, ECCP5f)|| 13005 SOC_MEM_FIELD_VALID(unit, mem, ECCP7f) || 13006 SOC_MEM_FIELD_VALID(unit, mem, ECCP_0f) || 13007 SOC_MEM_FIELD_VALID(unit, mem, ECCP_1f) || 13008 SOC_MEM_FIELD_VALID(unit, mem, ECCP_2f) || 13009 SOC_MEM_FIELD_VALID(unit, mem, ECCP_3f) || 13010 SOC_MEM_FIELD_VALID(unit, mem, ECCP_4f) || 13011 SOC_MEM_FIELD_VALID(unit, mem, ECC0f) || 13012 SOC_MEM_FIELD_VALID(unit, mem, ECC1f) || 13013 SOC_MEM_FIELD_VALID(unit, mem, ECC2f) || 13014 SOC_MEM_FIELD_VALID(unit, mem, ECC3f) || 13015 SOC_MEM_FIELD_VALID(unit, mem, PARITY0f) || 13016 SOC_MEM_FIELD_VALID(unit, mem, PARITY1f) || 13017 SOC_MEM_FIELD_VALID(unit, mem, PARITY2f) || 13018 SOC_MEM_FIELD_VALID(unit, mem, PARITY3f) || 13019 SOC_MEM_FIELD_VALID(unit, mem, PARITY_0f) || 13020 SOC_MEM_FIELD_VALID(unit, mem, PARITY_1f) || 13021 SOC_MEM_FIELD_VALID(unit, mem, PARITY_2f) || 13022 SOC_MEM_FIELD_VALID(unit, mem, PARITY_3f) || 13023 SOC_MEM_FIELD_VALID(unit, mem, PARITY_4f) || 13024 SOC_MEM_FIELD_VALID(unit, mem, HITf) || 13025 SOC_MEM_FIELD_VALID(unit, mem, HIT0f) || 13026 SOC_MEM_FIELD_VALID(unit, mem, HIT1f) || 13027 SOC_MEM_FIELD_VALID(unit, mem, HIT_0f) || 13028 SOC_MEM_FIELD_VALID(unit, mem, HIT_1f) || 13029 SOC_MEM_FIELD_VALID(unit, mem, HIT_2f) || 13030 SOC_MEM_FIELD_VALID(unit, mem, HIT_3f) || 13031 SOC_MEM_FIELD_VALID(unit, mem, HITDA_0f) || 13032 SOC_MEM_FIELD_VALID(unit, mem, HITDA_1f) || 13033 SOC_MEM_FIELD_VALID(unit, mem, HITDA_2f) || 13034 SOC_MEM_FIELD_VALID(unit, mem, HITDA_3f) || 13035 SOC_MEM_FIELD_VALID(unit, mem, HITSA_0f) || 13036 SOC_MEM_FIELD_VALID(unit, mem, HITSA_1f) || 13037 SOC_MEM_FIELD_VALID(unit, mem, HITSA_2f) || 13038 SOC_MEM_FIELD_VALID(unit, mem, HITSA_3f) || 13039 SOC_MEM_FIELD_VALID(unit, mem, HITSAf) || 13040 SOC_MEM_FIELD_VALID(unit, mem, HITDAf) || 13041 SOC_MEM_FIELD_VALID(unit, mem, B0_HITf) || 13042 SOC_MEM_FIELD_VALID(unit, mem, B1_HITf) || 13043 SOC_MEM_FIELD_VALID(unit, mem, L3_HIT_DCMf) || 13044 SOC_MEM_FIELD_VALID(unit, mem, L3_HIT_PMf) || 13045 SOC_MEM_FIELD_VALID(unit, mem, HIT_BITSf) || 13046 SOC_MEM_FIELD_VALID(unit, mem, BUCKETCOUNTf) || 13047 SOC_MEM_FIELD_VALID(unit, mem, REFRESHCOUNTf) || 13048 SOC_MEM_FIELD_VALID(unit, mem, ECCP_P0f) || 13049 SOC_MEM_FIELD_VALID(unit, mem, ECCP_P1f) || 13050 SOC_MEM_FIELD_VALID(unit, mem, ECCP_P2f) || 13051 SOC_MEM_FIELD_VALID(unit, mem, ECCP_P3f) || 13052 SOC_MEM_FIELD_VALID(unit, mem, ECC_P0f)|| 13053 SOC_MEM_FIELD_VALID(unit, mem, ECC_P1f)|| 13054 SOC_MEM_FIELD_VALID(unit, mem, ECC_P2f)|| 13055 SOC_MEM_FIELD_VALID(unit, mem, ECC_P3f)|| 13056 SOC_MEM_FIELD_VALID(unit, mem, PARITY_P0f) || 13057 SOC_MEM_FIELD_VALID(unit, mem, PARITY_P1f) || 13058 SOC_MEM_FIELD_VALID(unit, mem, PARITY_P2f) || 13059 SOC_MEM_FIELD_VALID(unit, mem, PARITY_P3f) || 13060 SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_0f) || 13061 SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_1f) || 13062 SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_2f) || 13063 SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_3f) || 13064 SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_0f) || 13065 SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_1f) || 13066 SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_2f) || 13067 SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_3f) || 13068 SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_0f) || 13069 SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_1f) || 13070 SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_2f) || 13071 SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_3f)) { 13072 return TRUE; 13073 } 13074 return FALSE; 13075 } 13076 #endif 13077 13078 #if defined(BCM_XGS3_SWITCH_SUPPORT) 13079 #ifdef BCM_WARM_BOOT_SUPPORT 13080 /* 13081 * Function: 13082 * soc_scache_mem_read_range 13083 * Purpose: 13084 * Read a range of chip's memory used for L2 Warm Boot 13085 * Parameters: 13086 * buffer -- Pointer to block of sufficiently large memory. 13087 * For DMA operations, this memory must be 13088 * DMA-able 13089 * Notes: 13090 * This function is only used for DMA'ing the scache from the 13091 * chip's internal memory. 13092 */ 13093 13094 STATIC int 13095 soc_scache_mem_read_range(int unit, soc_mem_t mem, int copyno, 13096 int index_min, int index_max, void *buffer) 13097 { 13098 int index; 13099 int count; 13100 void *buf; 13101 soc_mem_info_t *meminfo; 13102 unsigned int array_index = 0; 13103 13104 if (!soc_mem_is_valid(unit, mem)) { 13105 return SOC_E_MEMORY; 13106 } 13107 13108 if (copyno == MEM_BLOCK_ANY) { 13109 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 13110 } 13111 if (copyno == COPYNO_ALL) { 13112 return SOC_E_INTERNAL; 13113 } 13114 13115 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 13116 assert(buffer != NULL); 13117 13118 meminfo = &SOC_MEM_INFO(unit, mem); 13119 count = 0; 13120 13121 /* coverity[var_tested_neg : FALSE] */ 13122 LOG_INFO(BSL_LS_SOC_SOCMEM, 13123 (BSL_META_U(unit, 13124 "soc_scache_mem_read_range: unit %d memory %s.%s [%d:%d]\n"), 13125 unit, SOC_MEM_UFNAME(unit, mem), 13126 SOC_BLOCK_NAME(unit, copyno), 13127 index_min, index_max)); 13128 13129 /* If device is gone fill buffer with null entries. */ 13130 if (SOC_IS_DETACHING(unit)) { 13131 buf = buffer; 13132 for (index = index_min; index <= index_max; index++, count++) { 13133 buf = soc_mem_table_idx_to_pointer(unit, mem, void *, 13134 buffer, count); 13135 sal_memcpy(buf, soc_mem_entry_null(unit, mem), 13136 soc_mem_entry_bytes(unit, mem)); 13137 } 13138 return (SOC_E_NONE); 13139 } 13140 13141 /* coverity[negative_returns : FALSE] */ 13142 if (soc_mem_dmaable(unit, mem, copyno)) { 13143 if (SOC_IS_XGS3_SWITCH(unit)) { 13144 13145 SOC_IF_ERROR_RETURN 13146 (_soc_mem_dma_read(unit, mem, array_index, copyno, 13147 index_min, index_max, 0, buffer, -1)); 13148 13149 if (NULL != meminfo->snoop_cb) { 13150 if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) { 13151 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ, 13152 copyno, index_min, index_max, buffer, 13153 meminfo->snoop_user_data); 13154 } 13155 if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) { 13156 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT, 13157 copyno, index_min, index_max, buffer, 13158 meminfo->snoop_user_data); 13159 } 13160 } 13161 } 13162 } 13163 return SOC_E_NONE; 13164 } 13165 13166 /* 13167 * Function: 13168 * soc_scache_mem_write_range 13169 * Purpose: 13170 * Write a range of chip's memory used for L2 Warm Boot 13171 * Parameters: 13172 * buffer -- Pointer to block of sufficiently large memory. 13173 * For slam operations, this memory must be 13174 * slammable 13175 * Notes: 13176 * This function is only used for slamming the scache to the 13177 * chip's internal memory. 13178 */ 13179 STATIC int 13180 soc_scache_mem_write_range(int unit, soc_mem_t mem, int copyno, 13181 int index_min, int index_max, void *buffer) 13182 { 13183 uint32 entry_dw; 13184 int i, rv = SOC_E_NONE; 13185 soc_mem_info_t *meminfo; 13186 void *cache_buffer = NULL; 13187 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 13188 || defined(BCM_HURRICANE2_SUPPORT) 13189 int count, alloc_size; 13190 #endif 13191 uint32 *cache; 13192 13193 if (!soc_mem_is_valid(unit, mem)) { 13194 return SOC_E_MEMORY; 13195 } 13196 13197 meminfo = &SOC_MEM_INFO(unit, mem); 13198 entry_dw = soc_mem_entry_words(unit, mem); 13199 13200 LOG_INFO(BSL_LS_SOC_SOCMEM, 13201 (BSL_META_U(unit, 13202 "soc_scache_mem_write_range: unit %d memory %s.%s [%d:%d]\n"), 13203 unit, SOC_MEM_UFNAME(unit, mem), 13204 SOC_BLOCK_NAME(unit, copyno), 13205 index_min, index_max)); 13206 13207 /* coverity[negative_returns : FALSE] */ 13208 if (SOC_IS_XGS3_SWITCH(unit) && soc_mem_slamable(unit, mem, copyno)) { 13209 int blk; 13210 13211 if (copyno == COPYNO_ALL) { 13212 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 13213 copyno = blk; 13214 break; 13215 } 13216 } 13217 if (copyno == COPYNO_ALL) { 13218 return SOC_E_INTERNAL; 13219 } 13220 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 13221 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 13222 || defined(BCM_HURRICANE2_SUPPORT) 13223 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit) && 13224 (soc_feature(unit, soc_feature_xy_tcam) && 13225 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 13226 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM)))) { 13227 if (index_min > index_max) { 13228 count = index_min - index_max + 1; 13229 } else { 13230 count = index_max - index_min + 1; 13231 } 13232 alloc_size = count * entry_dw * sizeof(uint32); 13233 cache_buffer = sal_alloc(alloc_size, "cache buffer"); 13234 if (cache_buffer == NULL) { 13235 return SOC_E_MEMORY; 13236 } 13237 } 13238 #endif 13239 MEM_LOCK(unit, mem); 13240 rv = _soc_mem_dma_write(unit, 0, mem, 0, copyno, index_min, index_max, 13241 buffer, cache_buffer, -1); 13242 if (rv >= 0) { 13243 uint8 *vmap, *vmap1 = NULL; 13244 /* coverity[negative_returns : FALSE] */ 13245 /* coverity[negative_returns] */ 13246 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 13247 if (_SOC_MEM_CHK_L2_MEM(mem)) { 13248 if (mem == L2_ENTRY_1m) { 13249 vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno]; 13250 } else if (mem == L2_ENTRY_2m) { 13251 vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno]; 13252 } 13253 } 13254 13255 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 13256 sal_memcpy(cache + index_min * entry_dw, cache_buffer ? 13257 cache_buffer : buffer, 13258 (index_max - index_min + 1) * entry_dw * 4); 13259 for (i = index_min; i <= index_max; i++) { 13260 if (vmap1) { 13261 CACHE_VMAP_CLR(vmap, i); 13262 if (mem == L2_ENTRY_1m) { 13263 CACHE_VMAP_CLR(vmap1, i/2); 13264 } else { 13265 CACHE_VMAP_CLR(vmap1, i*2); 13266 CACHE_VMAP_CLR(vmap1, i*2 + 1); 13267 } 13268 } else { 13269 CACHE_VMAP_SET(vmap, i); 13270 } 13271 } 13272 #ifdef BCM_TRX_SUPPORT 13273 _soc_mem_aggr_cache_update(unit, mem, copyno, 0, 13274 index_min, index_max, 0, buffer); 13275 #endif /* BCM_TRX_SUPPORT */ 13276 } 13277 } 13278 MEM_UNLOCK(unit, mem); 13279 if (NULL != meminfo->snoop_cb) { 13280 if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) { 13281 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE, 13282 copyno, index_min, index_max, buffer, 13283 meminfo->snoop_user_data); 13284 } 13285 if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) { 13286 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT, 13287 copyno, index_min, index_max, buffer, 13288 meminfo->snoop_user_data); 13289 } 13290 } 13291 13292 if (cache_buffer) { 13293 sal_free(cache_buffer); 13294 } 13295 } 13296 return rv; 13297 } 13298 13299 int 13300 soc_scache_esw_nh_mem_write(int unit, uint8 *buf, int offset, int nbytes) 13301 { 13302 int num_entries, bytes2, rv = SOC_E_NONE; 13303 int stable_size; 13304 uint32 stable_index_max, stable_index_min; 13305 int i, j, bufptr; 13306 uint8 *buf2; 13307 int start, end; 13308 int scache_offset; 13309 uint8 mask[SOC_MAX_MEM_BYTES]; 13310 uint32 l3_next_hop_size = soc_mem_entry_bytes(unit, EGR_L3_NEXT_HOPm) * 13311 soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 13312 13313 SOC_IF_ERROR_RETURN( 13314 soc_stable_tmp_access(unit, sf_index_min, &stable_index_min, TRUE)); 13315 SOC_IF_ERROR_RETURN( 13316 soc_stable_tmp_access(unit, sf_index_max, &stable_index_max, TRUE)); 13317 SOC_IF_ERROR_RETURN( 13318 soc_stable_size_get(unit, &stable_size)); 13319 13320 bytes2 = soc_mem_entry_words(unit, EGR_L3_NEXT_HOPm) * sizeof(uint32); 13321 num_entries = stable_index_max - stable_index_min + 1; 13322 13323 start = stable_index_min + offset / (bytes2); 13324 13325 scache_offset = offset % (bytes2); 13326 end = start + (nbytes + scache_offset + bytes2 - 1) / (bytes2); 13327 if (stable_index_max < end) { 13328 LOG_ERROR(BSL_LS_SOC_SOCMEM, 13329 (BSL_META_U(unit, 13330 "Stable max index(%d) is less than buffer end(%d)\n"), 13331 stable_index_max, end)); 13332 return SOC_E_INTERNAL; 13333 } 13334 if (stable_size > l3_next_hop_size) { 13335 LOG_ERROR(BSL_LS_SOC_SOCMEM, 13336 (BSL_META_U(unit, 13337 "Stable size(%d) is larger than size of memory EGR_L3_NEXT_HOPm(%d)\n"), 13338 stable_size, l3_next_hop_size)); 13339 return SOC_E_INTERNAL; 13340 } 13341 buf2 = NULL; 13342 /* Allocate slammable memory */ 13343 buf2 = soc_cm_salloc(unit, bytes2 * num_entries, "EGR_L3_NEXT_HOP buffer"); 13344 if (NULL == buf2) { 13345 rv = SOC_E_MEMORY; 13346 goto cleanup; 13347 } 13348 sal_memset(buf2, 0, bytes2 * num_entries); 13349 13350 /* Copy the buffer to the individual memories */ 13351 bufptr = 0; 13352 sal_memset(mask, 0, SOC_MAX_MEM_BYTES); 13353 soc_mem_datamask_get(unit, EGR_L3_NEXT_HOPm, (uint32 *)mask); 13354 13355 SOC_IF_ERROR_RETURN 13356 (soc_scache_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 13357 start, start, buf2)); 13358 if (start != end) { 13359 SOC_IF_ERROR_RETURN 13360 (soc_scache_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 13361 end, end, buf2 + end * bytes2)); 13362 } 13363 13364 for (i = 0; i <= (end - start); i++) { 13365 if (bufptr < stable_size) { 13366 for (j = (i == 0) ? scache_offset : 0; j < SOC_MAX_MEM_BYTES; j++) { 13367 if (mask[j] != 0xff) { 13368 continue; 13369 } 13370 /* 13371 sal_memcpy(buf2 + (i - stable_index_min) * bytes2 + j, 13372 (buf + bufptr), 1); 13373 */ 13374 *(buf2 + i * bytes2 + j) = *(buf + bufptr); 13375 bufptr++; 13376 } 13377 } 13378 } 13379 13380 rv = soc_scache_mem_write_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 13381 start, end, buf2); 13382 cleanup: 13383 if (buf2 != NULL) { 13384 soc_cm_sfree(unit, buf2); 13385 } 13386 return rv; 13387 } 13388 13389 int 13390 soc_scache_esw_nh_mem_read(int unit, uint8 *buf, int offset, int nbytes) 13391 { 13392 int i, num_entries, bytes2, rv = SOC_E_NONE; 13393 int j, bufptr; 13394 int stable_size; 13395 uint32 stable_index_min, stable_index_max; 13396 uint8 *buf2; 13397 int start, end; 13398 int scache_offset; 13399 uint8 mask[SOC_MAX_MEM_BYTES]; 13400 uint32 l3_next_hop_size = soc_mem_entry_bytes(unit, EGR_L3_NEXT_HOPm) * 13401 soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 13402 13403 SOC_IF_ERROR_RETURN( 13404 soc_stable_tmp_access(unit, sf_index_min, &stable_index_min, TRUE)); 13405 SOC_IF_ERROR_RETURN( 13406 soc_stable_tmp_access(unit, sf_index_max, &stable_index_max, TRUE)); 13407 SOC_IF_ERROR_RETURN( 13408 soc_stable_size_get(unit, &stable_size)); 13409 13410 bytes2 = soc_mem_entry_words(unit, EGR_L3_NEXT_HOPm) * sizeof(uint32); 13411 num_entries = stable_index_max - stable_index_min + 1; 13412 13413 buf2 = NULL; 13414 start = stable_index_min + offset / (bytes2); 13415 13416 scache_offset = offset % (bytes2); 13417 end = start + (nbytes + scache_offset + bytes2 - 1) / (bytes2); 13418 if (stable_index_max < end) { 13419 LOG_ERROR(BSL_LS_SOC_SOCMEM, 13420 (BSL_META_U(unit, 13421 "Stable max index(%d) is less than buffer end(%d)\n"), 13422 stable_index_max, end)); 13423 return SOC_E_INTERNAL; 13424 } 13425 if (stable_size > l3_next_hop_size) { 13426 LOG_ERROR(BSL_LS_SOC_SOCMEM, 13427 (BSL_META_U(unit, 13428 "Stable size(%d) is larger than size of memory EGR_L3_NEXT_HOPm(%d)\n"), 13429 stable_size, l3_next_hop_size)); 13430 return SOC_E_INTERNAL; 13431 } 13432 /* Allocate DMA'able memory */ 13433 buf2 = soc_cm_salloc(unit, bytes2 * num_entries, "EGR_L3_NEXT_HOP buffer"); 13434 if (NULL == buf2) { 13435 rv = SOC_E_MEMORY; 13436 goto cleanup; 13437 } 13438 sal_memset(buf2, 0, bytes2 * num_entries); 13439 13440 /* DMA the tables */ 13441 rv = soc_scache_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 13442 stable_index_min, stable_index_max, buf2); 13443 13444 /* Copy out the individual buffers to the scache buffer */ 13445 bufptr = 0; 13446 sal_memset(mask, 0, SOC_MAX_MEM_BYTES); 13447 soc_mem_datamask_get(unit, EGR_L3_NEXT_HOPm, (uint32 *)mask); 13448 for (i = 0; i <= (end - start); i++) { 13449 if (bufptr < stable_size) { 13450 for (j = (i == 0) ? scache_offset : 0; j < SOC_MAX_MEM_BYTES; j++) { 13451 if (mask[j] != 0xff) { 13452 continue; 13453 } 13454 /* 13455 sal_memcpy((buf + offset + bufptr), 13456 buf2 + (i - stable_index_min) * bytes2 + j, 1); 13457 */ 13458 *(buf + bufptr) = *(buf2 + i * bytes2 + j); 13459 bufptr++; 13460 } 13461 } 13462 } 13463 cleanup: 13464 if (buf2 != NULL) { 13465 soc_cm_sfree(unit, buf2); 13466 } 13467 return rv; 13468 } 13469 #endif /* BCM_WARM_BOOT_SUPPORT */ 13470 #endif /* defined(BCM_XGS3_SWITCH_SUPPORT) */ 13471 13472 /* 13473 * Function: _soc_mem_write_ext_cache_set 13474 * 13475 * Purpose: Called by _soc_mem_write_extended(). Check for the no-cache flag 13476 * and set no_cache and index accordingly. 13477 * 13478 * Returns: Nothing, but sets no_cache and may alter index 13479 */ 13480 STATIC void 13481 _soc_mem_write_ext_cache_set(uint32 flags, int *index, int *no_cache) 13482 { 13483 if ((flags & SOC_MEM_DONT_USE_CACHE) == SOC_MEM_DONT_USE_CACHE) { 13484 *no_cache = 1; 13485 } else { 13486 *no_cache = 0; 13487 } 13488 13489 /*Legacy nocache handling*/ 13490 if (*index < 0) { 13491 *no_cache = 1; 13492 *index = -*index; 13493 } 13494 } 13495 13496 /* 13497 * Function: _soc_mem_hercules_write_attempt 13498 * 13499 * Purpose: Called by _soc_mem_write_extended(). If the unit is a hercules, 13500 * redirect the request to the hercules mem write handler. 13501 * 13502 * Returns: TRUE if the request was intercepted and handled by hercules 13503 * FALSE if the request should proceed normally 13504 */ 13505 STATIC int 13506 _soc_mem_hercules_write_attempt(int unit, soc_mem_t mem, int copyno, int index, 13507 void *entry_data, int *rv) 13508 { 13509 #ifdef BCM_HERCULES_SUPPORT 13510 /* Handle Hercules' word read tables separately */ 13511 if (SOC_IS_HERCULES(unit) && 13512 (soc_mem_flags(unit, mem) & SOC_MEM_FLAG_WORDADR)) { 13513 *rv = soc_hercules_mem_write(unit, mem, copyno, index, entry_data); 13514 return TRUE; 13515 } 13516 #endif /* BCM_HERCULES_SUPPORT */ 13517 13518 return FALSE; 13519 } 13520 13521 void * 13522 soc_mem_write_tcam_to_hw_format(int unit, soc_mem_t mem, void *entry_data, 13523 uint32 *cache_entry_data, 13524 uint32 *converted_entry_data) 13525 { 13526 void *entry_data_ptr = entry_data; 13527 13528 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 13529 || defined(BCM_HURRICANE2_SUPPORT) 13530 13531 soc_mem_info_t *meminfo = &SOC_MEM_INFO(unit, mem); 13532 if (soc_feature(unit, soc_feature_xy_tcam) && 13533 (meminfo->flags & SOC_MEM_FLAG_CAM) && 13534 (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM))) { 13535 13536 entry_data_ptr = converted_entry_data; 13537 _soc_mem_tcam_dm_to_xy(unit, mem, 1, entry_data, entry_data_ptr, 13538 cache_entry_data); 13539 } 13540 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 13541 13542 return entry_data_ptr; 13543 } 13544 13545 /* 13546 * Function: _soc_mem_write_sanity_check 13547 * 13548 * Purpose: Called by _soc_mem_write_extended(). Check mem/index parameters 13549 * for basic validity. 13550 * 13551 * Returns: SOC_E_xxx 13552 */ 13553 STATIC int 13554 _soc_mem_write_sanity_check(int unit, uint32 flags, soc_mem_t mem, 13555 int index) 13556 { 13557 soc_mem_info_t *meminfo = &SOC_MEM_INFO(unit, mem); 13558 int entry_num_max = 0; 13559 13560 if (!soc_mem_is_valid(unit, mem)) { 13561 return SOC_E_MEMORY; 13562 } 13563 13564 /* 13565 * When checking index, check for 0 instead of soc_mem_index_min. 13566 * Diagnostics need to read/write index 0 of Strata ARL and GIRULE. 13567 */ 13568 13569 if (!(flags & SOC_MEM_DONT_CHECK_INDEX)) { 13570 if ((flags & SOC_MEM_DONT_MAP_INDEX) && 13571 (mem == L3_DEFIPm || 13572 mem == L3_DEFIP_LEVEL1m || 13573 mem == L3_DEFIP_ONLYm || 13574 mem == L3_DEFIP_DATA_ONLYm || 13575 mem == L3_DEFIP_HIT_ONLY_Xm || 13576 mem == L3_DEFIP_HIT_ONLY_Ym || 13577 mem == L3_DEFIP_HIT_ONLYm || 13578 mem == L3_DEFIP_PAIR_128m || 13579 mem == L3_DEFIP_PAIR_LEVEL1m || 13580 mem == L3_DEFIP_PAIR_128_ONLYm || 13581 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 13582 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 13583 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 13584 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 13585 if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) { 13586 return SOC_E_PARAM; 13587 } 13588 } else { 13589 entry_num_max = soc_mem_index_max(unit, mem); 13590 13591 if (index < 0 || index > entry_num_max) { 13592 if (!(SOC_DEFIP_HOLE_RANGE_CHECK(unit, mem, index))) { 13593 LOG_WARN(BSL_LS_SOC_SOCMEM, 13594 (BSL_META_U(unit, 13595 "soc_mem_write: invalid index %d for memory %s\n"), 13596 index, SOC_MEM_NAME(unit, mem))); 13597 return SOC_E_PARAM; 13598 } 13599 } 13600 } 13601 } 13602 13603 if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) { 13604 LOG_WARN(BSL_LS_SOC_SOCMEM, 13605 (BSL_META_U(unit, 13606 "soc_mem_write: invalid index %d for memory %s\n"), 13607 index, SOC_MEM_NAME(unit, mem))); 13608 return SOC_E_PARAM; 13609 } 13610 13611 if (meminfo->flags & SOC_MEM_FLAG_READONLY) { 13612 LOG_ERROR(BSL_LS_SOC_SOCMEM, 13613 (BSL_META_U(unit, 13614 "soc_mem_write: attempt to write R/O memory %s\n"), 13615 SOC_MEM_NAME(unit, mem))); 13616 return SOC_E_INTERNAL; 13617 } 13618 13619 return SOC_E_NONE; 13620 } 13621 13622 /* 13623 * soc_mem_write_copyno_update 13624 * 13625 * Called from within soc_mem_write. When writing to Arad, the writer must 13626 * select which core is being written to. If SOC_CORE_ALL or COPYNO_ALL is 13627 * selected, then override the copyno variable to use broadcast registers 13628 * instead of iterating and writing to each separately. 13629 * 13630 * Returns SOC_E_xxx 13631 */ 13632 int 13633 soc_mem_write_copyno_update(int unit, soc_mem_t mem, int *copyno, 13634 int *copyno_override) 13635 { 13636 int rv = SOC_E_NONE; 13637 13638 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 13639 /* Use core broadcast writes when possible for more efficient writes */ 13640 if ((SOC_IS_ARAD(unit) || SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) 13641 && (*copyno == SOC_CORE_ALL || *copyno == COPYNO_ALL || SOC_BLOCK_IS_BROADCAST(unit, *copyno))) { 13642 *copyno_override = soc_mem_broadcast_block_get(unit, mem); 13643 if (*copyno_override == SOC_CORE_ALL) { 13644 *copyno_override = 0; 13645 } 13646 if (!*copyno_override) { 13647 *copyno = COPYNO_ALL; 13648 } 13649 } else 13650 #endif /* BCM_PETRA_SUPPORT */ 13651 13652 if (*copyno == SOC_CORE_ALL) { 13653 *copyno = COPYNO_ALL; 13654 } else if (*copyno != COPYNO_ALL) { 13655 if (!SOC_MEM_BLOCK_VALID(unit, mem, *copyno)) { 13656 LOG_WARN(BSL_LS_SOC_SOCMEM, 13657 (BSL_META_U(unit, 13658 "soc_mem_write: invalid block %d for memory %s\n"), 13659 *copyno, SOC_MEM_NAME(unit, mem))); 13660 rv = SOC_E_PARAM; 13661 } 13662 } 13663 13664 return rv; 13665 } 13666 13667 #ifdef BCM_TRIDENT_SUPPORT 13668 /* 13669 * Function: _soc_mem_write_instances_cache_update 13670 * 13671 * Purpose: If this mem view has several physical instances, 13672 * they need to be updated accordingly. 13673 * 13674 * Returns: None 13675 */ 13676 STATIC void 13677 _soc_mem_write_instances_cache_update(int unit, soc_mem_t mem, 13678 int blk, int no_cache, 13679 int index_min, int index_max, 13680 int array_index, void *entry_data) 13681 { 13682 soc_mem_t mem_cp[SOC_MEM_CP_MAX_NUM]; 13683 int i; 13684 13685 /* Tomahawk 3 has shadow memories that are updated when the main memory 13686 * is updated. Since these memories are automatically updated, we also 13687 * need to update the cache for these memories 13688 */ 13689 if (SOC_IS_TOMAHAWK3(unit)) { 13690 if (mem == MMU_THDO_CONFIG_UC_QGROUP0m) { 13691 mem_cp[0] = MMU_THDO_CONFIG_UC_QGROUP1m; 13692 mem_cp[1] = MMU_THDO_CONFIG_UC_QGROUP2m; 13693 mem_cp[2] = INVALIDm; 13694 13695 for (i = 0; mem_cp[i] != INVALIDm; i++) { 13696 _soc_mem_write_range_cache_update(unit, mem_cp[i], 13697 array_index, blk, no_cache, 13698 index_min, index_max, 13699 entry_data); 13700 } 13701 } 13702 } 13703 /* 13704 * There are 2 physical instances of THDO_OFFSET_0 on TD+. 13705 * Writing this table writes all two physical instances. 13706 * The instances are THDO_OFFSET_0A, THDO_OFFSET_0B. 13707 */ 13708 if (SOC_IS_TRIDENT(unit)) { 13709 int r = SOC_E_NONE; 13710 13711 r = soc_trident_mem_cp_get(unit, mem, mem_cp); 13712 if (SOC_FAILURE(r)) { 13713 return; 13714 } 13715 13716 for (i = 0; i < SOC_MEM_CP_MAX_NUM; i++) { 13717 if (soc_mem_is_valid(unit, mem_cp[i])) { 13718 _soc_mem_write_range_cache_update(unit, mem_cp[i], 13719 array_index, blk, no_cache, 13720 index_min, index_max, 13721 entry_data); 13722 } 13723 } 13724 } 13725 } 13726 #endif /* BCM_TRIDENT_SUPPORT */ 13727 13728 /* 13729 * Function: _soc_mem_write_cache_update 13730 * 13731 * Purpose: Called by soc_mem_write_extended(). After a successful write, 13732 * update the cache to hold the new data (if applicable). 13733 * 13734 * Returns: Nothing 13735 */ 13736 void 13737 _soc_mem_write_cache_update(int unit, soc_mem_t mem, int blk, int no_cache, 13738 int index, int array_index, void *entry_data, 13739 void *entry_data_ptr, uint32 *cache_entry_data, 13740 uint32 *converted_entry_data) 13741 { 13742 /* Write back to cache if active */ 13743 uint32 *cache; 13744 uint8 *vmap; 13745 int entry_dw; 13746 int mem_array_vmap_offset; 13747 int mem_array_cache_offset; 13748 13749 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 13750 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 13751 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 13752 entry_dw = soc_mem_entry_words(unit, mem); 13753 #ifdef BCM_DNX_SUPPORT 13754 mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ? 13755 ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) : 13756 (array_index * soc_mem_index_count(unit, mem)); 13757 13758 #else 13759 mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem); 13760 #endif 13761 mem_array_cache_offset = mem_array_vmap_offset * entry_dw; 13762 13763 if (cache != NULL && !no_cache && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 13764 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) || 13765 SOC_HW_ACCESS_DISABLE(unit)) { 13766 if (!SOC_WARM_BOOT(unit)) { 13767 CACHE_VMAP_CLR(vmap, mem_array_vmap_offset + index); 13768 } 13769 } else if (_SOC_MEM_CHK_L2_MEM(mem)) { 13770 soc_field_t fld_vld = VALIDf; 13771 if (soc_feature(unit, soc_feature_base_valid)) { 13772 fld_vld = BASE_VALIDf; 13773 } 13774 /* If an invalid entry is being written then clear the cache */ 13775 if (((mem == L2_ENTRY_2m && 13776 soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_0f) && 13777 soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_1f)) || 13778 ((mem == L2Xm || mem == L2_ENTRY_1m) && 13779 soc_mem_field32_get(unit, mem, entry_data, fld_vld))) && 13780 ((mem == L2_ENTRY_2m && 13781 (soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_0f) && 13782 soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_1f))) || 13783 ((mem == L2Xm || mem == L2_ENTRY_1m) && 13784 soc_mem_field32_get(unit, mem, entry_data, STATIC_BITf)))) { 13785 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 13786 sal_memcpy(cache + index * entry_dw, 13787 (entry_data_ptr == converted_entry_data) ? 13788 cache_entry_data : entry_data, entry_dw * 4); 13789 #else 13790 sal_memcpy(cache + index * entry_dw, entry_data, entry_dw * 4); 13791 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 13792 CACHE_VMAP_SET(vmap, index); 13793 } else { 13794 CACHE_VMAP_CLR(vmap, index); 13795 } 13796 if (mem == L2_ENTRY_1m) { 13797 vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[blk]; 13798 CACHE_VMAP_CLR(vmap, index/2); 13799 } else if (mem == L2_ENTRY_2m) { 13800 vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[blk]; 13801 CACHE_VMAP_CLR(vmap, index*2); 13802 CACHE_VMAP_CLR(vmap, index*2 + 1); 13803 } 13804 } else { 13805 if (SOC_IS_SAND(unit)) { 13806 /* DPP devices should use this write even if they are compiled with trident devices. */ 13807 sal_memcpy(cache + mem_array_cache_offset + index * entry_dw, 13808 entry_data, entry_dw * 4); 13809 } else { 13810 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 13811 || defined(BCM_HURRICANE2_SUPPORT) 13812 if (entry_data_ptr == converted_entry_data) { 13813 sal_memcpy(cache + index * entry_dw, 13814 cache_entry_data, entry_dw * 4); 13815 #if defined(INCLUDE_MEM_SCAN) 13816 /* Update memscan TCAM cache if necessary */ 13817 soc_mem_scan_tcam_cache_update(unit, mem, 13818 index, index, 13819 entry_data_ptr); 13820 #endif /* INCLUDE_MEM_SCAN */ 13821 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 13822 #ifdef BCM_WARM_BOOT_SUPPORT 13823 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) || 13824 SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) { 13825 soc_mem_overlay_tcam_update(unit, mem, blk, 13826 index, index); 13827 } 13828 #endif 13829 #endif 13830 } else { 13831 sal_memcpy(cache + index * entry_dw, 13832 entry_data, entry_dw * 4); 13833 } 13834 #else 13835 sal_memcpy(cache + mem_array_cache_offset + index * entry_dw, 13836 entry_data, entry_dw * 4); 13837 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 13838 } 13839 CACHE_VMAP_SET(vmap, (mem_array_vmap_offset + index)); 13840 13841 /* Clear VMAP index in cache when tunnel info is null entry */ 13842 if (_SOC_MEM_CHK_EGR_IP_TUNNEL(mem) && 13843 SOC_MEM_IS_VALID(unit, mem)) { 13844 if (sal_memcmp(entry_data, soc_mem_entry_null(unit, mem), 13845 soc_mem_entry_words(unit, mem) * sizeof(uint32)) == 0) { 13846 CACHE_VMAP_CLR(vmap, index); 13847 } 13848 } 13849 13850 #ifdef BCM_TRIDENT_SUPPORT 13851 _soc_mem_write_instances_cache_update(unit, mem, blk, 13852 no_cache, index, index, 13853 array_index, entry_data); 13854 #endif /* BCM_TRIDENT_SUPPORT */ 13855 } 13856 } 13857 } 13858 13859 void 13860 _soc_mem_alpm_write_cache(int unit, soc_mem_t mem, int copyno, 13861 int index, void *entry_data) 13862 { 13863 /* Write back to cache if active */ 13864 int blk; 13865 uint32 *cache; 13866 uint8 *vmap; 13867 int entry_dw; 13868 uint32 converted_entry_data[SOC_MAX_MEM_WORDS]; 13869 uint32 cache_entry_data[SOC_MAX_MEM_WORDS]; 13870 void *entry_data_ptr; 13871 13872 /* Currently only apply to LPM tables */ 13873 switch (mem) { 13874 case L3_DEFIPm: 13875 case L3_DEFIP_PAIR_128m: 13876 case L3_DEFIP_LEVEL1m: 13877 case L3_DEFIP_PAIR_LEVEL1m: 13878 case L3_DEFIP_ALPM_LEVEL2m: 13879 case L3_DEFIP_ALPM_LEVEL3m: 13880 case L3_DEFIP_ALPM_LEVEL2_HIT_ONLYm: /* TH3TBD need? */ 13881 case L3_DEFIP_ALPM_LEVEL3_HIT_ONLYm: 13882 case L3_DEFIP_AUX_TABLEm: 13883 case L3_DEFIP_ALPM_RAWm: 13884 case L3_DEFIP_ALPM_IPV4m: 13885 case L3_DEFIP_ALPM_IPV4_1m: 13886 case L3_DEFIP_ALPM_IPV6_64m: 13887 case L3_DEFIP_ALPM_IPV6_64_1m: 13888 case L3_DEFIP_ALPM_IPV6_128m: 13889 break; 13890 default: 13891 return ; 13892 } 13893 13894 entry_data_ptr = soc_mem_write_tcam_to_hw_format(unit, mem, entry_data, 13895 cache_entry_data, 13896 converted_entry_data); 13897 MEM_LOCK(unit, mem); 13898 13899 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 13900 13901 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 13902 if (copyno != COPYNO_ALL && copyno != blk) { 13903 continue; 13904 } 13905 13906 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 13907 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 13908 entry_dw = soc_mem_entry_words(unit, mem); 13909 13910 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 13911 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) || 13912 SOC_HW_ACCESS_DISABLE(unit)) { 13913 if (!SOC_WARM_BOOT(unit)) { 13914 CACHE_VMAP_CLR(vmap, index); 13915 } 13916 } else { 13917 if (entry_data_ptr == converted_entry_data) { 13918 sal_memcpy(cache + index * entry_dw, 13919 cache_entry_data, entry_dw * 4); 13920 #if defined(INCLUDE_MEM_SCAN) 13921 /* Update memscan TCAM cache if necessary */ 13922 soc_mem_scan_tcam_cache_update(unit, mem, 13923 index, index, 13924 entry_data_ptr); 13925 #endif /* INCLUDE_MEM_SCAN */ 13926 } else { 13927 sal_memcpy(cache + index * entry_dw, 13928 entry_data, entry_dw * 4); 13929 } 13930 CACHE_VMAP_SET(vmap, index); 13931 } 13932 } 13933 } 13934 13935 MEM_UNLOCK(unit, mem); 13936 13937 } 13938 13939 #ifdef BCM_ESW_SUPPORT 13940 STATIC uint32 13941 _soc_l2mode_fifo_enable_memwr_field_get(int unit) 13942 { 13943 uint32 rval = 0, memwr = 0; 13944 if (SOC_IS_TRIDENT2X(unit)) { 13945 if (READ_AUX_ARB_CONTROLr(unit, &rval) < 0) { 13946 return 0; 13947 } 13948 memwr = soc_reg_field_get(unit, AUX_ARB_CONTROLr, 13949 rval, 13950 L2_MOD_FIFO_ENABLE_MEMWRf); 13951 } 13952 return memwr; 13953 } 13954 13955 STATIC int 13956 _soc_l2mode_fifo_enable_memwr_field_set(int unit, int enable) 13957 { 13958 uint32 rval = 0; 13959 uint32 ena = (enable==0)?0:1; 13960 13961 if (SOC_IS_TRIDENT2X(unit)) { 13962 SOC_IF_ERROR_RETURN( 13963 READ_AUX_ARB_CONTROLr(unit, &rval)); 13964 soc_reg_field_set(unit, AUX_ARB_CONTROLr, &rval, 13965 L2_MOD_FIFO_ENABLE_MEMWRf, ena); 13966 SOC_IF_ERROR_RETURN( 13967 WRITE_AUX_ARB_CONTROLr(unit, rval)); 13968 } 13969 return SOC_E_NONE; 13970 } 13971 13972 #if defined(BCM_TRIUMPH3_SUPPORT) 13973 STATIC uint32 13974 _soc_l2mode_fifo_enable_delete_field_get(int unit) 13975 { 13976 uint32 rval = 0, l2_delete = 0; 13977 int i; 13978 soc_reg_t fifo_reg[] = { 13979 L2_MOD_FIFO_ENABLEr, 13980 AUX_ARB_CONTROLr 13981 }; 13982 soc_reg_t fifo_fld[] = { 13983 L2_DELETEf, 13984 L2_MOD_FIFO_ENABLE_L2_DELETEf 13985 }; 13986 13987 for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) { 13988 if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) { 13989 if (soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval) < 0) { 13990 return 0; 13991 } 13992 l2_delete = soc_reg_field_get(unit, fifo_reg[i], rval, fifo_fld[i]); 13993 break; 13994 } 13995 } 13996 return l2_delete; 13997 13998 } 13999 14000 STATIC int 14001 _soc_l2mode_fifo_enable_delete_field_set(int unit, uint32 enable) 14002 { 14003 uint32 rval = 0; 14004 int i; 14005 soc_reg_t fifo_reg[] = { 14006 L2_MOD_FIFO_ENABLEr, 14007 AUX_ARB_CONTROLr 14008 }; 14009 soc_reg_t fifo_fld[] = { 14010 L2_DELETEf, 14011 L2_MOD_FIFO_ENABLE_L2_DELETEf 14012 }; 14013 14014 for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) { 14015 if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) { 14016 SOC_IF_ERROR_RETURN( 14017 soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval)); 14018 soc_reg_field_set(unit, fifo_reg[i], &rval, fifo_fld[i], enable); 14019 SOC_IF_ERROR_RETURN( 14020 soc_reg32_set(unit, fifo_reg[i], REG_PORT_ANY, 0, rval)); 14021 break; 14022 } 14023 } 14024 14025 return SOC_E_NONE; 14026 } 14027 14028 STATIC uint32 14029 _soc_l2mode_fifo_enable_insert_field_get(int unit) 14030 { 14031 uint32 rval = 0, l2_insert = 0; 14032 int i; 14033 soc_reg_t fifo_reg[] = { 14034 L2_MOD_FIFO_ENABLEr, 14035 AUX_ARB_CONTROLr 14036 }; 14037 soc_reg_t fifo_fld[] = { 14038 L2_INSERTf, 14039 L2_MOD_FIFO_ENABLE_L2_INSERTf 14040 }; 14041 14042 for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) { 14043 if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) { 14044 if (soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval) < 0) { 14045 return 0; 14046 } 14047 l2_insert = soc_reg_field_get(unit, fifo_reg[i], rval, fifo_fld[i]); 14048 break; 14049 } 14050 } 14051 return l2_insert; 14052 14053 } 14054 14055 STATIC int 14056 _soc_l2mode_fifo_enable_insert_field_set(int unit, uint32 enable) 14057 { 14058 uint32 rval = 0; 14059 int i; 14060 soc_reg_t fifo_reg[] = { 14061 L2_MOD_FIFO_ENABLEr, 14062 AUX_ARB_CONTROLr 14063 }; 14064 soc_reg_t fifo_fld[] = { 14065 L2_INSERTf, 14066 L2_MOD_FIFO_ENABLE_L2_INSERTf 14067 }; 14068 14069 for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) { 14070 if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) { 14071 SOC_IF_ERROR_RETURN( 14072 soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval)); 14073 soc_reg_field_set(unit, fifo_reg[i], &rval, fifo_fld[i], enable); 14074 SOC_IF_ERROR_RETURN( 14075 soc_reg32_set(unit, fifo_reg[i], REG_PORT_ANY, 0, rval)); 14076 break; 14077 } 14078 } 14079 14080 return SOC_E_NONE; 14081 } 14082 14083 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 14084 14085 /* When L2 entries are corrected, l2mode_fifo memwr field must be '0'. 14086 * Reason1: We need not to produce the memwr event to L2mode_fifo 14087 * during soc_ser_sram_correction. 14088 * Reason2: If l2mode_fifo is full and memwr_field is '1', it will lead to recursion. 14089 * soc_ser_sram_correction -> _soc_mem_write_schan_msg_send -> soc_ser_sram_correction 14090 * _soc_mem_write_schan_msg_send -> ....... 14091 */ 14092 STATIC void 14093 _soc_ser_sram_correction_pre(int unit, soc_mem_t mem, uint32 mem_val) 14094 { 14095 switch(mem) { 14096 case L2Xm: 14097 if (mem_val) { 14098 (void)_soc_l2mode_fifo_enable_memwr_field_set(unit, 0); 14099 } 14100 break; 14101 default: 14102 return; 14103 } 14104 } 14105 14106 STATIC void 14107 _soc_ser_sram_correction_post(int unit, soc_mem_t mem, uint32 mem_val) 14108 { 14109 switch(mem) { 14110 case L2Xm: 14111 if (mem_val) { 14112 (void)_soc_l2mode_fifo_enable_memwr_field_set(unit, 1); 14113 } 14114 break; 14115 default: 14116 return; 14117 } 14118 } 14119 14120 STATIC void 14121 _soc_ser_sram_correction_init(int unit, soc_mem_t mem, uint32 *mem_val) 14122 { 14123 switch(mem) { 14124 case L2Xm: 14125 *mem_val = _soc_l2mode_fifo_enable_memwr_field_get(unit); 14126 break; 14127 default: 14128 return ; 14129 } 14130 return ; 14131 } 14132 #endif /* BCM_ESW_SUPPORT */ 14133 14134 /* 14135 * Function: _soc_mem_write_schan_msg_send 14136 * 14137 * Purpose: Called by soc_mem_write_extended(). Send the requested 14138 * schan_msg_t. On ESW chips, retry errors. If SER is available, 14139 * try to use it to correct errors. 14140 * 14141 * Returns: SOC_E_xxx 14142 */ 14143 STATIC int 14144 _soc_mem_write_schan_msg_send(int unit, schan_msg_t *schan_msg, soc_mem_t mem, 14145 int blk, int index2) 14146 { 14147 int rv; 14148 int allow_intr = SOC_IS_SAND(unit); 14149 int entry_dw = soc_mem_entry_words(unit, mem); 14150 14151 #ifdef BCM_ESW_SUPPORT 14152 uint32 retries_remaining = HASH_MEM_OP_RETRY_COUNT; 14153 int rv1 = SOC_E_NONE, rv2 = SOC_E_NONE; 14154 uint32 need_retry = 0; 14155 int pipe = 0; 14156 int acc_type; 14157 uint32 entry[SOC_MAX_MEM_WORDS]; 14158 #ifdef BCM_TOMAHAWK3_SUPPORT 14159 uint16 dev_id; 14160 uint8 rev_id; 14161 14162 soc_cm_get_id(unit, &dev_id, &rev_id); 14163 #endif 14164 do { 14165 rv = soc_schan_op(unit, schan_msg, 2 + entry_dw, 0, allow_intr); 14166 14167 if (SOC_E_FAIL == rv && 14168 soc_feature(unit, soc_feature_efp_meter_table_write_ignore_nack)) { 14169 if ((mem == EFP_METER_TABLEm || 14170 mem == EFP_METER_TABLE_PIPE0m || 14171 mem == EFP_METER_TABLE_PIPE1m || 14172 mem == EFP_METER_TABLE_PIPE2m || 14173 mem == EFP_METER_TABLE_PIPE3m || 14174 mem == EFP_METER_TABLE_Xm || 14175 mem == EFP_METER_TABLE_Ym) && ((index2 % 2) == 1)) { 14176 /* 14177 * Ignore the unexpected NACK during writing to EFP_METER_TABLExxx 14178 * since the real error is in the pair index instead of writen index and 14179 * the write op can go through successfully 14180 */ 14181 rv = SOC_E_NONE; 14182 break; 14183 } 14184 } 14185 14186 if (SOC_E_FAIL == rv && soc_feature(unit, soc_feature_shared_hash_mem)) { 14187 if (retries_remaining == HASH_MEM_OP_RETRY_COUNT) { 14188 _soc_ser_sram_correction_init(unit, mem, &need_retry); 14189 } 14190 _soc_ser_sram_correction_pre(unit, mem, need_retry); 14191 14192 if (need_retry){ 14193 rv2 = soc_schan_op(unit, schan_msg, 2 + entry_dw, 0, allow_intr); 14194 } 14195 /* If rv2==SOC_E_FAIL, the failure of soc_schan_op is not due to L2_mode_fifo is filled, 14196 * because we diable memwr fifo events, so we need to correct the memory. 14197 */ 14198 if (rv2 == SOC_E_FAIL || need_retry == 0) { 14199 /* For multiple pipe devices, SER error is attempted from alternative pipe 14200 * before attempting for inline correction. 14201 * For single pipe devices, inline SER correction is done 14202 */ 14203 14204 if (NUM_PIPE(unit) > 1) { 14205 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 14206 #ifdef BCM_TOMAHAWK3_SUPPORT 14207 if ((pipe == 2 || pipe == 3 || pipe == 4 || pipe ==5) 14208 && (dev_id == BCM56983_DEVICE_ID)) { 14209 continue; 14210 } 14211 #endif 14212 /* determine 1st pipe which has the problem */ 14213 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 14214 acc_type = (pipe == 0)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_0 : 14215 (pipe == 1)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_1 : 14216 (pipe == 2)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_2 : 14217 (pipe == 3)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_3 : 14218 (pipe == 4)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_4 : 14219 (pipe == 5)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_5 : 14220 (pipe == 6)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_6 : 14221 _SOC_MEM_ADDR_ACC_TYPE_PIPE_7; 14222 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit)) { 14223 acc_type = (pipe == 0) ? _SOC_MEM_ADDR_ACC_TYPE_PIPE_X: 14224 _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y; 14225 } else { 14226 return SOC_E_UNAVAIL; 14227 } 14228 14229 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14230 "unit %d: inline ALPM correction LOOP: pipe:%d index %d\n"), 14231 unit, pipe, index2)); 14232 rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS, mem, MEM_BLOCK_ANY, 14233 acc_type, index2, entry); 14234 if (SOC_E_FAIL == rv) { 14235 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14236 "unit %d: inline ALPM correction: will try ser_correction for pipe %d, index %d\n"), 14237 unit, pipe, index2)); 14238 break; 14239 } 14240 } 14241 } 14242 if (pipe >=0 && pipe < NUM_PIPE(unit)) { 14243 rv1 = soc_ser_sram_correction(unit, pipe, 14244 schan_msg->writecmd.header.v2.dst_blk, 14245 schan_msg->writecmd.address, mem, 14246 blk, index2, NULL); 14247 } 14248 } 14249 _soc_ser_sram_correction_post(unit, mem, need_retry); 14250 14251 if (rv1 == SOC_E_NONE && retries_remaining > 0) { 14252 retries_remaining--; 14253 } else { 14254 retries_remaining = 0; /* Don't try if the correction fails */ 14255 } 14256 } else if (SOC_E_FAIL == rv && soc_feature(unit, soc_feature_ignore_mem_write_nak)){ 14257 /* 14258 * In bcm53400 and bcm56160 series, when parity error happened in 14259 * FP_METER_TABLE/EFP_METER_TABLE, sometimes will always get SOC_E_FAIL. 14260 * Add retries here to avoid infinite loop. 14261 */ 14262 if ((mem == EFP_METER_TABLEm) || (mem == FP_METER_TABLEm)) { 14263 retries_remaining--; 14264 } 14265 } else if (SOC_FAILURE(rv)) { 14266 retries_remaining--; 14267 } 14268 } while (SOC_FAILURE(rv) && retries_remaining > 0); 14269 14270 #else 14271 rv = soc_schan_op(unit, schan_msg, 2 + entry_dw, 0, allow_intr); 14272 #endif /* BCM_ESW_SUPPORT */ 14273 14274 return rv; 14275 } 14276 14277 #ifdef ALPM_ENABLE 14278 void 14279 _soc_mem_write_alpm2_bnk_fmt_set(int unit, int index, soc_mem_t mem) 14280 { 14281 #if defined(BCM_TRIDENT3_SUPPORT) 14282 int8 fmt; 14283 int bucket_bank; 14284 14285 bucket_bank = index % soc_mem_index_count(unit, L3_DEFIP_ALPM_RAWm); 14286 switch (mem) { 14287 case L3_DEFIP_ALPM_IPV4m: 14288 fmt = 1; 14289 break; 14290 case L3_DEFIP_ALPM_IPV6_64m: 14291 fmt = 2; 14292 break; 14293 case L3_DEFIP_ALPM_IPV6_128m: 14294 fmt = 3; 14295 break; 14296 case L3_DEFIP_ALPM_IPV4_1m: 14297 fmt = 4; 14298 break; 14299 case L3_DEFIP_ALPM_IPV6_64_1m: 14300 fmt = 5; 14301 break; 14302 default: 14303 fmt = 0; 14304 break; 14305 } 14306 14307 _soc_trident3_alpm2_bnk_fmt_set(unit, bucket_bank, fmt); 14308 #endif 14309 return; 14310 } 14311 #endif 14312 14313 /* 14314 * Function: _soc_mem_write_alpm_bkt_view_set 14315 * 14316 * Purpose: Called by soc_mem_write_extended(). If writing to the ALPM 14317 * memories, add special processing to update the bucket view map. 14318 * 14319 * Returns: Nothing 14320 */ 14321 STATIC void 14322 _soc_mem_write_alpm_bkt_view_set(int unit, soc_mem_t mem, int index, 14323 void *entry_data) 14324 { 14325 #ifdef ALPM_ENABLE 14326 if (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 14327 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 14328 mem == L3_DEFIP_ALPM_IPV6_128m) { 14329 if (soc_mem_field32_get(unit, mem, entry_data, VALIDf)) { 14330 if (soc_feature(unit, soc_feature_alpm2)) { 14331 _soc_mem_write_alpm2_bnk_fmt_set(unit, index, mem); 14332 } else { 14333 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) { 14334 _soc_trident2_alpm_bkt_view_set(unit, index, mem); 14335 } 14336 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || \ 14337 defined(BCM_TRIDENT3_SUPPORT) 14338 else { 14339 soc_alpm_cmn_bkt_view_set(unit, index, mem); 14340 } 14341 #endif 14342 } 14343 } 14344 } 14345 #endif /* ALPM_ENABLE */ 14346 } 14347 14348 STATIC void 14349 _soc_mem_write_lpm_view_set(int unit, soc_mem_t mem, int index, 14350 void *entry_data) 14351 { 14352 #if defined(BCM_TOMAHAWK_SUPPORT) 14353 14354 int valid = 0; 14355 soc_mem_t defip_mem = L3_DEFIPm, defip_pair_mem = L3_DEFIP_PAIR_128m; 14356 14357 #if defined(BCM_TOMAHAWK3_SUPPORT) 14358 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 14359 defip_mem = L3_DEFIP_LEVEL1m; 14360 defip_pair_mem = L3_DEFIP_PAIR_LEVEL1m; 14361 } 14362 #endif 14363 14364 14365 if (SOC_IS_TOMAHAWKX(unit) && 14366 soc_feature(unit, soc_feature_l3_defip_map) && 14367 (mem == defip_mem || 14368 mem == L3_DEFIP_ONLYm)) { 14369 valid = soc_mem_field32_get(unit, mem, entry_data, VALID0f) || 14370 soc_mem_field32_get(unit, mem, entry_data, VALID1f); 14371 14372 mem = valid ? mem : INVALIDm; 14373 #if defined(BCM_TOMAHAWK3_SUPPORT) 14374 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 14375 _soc_th3_lpm_view_set(unit, index, mem, 0); 14376 } else 14377 #endif 14378 _soc_th_lpm_view_set(unit, index, mem, 0); 14379 } 14380 if (SOC_IS_TOMAHAWKX(unit) && 14381 soc_feature(unit, soc_feature_l3_defip_map) && 14382 (mem == defip_pair_mem || 14383 mem == L3_DEFIP_PAIR_128_ONLYm)) { 14384 14385 #if defined(BCM_TOMAHAWK3_SUPPORT) 14386 if (mem == L3_DEFIP_PAIR_LEVEL1m) { 14387 valid = soc_mem_field32_get(unit, mem, entry_data, LWR_VALID0f) || 14388 soc_mem_field32_get(unit, mem, entry_data, LWR_VALID1f) || 14389 soc_mem_field32_get(unit, mem, entry_data, UPR_VALID0f) || 14390 soc_mem_field32_get(unit, mem, entry_data, UPR_VALID1f); 14391 mem = valid ? mem : INVALIDm; 14392 _soc_th3_lpm_view_set(unit, index, mem, 1); 14393 } else 14394 #endif 14395 { 14396 valid = soc_mem_field32_get(unit, mem, entry_data, VALID0_LWRf) || 14397 soc_mem_field32_get(unit, mem, entry_data, VALID1_LWRf) || 14398 soc_mem_field32_get(unit, mem, entry_data, VALID0_UPRf) || 14399 soc_mem_field32_get(unit, mem, entry_data, VALID1_UPRf); 14400 mem = valid ? mem : INVALIDm; 14401 _soc_th_lpm_view_set(unit, index, mem, 1); 14402 } 14403 } 14404 #endif 14405 } 14406 /* 14407 * Function: _soc_mem_write_td2_shadow_entry_set 14408 * 14409 * Purpose: Called by soc_mem_write_extended(). On TD2, if writing to the 14410 * X or Y pipe map tables, update the shadow entry for them. 14411 * 14412 * Returns: SOC_E_xxx 14413 */ 14414 STATIC int 14415 _soc_mem_write_td2_shadow_entry_set(int unit, soc_mem_t mem, int index, 14416 void *entry_data) 14417 { 14418 int rv = SOC_E_NONE; 14419 14420 #ifdef BCM_TRIDENT2_SUPPORT 14421 /* For MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1, update software shadow table. */ 14422 if (SOC_IS_TRIDENT2(unit)) { 14423 if (mem == MMU_INTFI_XPIPE_FC_MAP_TBL0m || 14424 mem == MMU_INTFI_XPIPE_FC_MAP_TBL1m || 14425 mem == MMU_INTFI_YPIPE_FC_MAP_TBL0m || 14426 mem == MMU_INTFI_YPIPE_FC_MAP_TBL1m){ 14427 rv = soc_trident2_fc_map_shadow_entry_set(unit, mem, index, 14428 entry_data); 14429 } 14430 } 14431 #endif 14432 14433 return rv; 14434 } 14435 14436 #ifdef HR3LITE_LPM_WAR 14437 /* 14438 * Function: _soc_mem_hr3_lpm_duplicate 14439 * 14440 * Purpose: Called by _soc_mem_write_schan_msg_create(). 14441 * This function is used to duplicate a LPM-DATA entry on 14442 * HR3-Lite device. LPM table in HR3-Lite support 64 entries 14443 * only but this LPM TCAM for LPM entry between 32~63 can only 14444 * be hit with LPM-DATA in entry between 512~543. 14445 * 14446 * Returns: SOC_E_xxx 14447 */ 14448 STATIC int 14449 _soc_mem_hr3_lpm_duplicate(int unit, soc_mem_t mem, int blk, 14450 int copyno, int array_index, void *in_entry_data, int index) 14451 { 14452 defip_entry_t *lpm_entry = NULL; 14453 defip_data_only_entry_t lpm_data_entry; 14454 defip_hit_only_entry_t lpm_hit_entry; 14455 int lpm_shadow_size = 0; 14456 void *entry_data = in_entry_data; 14457 void *lpm_showdow_entry; 14458 schan_msg_t schan_msg; 14459 int entry_dw = 0, data_byte_len = 0; 14460 int src_blk = 0, dst_blk = 0, acc_type = 0; 14461 int copyno_override = 0; /* If non-zero, will override copyno */ 14462 uint32 maddr; 14463 uint8 at; 14464 soc_mem_t lpm_shadow[] = {L3_DEFIP_DATA_ONLYm, L3_DEFIP_HIT_ONLYm}; 14465 soc_mem_t update_mem = INVALIDm; 14466 int mem_update_cnt = 0; 14467 int mem_update_id = -1; 14468 int i; 14469 uint32 buf; 14470 soc_mem_info_t *m; 14471 soc_field_info_t *fld; 14472 14473 if (!soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit)) { 14474 return SOC_E_NONE; 14475 } 14476 14477 mem_update_id = 0; 14478 if (mem == L3_DEFIPm) { 14479 mem_update_cnt = 2; 14480 lpm_entry = entry_data; 14481 } else { 14482 mem_update_cnt = 1; 14483 if (mem == L3_DEFIP_HIT_ONLYm) { 14484 mem_update_id = 1; 14485 } 14486 } 14487 14488 for (i = mem_update_id; mem_update_cnt > 0; mem_update_cnt--, i++) { 14489 14490 /* 14491 * L3_DEFIPm in HW view is constucted with three tables of 14492 * LPM-TCAM, LPM-DATA and LPM_HTI. 14493 * - This WAR is to duplicate LPM-DATA and LPM-HIT entry. 14494 */ 14495 update_mem = lpm_shadow[i]; 14496 LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, "HR3-Lite LPM_WAR :" 14497 "updateing mem=%s,index=%d\n"), 14498 SOC_MEM_NAME(unit,update_mem), index)); 14499 if (lpm_entry != NULL) { 14500 m = &SOC_MEM_INFO(unit, update_mem); 14501 if (update_mem == L3_DEFIP_DATA_ONLYm) { 14502 lpm_shadow_size = sizeof(defip_data_only_entry_t); 14503 lpm_showdow_entry = &lpm_data_entry; 14504 } else { 14505 lpm_shadow_size = sizeof(defip_hit_only_entry_t); 14506 lpm_showdow_entry = &lpm_hit_entry; 14507 } 14508 sal_memset(lpm_showdow_entry, 0, lpm_shadow_size); 14509 for (fld = &m->fields[0]; fld < &m->fields[m->nFields]; fld++) { 14510 14511 buf = soc_L3_DEFIPm_field32_get(unit, lpm_entry, fld->field); 14512 soc_mem_field32_set(unit, update_mem, 14513 lpm_showdow_entry, fld->field, buf); 14514 } 14515 /* assign processing entry_data to this updating LPM shadow entry */ 14516 entry_data = lpm_showdow_entry; 14517 } 14518 14519 /* start the LPM shadow update */ 14520 mem = update_mem; 14521 14522 if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) { 14523 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14524 "soc_mem_write unit %d: %s.%s[%d]: "), 14525 unit, SOC_MEM_NAME(unit, mem), 14526 SOC_BLOCK_NAME(unit, copyno), index)); 14527 soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM); 14528 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14529 "\n"))); 14530 } 14531 /* start on LPM-DATAm duplication */ 14532 entry_dw = soc_mem_entry_words(unit, mem); 14533 data_byte_len = entry_dw * sizeof (uint32); 14534 14535 schan_msg_clear(&schan_msg); 14536 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 14537 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 14538 14539 sal_memcpy(schan_msg.writecmd.data, entry_data, data_byte_len); 14540 soc_mem_write_copyno_update(unit, mem, ©no, ©no_override); 14541 14542 maddr = soc_mem_addr_get(unit, mem, array_index, blk, index, &at); 14543 schan_msg.writecmd.address = maddr; 14544 14545 soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk); 14546 14547 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG, 14548 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 14549 SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, 14550 &schan_msg, mem, blk, index)); 14551 LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, "HR3-Lite LPM_WAR :" 14552 "mem=%s(%d) duplicated\n"), 14553 SOC_MEM_NAME(unit,update_mem), index)); 14554 } 14555 14556 return SOC_E_NONE; 14557 } 14558 #endif 14559 #ifdef BCM_TOMAHAWK3_SUPPORT 14560 /* 14561 * Function: _soc_th3_mem_write_schan_msg_create 14562 * 14563 * Purpose: Called by soc_mem_write_extended(). Create the schan_msg_t struct 14564 * and send it down the line using _soc_mem_write_schan_msg_send(). 14565 * Set copyno=COPYNO_ALL for all copies of the memory. 14566 * 14567 * Returns: SOC_E_xxx 14568 */ 14569 STATIC int 14570 _soc_th3_mem_write_schan_msg_create(int unit, uint32 flags, 14571 soc_mem_t mem, int copyno, 14572 int array_index, void *entry_data_ptr, 14573 void *entry_data, 14574 uint32 *cache_entry_data, 14575 uint32 *converted_entry_data, 14576 int index, int no_cache, int acc_type) 14577 { 14578 int blk; 14579 int index2; 14580 schan_msg_t schan_msg; 14581 int src_blk, dst_blk; 14582 int copyno_override = 0; /* If non-zero, will override copyno */ 14583 uint32 maddr; 14584 uint8 at; 14585 int entry_dw = soc_mem_entry_words(unit, mem); 14586 int data_byte_len = entry_dw * sizeof (uint32); 14587 soc_mem_t mem_for_write = mem; 14588 14589 /* 14590 * Setup S-Channel command packet 14591 * 14592 * NOTE: the datalen field matters only for the Write Memory and 14593 * Write Register commands, where it is used only by the CMIC to 14594 * determine how much data to send, and is in units of bytes. 14595 */ 14596 schan_msg_clear(&schan_msg); 14597 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 14598 14599 sal_memcpy(schan_msg.writecmd.data, entry_data_ptr, 14600 entry_dw * sizeof(uint32)); 14601 14602 soc_mem_write_copyno_update(unit, mem_for_write, ©no, ©no_override); 14603 14604 if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) { 14605 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14606 "soc_mem_write unit %d: %s.%s[%d]: "), 14607 unit, SOC_MEM_NAME(unit, mem), 14608 SOC_BLOCK_NAME(unit, copyno), index)); 14609 soc_mem_entry_dump(unit, mem, entry_data_ptr, BSL_INFO|BSL_LS_SOC_SOCMEM); 14610 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14611 "\n"))); 14612 } 14613 14614 /* Write to one or all copies of the memory */ 14615 SOC_MEM_BLOCK_ITER(unit, mem_for_write, blk) { 14616 if (copyno_override) { 14617 blk = copyno = copyno_override; 14618 } else if (copyno != COPYNO_ALL && copyno != blk) { 14619 continue; 14620 } 14621 14622 index2 = index; 14623 if (!(flags & SOC_MEM_DONT_MAP_INDEX)) { 14624 _soc_mem_read_defip_index_map(unit, mem, index, &index2); 14625 } 14626 14627 if ((flags & SOC_MEM_DONT_MAP_INDEX) && 14628 (mem == L3_DEFIPm || 14629 mem == L3_DEFIP_ONLYm || 14630 mem == L3_DEFIP_DATA_ONLYm || 14631 mem == L3_DEFIP_HIT_ONLY_Xm || 14632 mem == L3_DEFIP_HIT_ONLY_Ym || 14633 mem == L3_DEFIP_HIT_ONLYm || 14634 mem == L3_DEFIP_PAIR_128m || 14635 mem == L3_DEFIP_PAIR_128_ONLYm || 14636 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 14637 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 14638 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 14639 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 14640 /* Don`t update cache when writing L3_DEFIP with physical index */ 14641 no_cache = 1; 14642 } 14643 maddr = soc_mem_addr_get(unit, mem_for_write, array_index, blk, index2, &at); 14644 schan_msg.writecmd.address = maddr; 14645 14646 soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk); 14647 14648 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG, 14649 dst_blk, src_blk, acc_type, data_byte_len, 0, 14650 0); 14651 14652 /* Write header + address + entry_dw data DWORDs */ 14653 /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */ 14654 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 14655 LOG_WARN(BSL_LS_SOC_SOCMEM, 14656 (BSL_META_U(unit, 14657 "soc_mem_write: assert will fail for memory %s\n"), 14658 SOC_MEM_NAME(unit, mem))); 14659 } 14660 14661 #ifdef CRASH_RECOVERY_SUPPORT 14662 if (!(BCM_UNIT_DO_HW_READ_WRITE(unit))){ 14663 SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write, 14664 blk, index2)); 14665 } 14666 #else 14667 SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write, 14668 blk, index2)); 14669 #endif /* CRASH_RECOVERY_SUPPORT */ 14670 14671 if (copyno_override) 14672 break; 14673 14674 /* we dont cache in case block is a broadcast_block*/ 14675 _soc_mem_write_cache_update(unit, mem, blk, no_cache, index, 14676 array_index, entry_data, entry_data_ptr, 14677 cache_entry_data, converted_entry_data); 14678 14679 /* Update the cache for other memory copies of this memory view */ 14680 #ifdef BCM_TRX_SUPPORT 14681 _soc_mem_aggr_cache_update(unit, mem, blk, no_cache, 14682 index, index, 14683 array_index, entry_data); 14684 #endif /* BCM_TRX_SUPPORT */ 14685 } 14686 if (copyno_override) { 14687 /* if block is a broadcast_block we cach seperatly for each block*/ 14688 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 14689 _soc_mem_write_cache_update(unit, mem, blk, no_cache, index, 14690 array_index, entry_data, entry_data_ptr, 14691 cache_entry_data, converted_entry_data); 14692 } 14693 14694 } 14695 14696 _soc_mem_write_lpm_view_set(unit, mem, index2, entry_data); 14697 14698 return SOC_E_NONE; 14699 } 14700 #endif 14701 /* 14702 * Function: _soc_mem_write_schan_msg_create 14703 * 14704 * Purpose: Called by soc_mem_write_extended(). Create the schan_msg_t struct 14705 * and send it down the line using _soc_mem_write_schan_msg_send(). 14706 * Set copyno=COPYNO_ALL for all copies of the memory. 14707 * 14708 * Returns: SOC_E_xxx 14709 */ 14710 STATIC int 14711 _soc_mem_write_schan_msg_create(int unit, uint32 flags, 14712 soc_mem_t mem, int copyno, 14713 int array_index, void *entry_data_ptr, 14714 void *entry_data, 14715 uint32 *cache_entry_data, 14716 uint32 *converted_entry_data, 14717 int index, int no_cache) 14718 { 14719 int blk; 14720 int index2; 14721 schan_msg_t schan_msg; 14722 int src_blk, dst_blk, acc_type; 14723 int copyno_override = 0; /* If non-zero, will override copyno */ 14724 uint32 maddr; 14725 uint8 at; 14726 int entry_dw = soc_mem_entry_words(unit, mem); 14727 int data_byte_len = entry_dw * sizeof (uint32); 14728 soc_mem_t mem_for_write = mem; 14729 #ifdef HR3LITE_LPM_WAR 14730 int lpm_data_shadow_index = -1; 14731 #endif 14732 14733 #if defined(BCM_TOMAHAWK_SUPPORT) 14734 /* 14735 * MEMWR to MPLS_ENTRY uses Read-Modify-Write, when a double-bit error is detected 14736 * during read, the corrupt data will be used to compute LP control word. As a result, LP 14737 * control word get corrupted and cannot be recovered in current SER logic. So when 14738 * launching MEMWR to MPLS_ENTRY, we translate it to MEMWR to MPLS_ENTRY_ECC 14739 * on TH,TH+. 14740 */ 14741 if ((SOC_IS_TOMAHAWK(unit) || SOC_IS_TOMAHAWKPLUS(unit)) && 14742 (MPLS_ENTRYm == mem)) { 14743 mem_for_write = MPLS_ENTRY_ECCm; 14744 } 14745 #endif 14746 14747 /* 14748 * Setup S-Channel command packet 14749 * 14750 * NOTE: the datalen field matters only for the Write Memory and 14751 * Write Register commands, where it is used only by the CMIC to 14752 * determine how much data to send, and is in units of bytes. 14753 */ 14754 schan_msg_clear(&schan_msg); 14755 acc_type = SOC_MEM_ACC_TYPE(unit, mem_for_write); 14756 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 14757 14758 sal_memcpy(schan_msg.writecmd.data, entry_data_ptr, 14759 entry_dw * sizeof(uint32)); 14760 14761 soc_mem_write_copyno_update(unit, mem_for_write, ©no, ©no_override); 14762 14763 if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) { 14764 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14765 "soc_mem_write unit %d: %s.%s[%d]: "), 14766 unit, SOC_MEM_NAME(unit, mem), 14767 SOC_BLOCK_NAME(unit, copyno), index)); 14768 soc_mem_entry_dump(unit, mem, entry_data_ptr, BSL_INFO|BSL_LS_SOC_SOCMEM); 14769 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 14770 "\n"))); 14771 } 14772 14773 #ifdef HR3LITE_LPM_WAR 14774 if (soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit) && 14775 NEED_HR3LITE_LPM_SHADOW(mem)) { 14776 lpm_data_shadow_index = HR3LITE_LPM_HIT_INDEX2(index); 14777 } 14778 #endif /* HR3LITE_LPM_WAR */ 14779 14780 /* Write to one or all copies of the memory */ 14781 SOC_MEM_BLOCK_ITER(unit, mem_for_write, blk) { 14782 if (copyno_override) { 14783 blk = copyno = copyno_override; 14784 } else if (copyno != COPYNO_ALL && copyno != blk) { 14785 continue; 14786 } 14787 14788 index2 = index; 14789 if (!(flags & SOC_MEM_DONT_MAP_INDEX)) { 14790 _soc_mem_read_defip_index_map(unit, mem, index, &index2); 14791 } 14792 14793 if ((flags & SOC_MEM_DONT_MAP_INDEX) && 14794 (mem == L3_DEFIPm || 14795 mem == L3_DEFIP_ONLYm || 14796 mem == L3_DEFIP_DATA_ONLYm || 14797 mem == L3_DEFIP_HIT_ONLY_Xm || 14798 mem == L3_DEFIP_HIT_ONLY_Ym || 14799 mem == L3_DEFIP_HIT_ONLYm || 14800 mem == L3_DEFIP_PAIR_128m || 14801 mem == L3_DEFIP_PAIR_128_ONLYm || 14802 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 14803 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 14804 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 14805 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 14806 /* Don`t update cache when writing L3_DEFIP with physical index */ 14807 no_cache = 1; 14808 } 14809 maddr = soc_mem_addr_get(unit, mem_for_write, array_index, blk, index2, &at); 14810 schan_msg.writecmd.address = maddr; 14811 14812 soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk); 14813 14814 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG, 14815 dst_blk, src_blk, acc_type, data_byte_len, 0, 14816 0); 14817 14818 /* Write header + address + entry_dw data DWORDs */ 14819 /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */ 14820 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 14821 LOG_WARN(BSL_LS_SOC_SOCMEM, 14822 (BSL_META_U(unit, 14823 "soc_mem_write: assert will fail for memory %s\n"), 14824 SOC_MEM_NAME(unit, mem))); 14825 } 14826 14827 #ifdef CRASH_RECOVERY_SUPPORT 14828 if (!(BCM_UNIT_DO_HW_READ_WRITE(unit))){ 14829 SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write, 14830 blk, index2)); 14831 } 14832 #else 14833 SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write, 14834 blk, index2)); 14835 #endif /* CRASH_RECOVERY_SUPPORT */ 14836 14837 #ifdef HR3LITE_LPM_WAR 14838 if (lpm_data_shadow_index != -1) { 14839 LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, "HR3-Lite LPM_WAR :" 14840 "request mem=%s(%d) duplicate on LPM DATA/HIT entry(%d)\n"), 14841 SOC_MEM_NAME(unit,mem), index, lpm_data_shadow_index)); 14842 /* coverity[stack_use_overflow] */ 14843 SOC_IF_ERROR_RETURN(_soc_mem_hr3_lpm_duplicate(unit, mem, blk, 14844 copyno, array_index, entry_data, lpm_data_shadow_index)); 14845 } 14846 #endif /* HR3LITE_LPM_WAR */ 14847 14848 if (copyno_override) 14849 break; 14850 14851 /* we dont cache in case block is a broadcast_block*/ 14852 _soc_mem_write_cache_update(unit, mem, blk, no_cache, index, 14853 array_index, entry_data, entry_data_ptr, 14854 cache_entry_data, converted_entry_data); 14855 14856 /* Update the cache for other memory copies of this memory view */ 14857 #ifdef BCM_TRX_SUPPORT 14858 _soc_mem_aggr_cache_update(unit, mem, blk, no_cache, 14859 index, index, 14860 array_index, entry_data); 14861 #endif /* BCM_TRX_SUPPORT */ 14862 } 14863 if (copyno_override) { 14864 /* if block is a broadcast_block we cach seperatly for each block*/ 14865 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 14866 _soc_mem_write_cache_update(unit, mem, blk, no_cache, index, 14867 array_index, entry_data, entry_data_ptr, 14868 cache_entry_data, converted_entry_data); 14869 } 14870 14871 } 14872 14873 _soc_mem_write_lpm_view_set(unit, mem, index2, entry_data); 14874 14875 return SOC_E_NONE; 14876 } 14877 14878 /* 14879 * Function: 14880 * _soc_mem_write_extended 14881 * Purpose: 14882 * Write a memory internal to the SOC. 14883 * Notes: 14884 * GBP/CBP memory should only accessed when MMU is in DEBUG mode. 14885 */ 14886 STATIC int 14887 _soc_mem_write_extended(int unit, uint32 flags, soc_mem_t mem, 14888 /* in memory arrays this is the element index in the array, otherwise 0 */ 14889 unsigned array_index, 14890 int copyno, /* Use COPYNO_ALL for all */ 14891 int index, void *entry_data) 14892 { 14893 soc_mem_info_t *meminfo = &SOC_MEM_INFO(unit, mem); 14894 int no_cache; 14895 int rv = SOC_E_NONE; 14896 void *entry_data_ptr; 14897 uint32 converted_entry_data[SOC_MAX_MEM_WORDS]; 14898 uint32 cache_entry_data[SOC_MAX_MEM_WORDS]; 14899 #ifdef BCM_TOMAHAWK3_SUPPORT 14900 int acc_type = 0, j = 0; 14901 uint16 dev_id; 14902 uint8 rev_id; 14903 #endif 14904 #ifdef CRASH_RECOVERY_SUPPORT 14905 /* Use crash recovery defined callback for access */ 14906 if (BCM_UNIT_DO_HW_READ_WRITE(unit)) 14907 { 14908 if(Hw_Log_List[unit].Access_cb.mem_write) 14909 { 14910 Hw_Log_List[unit].Access_cb.mem_write(unit, mem, array_index, copyno, index, entry_data); 14911 } 14912 } 14913 #endif /* CRASH_RECOVERY_SUPPORT */ 14914 14915 SOC_IF_ERROR_RETURN(_soc_mem_write_sanity_check(unit, flags, mem, index)); 14916 14917 _soc_mem_write_ext_cache_set(flags, &index, &no_cache); 14918 if (_soc_mem_hercules_write_attempt(unit, mem, copyno, index, entry_data, 14919 &rv)) { 14920 return rv; 14921 } 14922 14923 entry_data_ptr = soc_mem_write_tcam_to_hw_format(unit, mem, entry_data, 14924 cache_entry_data, 14925 converted_entry_data); 14926 #ifdef BCM_TOMAHAWK3_SUPPORT 14927 if (SOC_MEM_IS_VALID(unit, mem)) { 14928 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 14929 } 14930 soc_cm_get_id(unit, &dev_id, &rev_id); 14931 #endif 14932 14933 #ifdef ALPM_ENABLE 14934 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 14935 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 14936 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 14937 mem == L3_DEFIP_ALPM_RAWm) { 14938 SOC_ALPM_LPM_LOCK(unit); 14939 } else 14940 #endif 14941 { 14942 MEM_LOCK(unit, mem); 14943 } 14944 _soc_mem_read_tr3_esm_lock(unit, copyno); 14945 14946 #ifdef BCM_TOMAHAWK3_SUPPORT 14947 if (((acc_type == 9 || acc_type == 14) && (dev_id == BCM56983_DEVICE_ID))) { 14948 for (j = 0; j < 4; j++) { 14949 switch(j) { 14950 case 0 : acc_type = 0; 14951 break; 14952 case 1 : acc_type = 1; 14953 break; 14954 case 2 : acc_type = 6; 14955 break; 14956 case 3 : acc_type = 7; 14957 break; 14958 } 14959 14960 /* coverity[stack_use_overflow] */ 14961 rv = _soc_th3_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index, 14962 entry_data_ptr, entry_data, 14963 cache_entry_data, converted_entry_data, 14964 index, no_cache, acc_type); 14965 } 14966 } else if (acc_type == 16 && (dev_id == BCM56983_DEVICE_ID)) { 14967 acc_type = 0; 14968 /* coverity[stack_use_overflow] */ 14969 rv = _soc_th3_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index, 14970 entry_data_ptr, entry_data, 14971 cache_entry_data, converted_entry_data, 14972 index, no_cache, acc_type); 14973 } 14974 #if 0 14975 SDK-166723 fix : Commenting this code as it causes invalid nxt hop mac to be updated 14976 into dst mac of the packet 14977 else if (acc_type == 15 && (dev_id == BCM56983_DEVICE_ID)) { 14978 for (j = 0; j < 2; j++) { 14979 switch(j) { 14980 case 0 : acc_type = 0; 14981 break; 14982 case 1 : acc_type = 6; 14983 break; 14984 } 14985 /* coverity[stack_use_overflow] */ 14986 rv = _soc_th3_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index, 14987 entry_data_ptr, entry_data, 14988 cache_entry_data, converted_entry_data, index, no_cache, acc_type); 14989 } 14990 } 14991 #endif 14992 else 14993 #endif 14994 { 14995 /* coverity[stack_use_overflow] */ 14996 rv = _soc_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index, 14997 entry_data_ptr, entry_data, 14998 cache_entry_data, converted_entry_data, 14999 index, no_cache); 15000 } 15001 if (SOC_SUCCESS(rv)) { 15002 _soc_mem_write_alpm_bkt_view_set(unit, mem, index, entry_data); 15003 rv = _soc_mem_write_td2_shadow_entry_set(unit, mem, index, entry_data); 15004 } 15005 15006 _soc_mem_read_tr3_esm_unlock(unit, copyno); 15007 #ifdef ALPM_ENABLE 15008 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 15009 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 15010 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 15011 mem == L3_DEFIP_ALPM_RAWm) { 15012 SOC_ALPM_LPM_UNLOCK(unit); 15013 } else 15014 #endif 15015 { 15016 MEM_UNLOCK(unit, mem); 15017 } 15018 15019 if (NULL != meminfo->snoop_cb) { 15020 if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) { 15021 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE, 15022 copyno, index, index, entry_data_ptr, 15023 meminfo->snoop_user_data); 15024 } 15025 if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) { 15026 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT, 15027 copyno, index, index, entry_data_ptr, 15028 meminfo->snoop_user_data); 15029 } 15030 } 15031 15032 return rv; 15033 } 15034 15035 #ifdef BCM_TRIUMPH2_SUPPORT 15036 STATIC int 15037 _soc_mem_write(int unit, soc_mem_t mem, 15038 /* in memory arrays this is the element index in the array, otherwise 0 */ 15039 unsigned array_index, 15040 int copyno, /* Use COPYNO_ALL for all */ 15041 int index, void *entry_data) 15042 { 15043 return _soc_mem_write_extended(unit, SOC_MEM_NO_FLAGS, mem, 15044 array_index, copyno, index, entry_data); 15045 } 15046 #endif /* BCM_TRIUMPH2_SUPPORT */ 15047 15048 /* 15049 * Function: 15050 * soc_mem_pipe_select_write 15051 * Purpose: 15052 * Write a memory internal to the SOC with pipe selection. 15053 * Notes: 15054 * GBP/CBP memory should only accessed when MMU is in DEBUG mode. 15055 */ 15056 15057 int 15058 soc_mem_pipe_select_write(int unit, 15059 uint32 flags, 15060 soc_mem_t mem, 15061 int copyno, /* Use COPYNO_ALL for all */ 15062 int acc_type, 15063 int index, 15064 void *entry_data) 15065 { 15066 schan_msg_t schan_msg; 15067 int blk; 15068 soc_mem_info_t *meminfo; 15069 int entry_dw; 15070 uint32 *cache; 15071 uint32 maddr; 15072 uint8 at, *vmap; 15073 int no_cache; 15074 int index2, allow_intr=0; 15075 int rv; 15076 int src_blk, dst_blk, data_byte_len; 15077 void *entry_data_ptr; 15078 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 15079 uint32 converted_entry_data[SOC_MAX_MEM_WORDS]; 15080 uint32 cache_entry_data[SOC_MAX_MEM_WORDS]; 15081 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 15082 #ifdef BCM_ESW_SUPPORT 15083 uint8 write_retry_attempt = 0; 15084 int rv1 = SOC_E_NONE, rv2 = SOC_E_NONE; 15085 int pipe = SOC_PIPE_ANY; 15086 uint32 need_retry = 0; 15087 #endif 15088 int entry_num_max = 0; 15089 15090 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 15091 entry_dw = soc_mem_entry_words(unit, mem); 15092 15093 if (!soc_feature(unit, soc_feature_two_ingress_pipes)) { 15094 /* Not a relevant device */ 15095 return SOC_E_UNAVAIL; 15096 } 15097 15098 if (!soc_mem_is_valid(unit, mem)) { 15099 return SOC_E_MEMORY; 15100 } 15101 meminfo = &SOC_MEM_INFO(unit, mem); 15102 15103 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE)); 15104 15105 if ((flags & SOC_MEM_DONT_USE_CACHE) == SOC_MEM_DONT_USE_CACHE) { 15106 no_cache = 1; 15107 } else { 15108 no_cache = 0; 15109 } 15110 15111 if (meminfo->flags & SOC_MEM_FLAG_READONLY) { 15112 LOG_ERROR(BSL_LS_SOC_SOCMEM, 15113 (BSL_META_U(unit, 15114 "soc_mem_write: attempt to write R/O memory %s\n"), 15115 SOC_MEM_NAME(unit, mem))); 15116 return SOC_E_INTERNAL; 15117 } 15118 15119 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 15120 if (soc_feature(unit, soc_feature_xy_tcam) && 15121 (meminfo->flags & SOC_MEM_FLAG_CAM) && 15122 (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM))) { 15123 entry_data_ptr = converted_entry_data; 15124 _soc_mem_tcam_dm_to_xy(unit, mem, 1, entry_data, entry_data_ptr, 15125 cache_entry_data); 15126 } else 15127 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 15128 { 15129 entry_data_ptr = entry_data; 15130 } 15131 15132 /* 15133 * Setup S-Channel command packet 15134 * 15135 * NOTE: the datalen field matters only for the Write Memory and 15136 * Write Register commands, where it is used only by the CMIC to 15137 * determine how much data to send, and is in units of bytes. 15138 */ 15139 15140 schan_msg_clear(&schan_msg); 15141 data_byte_len = entry_dw * sizeof (uint32); 15142 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 15143 sal_memcpy(schan_msg.writecmd.data, 15144 entry_data_ptr, 15145 entry_dw * sizeof (uint32)); 15146 15147 if (copyno != COPYNO_ALL) { 15148 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 15149 LOG_WARN(BSL_LS_SOC_SOCMEM, 15150 (BSL_META_U(unit, 15151 "soc_mem_write: invalid block %d for memory %s\n"), 15152 copyno, SOC_MEM_NAME(unit, mem))); 15153 return SOC_E_PARAM; 15154 } 15155 } 15156 15157 /* 15158 * When checking index, check for 0 instead of soc_mem_index_min. 15159 * Diagnostics need to read/write index 0 of Strata ARL and GIRULE. 15160 */ 15161 if ((flags & SOC_MEM_DONT_MAP_INDEX) && 15162 (mem == L3_DEFIPm || 15163 mem == L3_DEFIP_LEVEL1m || 15164 mem == L3_DEFIP_ONLYm || 15165 mem == L3_DEFIP_DATA_ONLYm || 15166 mem == L3_DEFIP_HIT_ONLY_Xm || 15167 mem == L3_DEFIP_HIT_ONLY_Ym || 15168 mem == L3_DEFIP_HIT_ONLYm || 15169 mem == L3_DEFIP_PAIR_128m || 15170 mem == L3_DEFIP_PAIR_LEVEL1m || 15171 mem == L3_DEFIP_PAIR_128_ONLYm || 15172 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 15173 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 15174 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 15175 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 15176 if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) { 15177 return SOC_E_PARAM; 15178 } 15179 /* Don`t update cache when writing L3_DEFIP with physical index */ 15180 no_cache = 1; 15181 } else { 15182 entry_num_max = soc_mem_index_max(unit, mem); 15183 15184 if (index < 0 || index > entry_num_max) { 15185 LOG_WARN(BSL_LS_SOC_SOCMEM, 15186 (BSL_META_U(unit, 15187 "soc_mem_pipe_select_write: invalid index %d for memory %s acc_type %d\n"), 15188 index, SOC_MEM_NAME(unit, mem), acc_type)); 15189 return SOC_E_PARAM; 15190 } 15191 } 15192 15193 if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) { 15194 LOG_WARN(BSL_LS_SOC_SOCMEM, 15195 (BSL_META_U(unit, 15196 "soc_mem_pipe_select_write: invalid index %d for memory %s\n"), 15197 index, SOC_MEM_NAME(unit, mem))); 15198 return SOC_E_PARAM; 15199 } 15200 15201 if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) { 15202 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 15203 "soc_mem_pipe_select_write unit %d: %s.%s[%d]: "), 15204 unit, SOC_MEM_NAME(unit, mem), 15205 SOC_BLOCK_NAME(unit, copyno), index)); 15206 soc_mem_entry_dump(unit, mem, entry_data_ptr, BSL_INFO|BSL_LS_SOC_SOCMEM); 15207 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 15208 "\n"))); 15209 } 15210 15211 /* Write to one or all copies of the memory */ 15212 15213 rv = SOC_E_NONE; 15214 15215 #ifdef ALPM_ENABLE 15216 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 15217 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 15218 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 15219 mem == L3_DEFIP_ALPM_RAWm) { 15220 SOC_ALPM_LPM_LOCK(unit); 15221 } else 15222 #endif 15223 { 15224 MEM_LOCK(unit, mem); 15225 } 15226 #if defined(BCM_TRIUMPH3_SUPPORT) 15227 if (soc_feature(unit, soc_feature_esm_correction)) { 15228 if (copyno == MEM_BLOCK_ANY) { 15229 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 15230 } 15231 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 15232 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU)) { 15233 SOC_ESM_LOCK(unit); 15234 } 15235 } 15236 #endif 15237 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 15238 if (copyno != COPYNO_ALL && copyno != blk) { 15239 continue; 15240 } 15241 15242 index2 = index; 15243 15244 15245 #if defined(BCM_TRIDENT2_SUPPORT) 15246 if (SOC_IS_TD2_TT2(unit) && 15247 soc_feature(unit, soc_feature_l3_defip_map) && 15248 (mem == L3_DEFIPm || 15249 mem == L3_DEFIP_LEVEL1m || 15250 mem == L3_DEFIP_ONLYm || 15251 mem == L3_DEFIP_DATA_ONLYm || 15252 mem == L3_DEFIP_HIT_ONLY_Xm || 15253 mem == L3_DEFIP_HIT_ONLY_Ym || 15254 mem == L3_DEFIP_HIT_ONLYm || 15255 mem == L3_DEFIP_PAIR_128m || 15256 mem == L3_DEFIP_PAIR_LEVEL1m || 15257 mem == L3_DEFIP_PAIR_128_ONLYm || 15258 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 15259 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 15260 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 15261 mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) { 15262 if (!(flags & SOC_MEM_DONT_MAP_INDEX)) { 15263 index2 = soc_trident2_l3_defip_index_map(unit, mem, index); 15264 } 15265 } 15266 #endif /* BCM_TRIDENT2_SUPPORT */ 15267 maddr = soc_mem_addr_get(unit, mem, 0, blk, index2, &at); 15268 #if defined(BCM_EXTND_SBUS_SUPPORT) 15269 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 15270 /* Override ACC_TYPE in address */ 15271 maddr &= ~(_SOC_MEM_ADDR_ACC_TYPE_MASK << 15272 _SOC_MEM_ADDR_ACC_TYPE_SHIFT); 15273 maddr |= (acc_type & _SOC_MEM_ADDR_ACC_TYPE_MASK) << 15274 _SOC_MEM_ADDR_ACC_TYPE_SHIFT; 15275 } 15276 #endif /* BCM_EXTND_SBUS_SUPPORT */ 15277 schan_msg.writecmd.address = maddr; 15278 dst_blk = 0; 15279 #if defined(BCM_EXTND_SBUS_SUPPORT) 15280 if (soc_feature(unit, soc_feature_new_sbus_format)) { 15281 dst_blk = SOC_BLOCK2SCH(unit, blk); 15282 } else 15283 #endif /* BCM_EXTND_SBUS_SUPPORT */ 15284 { 15285 #if defined(BCM_XGS3_SWITCH_SUPPORT) 15286 /* required on XGS3. Optional on other devices */ 15287 dst_blk = ((maddr >> SOC_BLOCK_BP) 15288 & 0xf) | (((maddr >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 15289 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 15290 } 15291 15292 soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG, 15293 dst_blk, src_blk, acc_type, data_byte_len, 0, 15294 0); 15295 15296 /* Write header + address + entry_dw data DWORDs */ 15297 /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */ 15298 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 15299 LOG_WARN(BSL_LS_SOC_SOCMEM, 15300 (BSL_META_U(unit, 15301 "soc_mem_pipe_select_write: assert will fail for memory %s\n"), SOC_MEM_NAME(unit, mem))); 15302 } 15303 #ifdef BCM_ESW_SUPPORT 15304 _retry_op: 15305 #endif /* BCM_ESW_SUPPORT */ 15306 rv = soc_schan_op(unit, &schan_msg, 15307 2 + entry_dw, 0, allow_intr); 15308 if (SOC_E_FAIL == rv) { 15309 #ifdef BCM_ESW_SUPPORT 15310 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 15311 15312 if (0 == write_retry_attempt) { 15313 _soc_ser_sram_correction_init(unit, mem, &need_retry); 15314 } 15315 _soc_ser_sram_correction_pre(unit, mem, need_retry); 15316 15317 if (need_retry){ 15318 rv2 = soc_schan_op(unit, &schan_msg, 2 + entry_dw, 0, allow_intr); 15319 } 15320 /* If rv2==SOC_E_FAIL, the failure of soc_schan_op is not due to L2_mode_fifo is filled, 15321 * because we diable memwr fifo events, so we need to correct the memory. 15322 */ 15323 if (rv2 == SOC_E_FAIL || need_retry == 0) { 15324 if (SOC_IS_TOMAHAWKX(unit)) { 15325 pipe = (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_0) ? 0 : 15326 (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_1) ? 1 : 15327 (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_2) ? 2 : 15328 (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_3) ? 3 : 15329 (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_4) ? 4 : 15330 (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_5) ? 5 : 15331 (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_6) ? 6 : 15332 7; 15333 } else if (SOC_IS_TRIDENT2X(unit)) { 15334 pipe = (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_X) ? 0 : 15335 1; 15336 } else if (SOC_IS_TRIDENT3X(unit)){ 15337 pipe = (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_0) ? 0 : 15338 1; 15339 } else { 15340 pipe = -1; 15341 } 15342 rv1 = soc_ser_sram_correction(unit, pipe, 15343 schan_msg.writecmd.header.v2.dst_blk, 15344 schan_msg.writecmd.address, mem, 15345 blk, index2, NULL); 15346 } 15347 _soc_ser_sram_correction_post(unit, mem, need_retry); 15348 15349 if (rv1 == SOC_E_NONE) { 15350 if (write_retry_attempt < HASH_MEM_OP_RETRY_COUNT) { 15351 write_retry_attempt++; 15352 goto _retry_op; 15353 } 15354 } 15355 } 15356 #endif /* BCM_ESW_SUPPORT */ 15357 goto done; 15358 } 15359 15360 /* Write back to cache if active */ 15361 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 15362 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 15363 15364 if (cache != NULL && !no_cache && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 15365 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) || 15366 SOC_HW_ACCESS_DISABLE(unit)) { 15367 if (!SOC_WARM_BOOT(unit)) { 15368 CACHE_VMAP_CLR(vmap, index); 15369 } 15370 } else if (_SOC_MEM_CHK_L2_MEM(mem)) { 15371 soc_field_t fld_vld = VALIDf; 15372 if (soc_feature(unit, soc_feature_base_valid)) { 15373 fld_vld = BASE_VALIDf; 15374 } 15375 /* If an invalid entry is being written then clear the cache */ 15376 if (((mem == L2_ENTRY_2m && 15377 soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_0f) && 15378 soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_1f)) || 15379 ((mem == L2Xm || mem == L2_ENTRY_1m) && 15380 soc_mem_field32_get(unit, mem, entry_data, fld_vld))) && 15381 ((mem == L2_ENTRY_2m && 15382 (soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_0f) && 15383 soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_1f))) || 15384 ((mem == L2Xm || mem == L2_ENTRY_1m) && 15385 soc_mem_field32_get(unit, mem, entry_data, STATIC_BITf)))) { 15386 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 15387 sal_memcpy(cache + index * entry_dw, 15388 (entry_data_ptr == converted_entry_data) ? 15389 cache_entry_data : entry_data, entry_dw * 4); 15390 #else 15391 sal_memcpy(cache + index * entry_dw, entry_data, entry_dw * 4); 15392 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 15393 CACHE_VMAP_SET(vmap, index); 15394 } else { 15395 CACHE_VMAP_CLR(vmap, index); 15396 } 15397 if (mem == L2_ENTRY_1m) { 15398 vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[blk]; 15399 CACHE_VMAP_CLR(vmap, index/2); 15400 } else if (mem == L2_ENTRY_2m) { 15401 vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[blk]; 15402 CACHE_VMAP_CLR(vmap, index*2); 15403 CACHE_VMAP_CLR(vmap, index*2 + 1); 15404 } 15405 } else { 15406 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) 15407 sal_memcpy(cache + index * entry_dw, 15408 (entry_data_ptr == converted_entry_data) ? 15409 cache_entry_data : entry_data, entry_dw * 4); 15410 #else 15411 sal_memcpy(cache + index * entry_dw, entry_data, entry_dw * 4); 15412 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 15413 CACHE_VMAP_SET(vmap, index); 15414 } 15415 } 15416 } 15417 15418 done: 15419 #if defined(BCM_TRIUMPH3_SUPPORT) 15420 if (soc_feature(unit, soc_feature_esm_correction)) { 15421 if (copyno == MEM_BLOCK_ANY) { 15422 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 15423 } 15424 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 15425 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU)) { 15426 SOC_ESM_UNLOCK(unit); 15427 } 15428 } 15429 #endif 15430 #ifdef ALPM_ENABLE 15431 if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m || 15432 mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m || 15433 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 15434 mem == L3_DEFIP_ALPM_RAWm) { 15435 SOC_ALPM_LPM_UNLOCK(unit); 15436 } else 15437 #endif 15438 { 15439 MEM_UNLOCK(unit, mem); 15440 } 15441 15442 if (NULL != meminfo->snoop_cb) { 15443 if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) { 15444 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE, 15445 copyno, index, index, entry_data_ptr, 15446 meminfo->snoop_user_data); 15447 } 15448 if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) { 15449 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT, 15450 copyno, index, index, entry_data_ptr, 15451 meminfo->snoop_user_data); 15452 } 15453 } 15454 15455 return rv; 15456 } 15457 15458 #ifdef BCM_TRIUMPH2_SUPPORT 15459 STATIC int 15460 _soc_mem_op_cpu_tdm(int unit, int enable) 15461 { 15462 if (enable) { 15463 soc_IARB_TDM_TABLEm_field32_set(unit, 15464 &(SOC_CONTROL(unit)->iarb_tdm), 15465 PORT_NUMf, 0); 15466 } else { 15467 soc_IARB_TDM_TABLEm_field32_set(unit, 15468 &(SOC_CONTROL(unit)->iarb_tdm), 15469 PORT_NUMf, 63); 15470 } 15471 return _soc_mem_write(unit, IARB_TDM_TABLEm, 0, SOC_BLOCK_ALL, 15472 SOC_CONTROL(unit)->iarb_tdm_idx, 15473 &(SOC_CONTROL(unit)->iarb_tdm)); 15474 } 15475 #endif /* BCM_TRIUMPH2_SUPPORT */ 15476 15477 #ifdef BCM_HURRICANE2_SUPPORT 15478 STATIC int 15479 _soc_mem_hr2_parity_generate(int unit, soc_mem_t mem, void *entry_data) 15480 { 15481 uint8 *data8_buf, data8_val; 15482 int num_bytes, i; 15483 uint32 parity, rval; 15484 15485 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 15486 if (soc_reg_field_get(unit, MISCCONFIGr, rval, PARITY_CHECK_ENf) == 0) { 15487 return SOC_E_NONE; 15488 } 15489 if ((mem == MMU_IPMC_VLAN_TBLm) || (mem == MMU_IPMC_GROUP_TBL0m) 15490 || (mem == MMU_IPMC_GROUP_TBL1m)) { 15491 data8_buf = (uint8 *)entry_data; 15492 num_bytes = soc_mem_entry_bytes(unit,mem); 15493 15494 /* Reset the parity value */ 15495 parity = 0; 15496 soc_mem_field32_set(unit, mem, entry_data, PARITYf, parity); 15497 15498 /* Calculate the parity value */ 15499 for (i = 0; i < num_bytes; i++) { 15500 data8_val = data8_buf[i]; 15501 while (data8_val > 0) { 15502 if (data8_val & 0x1) { 15503 parity++; 15504 } 15505 data8_val = data8_val >> 1; 15506 } 15507 } 15508 15509 /* Set parity value */ 15510 parity &= 0x1; 15511 soc_mem_field32_set(unit, mem, entry_data, PARITYf, parity); 15512 } 15513 return SOC_E_NONE; 15514 } 15515 #endif /* BCM_HURRICANE2_SUPPORT */ 15516 15517 #ifdef BCM_KATANA2_SUPPORT 15518 STATIC int 15519 _soc_mem_write_kt2(int unit, soc_mem_t mem, int copyno, int index, 15520 void *entry_data) 15521 { 15522 int rv = SOC_E_FAIL; 15523 15524 uint32 rval; 15525 uint16 dev_id; 15526 uint8 rev_id; 15527 15528 soc_cm_get_id(unit, &dev_id, &rev_id); 15529 if ((rev_id == BCM56450_B1_REV_ID) && 15530 (SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) && 15531 (mem == ING_PHYSICAL_PORT_TABLEm)) { 15532 15533 READ_ING_Q_BEGINr(unit,&rval); 15534 soc_reg_field_set(unit, ING_Q_BEGINr, &rval, 15535 ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf , 1); 15536 WRITE_ING_Q_BEGINr(unit,rval); 15537 LOG_VERBOSE(BSL_LS_SOC_COMMON, 15538 (BSL_META_U(unit, "WRITE PKT_DISABLE=1\n"))); 15539 15540 rv = soc_mem_array_write(unit, mem, 0, copyno, index, entry_data); 15541 soc_reg_field_set(unit, ING_Q_BEGINr, &rval, 15542 ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf , 0); 15543 WRITE_ING_Q_BEGINr(unit,rval); 15544 LOG_VERBOSE(BSL_LS_SOC_COMMON, 15545 (BSL_META_U(unit, "WRITE PKT_DISABLE=0\n"))); 15546 } else { 15547 return soc_mem_array_write(unit, mem, 0, copyno, index, entry_data); 15548 } 15549 15550 return rv; 15551 } 15552 #endif 15553 15554 void 15555 soc_mem_watch_set(int unit, int value) 15556 { 15557 SOC_CONTROL(unit)->soc_mem_watch = value; 15558 LOG_CLI((BSL_META("memwatch delta %s\n"), 15559 value ? "on" : "off")); 15560 } 15561 15562 /* 15563 * Function: 15564 * soc_mem_write 15565 * Purpose: 15566 * Write a memory internal to the SOC. 15567 * Notes: 15568 * GBP/CBP memory should only accessed when MMU is in DEBUG mode. 15569 */ 15570 int 15571 soc_mem_write(int unit, 15572 soc_mem_t mem, 15573 int copyno, /* Use COPYNO_ALL for all */ 15574 int index, 15575 void *entry_data) 15576 { 15577 int rv; 15578 #ifdef BCM_TRIDENT3_SUPPORT 15579 soc_mem_t phy_mem; 15580 #endif 15581 15582 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 15583 15584 if (SOC_CONTROL(unit)->soc_mem_watch) { 15585 if (SOC_CONTROL(unit)->prev_mem != mem) { 15586 LOG_CLI((BSL_META_U(unit, "%d:%s MEM: %s[%d]\n"), 15587 unit, BSL_FUNC, SOC_MEM_NAME(unit, mem), 15588 index)); 15589 SOC_CONTROL(unit)->prev_mem = mem; 15590 } 15591 } 15592 15593 #ifdef BCM_TRIDENT3_SUPPORT 15594 if (soc_feature(unit, soc_feature_flex_flow)) { 15595 if (SOC_MEM_IS_VIEW(unit, mem)) { 15596 rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem); 15597 if (rv != SOC_E_NONE) { 15598 return rv; 15599 } 15600 mem = phy_mem; 15601 } 15602 } 15603 #endif 15604 _SOC_MEM_REPLACE_MEM(unit, mem); 15605 15606 #ifdef BCM_KATANA2_SUPPORT 15607 if (SOC_IS_KATANA2(unit)) { 15608 rv = _soc_mem_write_kt2(unit, mem, copyno, index, entry_data); 15609 } else 15610 #endif 15611 { 15612 rv = soc_mem_array_write(unit, mem, 0, copyno, index, entry_data); 15613 } 15614 15615 return rv; 15616 } 15617 15618 int 15619 soc_mem_write_extended(int unit, uint32 flags, 15620 soc_mem_t mem, 15621 int copyno, /* COPYNO_ALL allowed */ 15622 int index, 15623 void *entry_data) 15624 { 15625 int rv; 15626 15627 _SOC_MEM_REPLACE_MEM(unit, mem); 15628 #ifdef BCM_KATANA2_SUPPORT 15629 if (SOC_IS_KATANA2(unit)) { 15630 rv = _soc_mem_write_kt2(unit, mem, copyno, index, entry_data); 15631 } else 15632 #endif 15633 { 15634 rv = soc_mem_array_write_extended(unit, flags, mem, 0, copyno, 15635 index, entry_data); 15636 } 15637 15638 return rv; 15639 } 15640 15641 /* 15642 * Function: soc_mem_array_write 15643 * Purpose: Write a memory array internal to the SOC. 15644 */ 15645 int 15646 soc_mem_array_write(int unit, soc_mem_t mem, unsigned array_index, int copyno,/* Use COPYNO_ALL for all */ 15647 int index, void *entry_data) 15648 { 15649 return soc_mem_array_write_extended(unit, SOC_MEM_NO_FLAGS, mem, 15650 array_index, copyno, index, entry_data); 15651 } 15652 15653 int 15654 soc_mem_array_write_extended(int unit, uint32 flags, 15655 soc_mem_t mem, unsigned array_index, 15656 int copyno,/* Use COPYNO_ALL for all */ 15657 int index, void *entry_data) 15658 { 15659 int rv; 15660 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 15661 || defined(BCM_HURRICANE2_SUPPORT) 15662 soc_mem_t aggr_mem = INVALIDm; 15663 void *shift_buffer[MAX_TCAM_PROTECT_RANGES] = {NULL}; 15664 #endif 15665 #ifdef BCM_HURRICANE2_SUPPORT 15666 uint32 try_cnt = 0, val = 0; 15667 int entry_len = 0, skip_cache = 0; 15668 void *entry_tmp = NULL; /* the copy for written entry */ 15669 void *gp_entry_chk = NULL; /* for read check */ 15670 void *xp_entry_chk = NULL; /* for read check */ 15671 #endif /* BCM_HURRICANE2_SUPPORT */ 15672 #ifdef BCM_SAND_SUPPORT 15673 int entry_dw; 15674 #endif 15675 #ifdef BCM_GREYHOUND_SUPPORT 15676 uint32 ori_val = 0, new_val = 0, field_val = 0; 15677 int disable_hw_learn = FALSE; 15678 #endif /* BCM_GREYHOUND_SUPPORT */ 15679 15680 /* Use user defined callback for access */ 15681 if(SOC_INFO(unit).reg_access.mem_write) { 15682 return SOC_INFO(unit).reg_access.mem_write(unit, mem, array_index, copyno, index, entry_data); 15683 } 15684 15685 /* if reloading, don't write to register */ 15686 if (SOC_IS_RELOADING(unit)){ 15687 return SOC_E_NONE; 15688 } 15689 15690 #ifdef BCM_SAND_SUPPORT 15691 entry_dw = soc_mem_entry_words(unit, mem); 15692 15693 /* Write header + address + entry_dw data DWORDs */ 15694 if ((entry_dw + 2 > CMIC_SCHAN_WORDS(unit))) 15695 { 15696 if (SOC_IS_SAND(unit)) 15697 { 15698 rv = _soc_mem_array_wide_write(unit, flags, mem, array_index, copyno, index, entry_data); 15699 return rv; 15700 } 15701 } 15702 #endif 15703 15704 #ifdef BCM_TRIUMPH2_SUPPORT 15705 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 15706 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit)) { 15707 if ((mem == LMEPm) || (mem == LMEP_1m)) { 15708 /* Disable CPU slot from TDM */ 15709 /* coverity[stack_use_overflow] */ 15710 SOC_IF_ERROR_RETURN(_soc_mem_op_cpu_tdm(unit, 0)); 15711 } 15712 } 15713 #endif /* BCM_TRIUMPH2_SUPPORT */ 15714 15715 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 15716 || defined(BCM_HURRICANE2_SUPPORT) 15717 if (soc_feature(unit, soc_feature_xy_tcam) && 15718 SOC_CONTROL(unit)->tcam_protect_write && 15719 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 15720 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 15721 SOC_IF_ERROR_RETURN 15722 (_soc_mem_tcam_entry_preserve(unit, mem, copyno, index, 1, 15723 entry_data, &aggr_mem, 15724 shift_buffer)); 15725 } 15726 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 15727 15728 #ifdef BCM_GREYHOUND_SUPPORT 15729 /* 15730 * To pause L2 hardware learning when IPIPE tables are being written 15731 * after all modules are initialized. 15732 */ 15733 if (SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) { 15734 /* This soc info will be updated when soc attached for a device. */ 15735 if (SOC_CONTROL(unit)->l2x_learn_pause_on_table_write && 15736 SOC_BLOCK_IS_CMP(unit, SOC_MEM_BLOCK_MIN(unit, mem), 15737 SOC_BLK_IPIPE)) { 15738 SOC_IF_ERROR_RETURN(READ_ING_MISC_CONFIG2r(unit, &ori_val)); 15739 15740 new_val = ori_val; 15741 soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val, 15742 CML_OVERRIDE_ENABLE_NEWf, 0x1); 15743 soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val, 15744 CML_OVERRIDE_ENABLE_MOVEf, 0x1); 15745 field_val = soc_reg_field_get(unit, ING_MISC_CONFIG2r, 15746 new_val, CML_OVERRIDE_NEWf); 15747 field_val &= ~0x8; 15748 soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val, 15749 CML_OVERRIDE_NEWf, field_val); 15750 15751 field_val = soc_reg_field_get(unit, ING_MISC_CONFIG2r, 15752 new_val, CML_OVERRIDE_MOVEf); 15753 field_val &= ~0x8; 15754 soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val, 15755 CML_OVERRIDE_MOVEf, field_val); 15756 15757 if (new_val != ori_val) { 15758 SOC_IF_ERROR_RETURN 15759 (WRITE_ING_MISC_CONFIG2r(unit, new_val)); 15760 disable_hw_learn = TRUE; 15761 } 15762 } 15763 } 15764 #endif /* BCM_GREYHOUND_SUPPORT */ 15765 15766 #ifdef BCM_HURRICANE2_SUPPORT 15767 if (SOC_IS_HURRICANE2(unit)) { 15768 SOC_IF_ERROR_RETURN 15769 (_soc_mem_hr2_parity_generate(unit, mem, entry_data)); 15770 } 15771 if (SOC_IS_HURRICANE2(unit) && mem == MMU_IPMC_VLAN_TBLm) { 15772 entry_len = soc_mem_entry_words(unit, mem) * sizeof(uint32); 15773 entry_tmp = sal_alloc(entry_len, "ipmc_vlan_entry_copy"); 15774 gp_entry_chk = sal_alloc(entry_len, "ipmc_vlan_gpentry_check"); 15775 xp_entry_chk = sal_alloc(entry_len, "ipmc_vlan_xpentry_check"); 15776 if (entry_tmp == NULL || gp_entry_chk == NULL || 15777 xp_entry_chk == NULL) { 15778 rv = SOC_E_MEMORY; 15779 goto hr2_war_done; 15780 } 15781 sal_memcpy(entry_tmp, entry_data, entry_len); 15782 sal_memset(gp_entry_chk, 0, entry_len); 15783 sal_memset(xp_entry_chk, 0, entry_len); 15784 } 15785 #endif /* BCM_HURRICANE2_SUPPORT */ 15786 15787 rv = _soc_mem_write_extended(unit, flags,mem, array_index, copyno, index, 15788 entry_data); 15789 15790 #ifdef BCM_HURRICANE2_SUPPORT 15791 /* SDK-50996: HR2 WAR for sbus issue while writing to IPMC_VLAN */ 15792 if (SOC_IS_HURRICANE2(unit) && mem == MMU_IPMC_VLAN_TBLm) { 15793 15794 /* Skip cache */ 15795 skip_cache = SOC_MEM_TEST_SKIP_CACHE(unit); 15796 SOC_MEM_TEST_SKIP_CACHE_SET(unit, TRUE); 15797 15798 do { 15799 if (++try_cnt > 10) { 15800 rv = SOC_E_INTERNAL; 15801 goto hr2_war_done; 15802 } 15803 if (try_cnt > 1){ 15804 sal_memcpy(entry_data, entry_tmp, entry_len); 15805 if ((rv = _soc_mem_write_extended(unit, flags, mem, 15806 array_index, copyno, index, entry_data)) < 0) { 15807 goto hr2_war_done; 15808 } 15809 } 15810 15811 /* Force the read on XPORT's IPMC_VLANm */ 15812 if ((rv = READ_MISCCONFIGr(unit, &val)) < 0) { 15813 goto hr2_war_done; 15814 } 15815 soc_reg_field_set(unit, MISCCONFIGr, &val, 15816 IPMC_VLAN_TBL_RD_SELf, 1); 15817 if ((rv = WRITE_MISCCONFIGr(unit, val)) < 0) { 15818 goto hr2_war_done; 15819 } 15820 sal_memset(xp_entry_chk, 0, entry_len); 15821 if ((rv = soc_mem_array_read(unit, mem, 15822 array_index, copyno, index, xp_entry_chk)) < 0) { 15823 goto hr2_war_done; 15824 } 15825 15826 /* Force the read on GPORT's IPMC_VLANm */ 15827 if ((rv = READ_MISCCONFIGr(unit, &val)) < 0) { 15828 goto hr2_war_done; 15829 } 15830 soc_reg_field_set(unit, MISCCONFIGr, &val, 15831 IPMC_VLAN_TBL_RD_SELf, 0); 15832 if ((rv = WRITE_MISCCONFIGr(unit, val)) < 0) { 15833 goto hr2_war_done; 15834 } 15835 sal_memset(gp_entry_chk, 0, entry_len); 15836 if ((rv = soc_mem_array_read(unit, mem, 15837 array_index, copyno, index, gp_entry_chk)) < 0) { 15838 goto hr2_war_done; 15839 } 15840 } while(sal_memcmp(gp_entry_chk, entry_tmp, entry_len) || 15841 sal_memcmp(xp_entry_chk, entry_tmp, entry_len)); 15842 15843 /* free the allocated memory */ 15844 hr2_war_done : 15845 if (entry_tmp) { 15846 sal_free(entry_tmp); 15847 } 15848 if (gp_entry_chk) { 15849 sal_free(gp_entry_chk); 15850 } 15851 if (xp_entry_chk) { 15852 sal_free(xp_entry_chk); 15853 } 15854 15855 SOC_MEM_TEST_SKIP_CACHE_SET(unit, skip_cache); 15856 /* return once the WAR got error return */ 15857 if (SOC_FAILURE(rv)){ 15858 return rv; 15859 } 15860 } 15861 #endif /* BCM_HURRICANE2_SUPPORT */ 15862 15863 #ifdef BCM_GREYHOUND_SUPPORT 15864 /* 15865 * Restore original L2 hardware learn setting after table write 15866 * operation completes. 15867 */ 15868 if (disable_hw_learn) { 15869 SOC_IF_ERROR_RETURN(WRITE_ING_MISC_CONFIG2r(unit, ori_val)); 15870 } 15871 #endif /* BCM_GREYHOUND_SUPPORT */ 15872 15873 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 15874 || defined(BCM_HURRICANE2_SUPPORT) 15875 if (soc_feature(unit, soc_feature_xy_tcam) && 15876 SOC_CONTROL(unit)->tcam_protect_write && 15877 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 15878 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) { 15879 SOC_IF_ERROR_RETURN 15880 (_soc_mem_tcam_entry_restore(unit, aggr_mem, copyno, index, 1, 15881 shift_buffer)); 15882 } 15883 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */ 15884 15885 SOC_IF_ERROR_RETURN(rv); 15886 15887 #ifdef BCM_TRIUMPH2_SUPPORT 15888 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 15889 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit)) { 15890 if ((mem == LMEPm) || (mem == LMEP_1m)) { 15891 /* Enable CPU slot from TDM */ 15892 SOC_IF_ERROR_RETURN(_soc_mem_op_cpu_tdm(unit, 1)); 15893 } 15894 } 15895 #endif /* BCM_TRIUMPH2_SUPPORT */ 15896 15897 return rv; 15898 } 15899 15900 /* 15901 * Function: 15902 * soc_mem_write_range 15903 * Purpose: 15904 * Write a range of chip's memory with multiple entries 15905 */ 15906 int 15907 soc_mem_write_range(int unit, soc_mem_t mem, int copyno, 15908 int index_min, int index_max, void *buffer) 15909 { 15910 int rc; 15911 15912 rc = soc_mem_write_range_multi_cmc(unit, mem, copyno, 15913 index_min, index_max, buffer, -1); 15914 return rc; 15915 } 15916 15917 /* 15918 * Function: 15919 * soc_mem_write_range_multi_cmc 15920 * Purpose: 15921 * Write a range of chip's memory with multiple entries 15922 * With multiple CMC/channel support 15923 */ 15924 int 15925 soc_mem_write_range_multi_cmc(int unit, soc_mem_t mem, int copyno, 15926 int index_min, int index_max, void *buffer, 15927 int vchan) 15928 { 15929 int rc; 15930 15931 #ifdef SOC_MEM_DEBUG_SPEED 15932 15933 sal_usecs_t start_time; 15934 int diff_time, count = (index_max > index_min) ? 15935 (index_max - index_min + 1) : 15936 (index_min - index_max + 1); 15937 15938 start_time = sal_time_usecs(); 15939 #endif 15940 15941 rc = soc_mem_array_write_range_multi_cmc(unit, 0, mem, 0, copyno, index_min, 15942 index_max, buffer, vchan); 15943 15944 #ifdef SOC_MEM_DEBUG_SPEED 15945 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 15946 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 15947 (BSL_META_U(unit, 15948 "Total dma write time: %d usecs, [%d nsecs per op]\n"), 15949 diff_time, diff_time*1000/count)); 15950 #endif 15951 return rc; 15952 } 15953 15954 /* 15955 * Function: 15956 * soc_mem_array_write_range 15957 * Purpose: 15958 * Write a range of chip's memory with multiple entries 15959 */ 15960 15961 int 15962 soc_mem_array_write_range(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, 15963 int copyno, int index_min, int index_max, void *buffer) 15964 { 15965 int rv; 15966 rv = soc_mem_array_write_range_multi_cmc(unit, flags, mem, array_index, 15967 copyno, index_min, index_max, buffer, -1); 15968 return rv; 15969 } 15970 15971 /* 15972 * Function: 15973 * soc_mem_array_write_range_multi_cmc 15974 * Purpose: 15975 * Write a range of chip's memory with multiple entries 15976 */ 15977 15978 int 15979 soc_mem_array_write_range_multi_cmc(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, 15980 int copyno, int index_min, int index_max, void *buffer, 15981 int vchan) 15982 { 15983 int rv = SOC_E_NONE; 15984 uint32 entry_dw; 15985 int mem_array_vmap_offset, mem_array_cache_offset; 15986 int i; 15987 soc_mem_info_t *meminfo; 15988 void *cache_buffer = NULL; 15989 int blk, cache_copyno = copyno; 15990 int copyno_override = 0; /* If non-zero, will override copyno */ 15991 #ifdef BROADCOM_DEBUG 15992 shared_block_t *p = NULL; 15993 int length = 0; 15994 #endif 15995 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \ 15996 || defined(BCM_HURRICANE2_SUPPORT) 15997 15998 int count, alloc_size; 15999 #endif 16000 uint32 *cache; 16001 int indices_reversed = (index_max < index_min); 16002 int effective_min = indices_reversed ? index_max : index_min; 16003 int effective_max = indices_reversed ? index_min : index_max; 16004 int index_limit = indices_reversed ? (index_min - 1) : (index_max + 1); 16005 16006 uint16 dev_id; 16007 uint8 rev_id; 16008 16009 16010 /* if reloading, don't write to register 16011 and write to H/W is not allowed during Warm boot */ 16012 if (SOC_IS_RELOADING(unit) || SOC_WARM_BOOT(unit)) 16013 { 16014 return SOC_E_NONE; 16015 } 16016 16017 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 16018 16019 if (!soc_mem_is_valid(unit, mem)) { 16020 return SOC_E_MEMORY; 16021 } 16022 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) 16023 if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)){ 16024 soc_mem_write_copyno_update(unit, mem, ©no, ©no_override); 16025 if ((copyno == COPYNO_ALL || copyno == SOC_CORE_ALL) && copyno_override){ 16026 copyno = copyno_override; 16027 } 16028 if (cache_copyno == copyno_override) { 16029 cache_copyno = COPYNO_ALL; 16030 } 16031 } else 16032 #endif 16033 if (copyno == COPYNO_ALL) { 16034 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 16035 if (copyno == COPYNO_ALL) { 16036 return SOC_E_INTERNAL; 16037 } 16038 } 16039 #ifdef BROADCOM_DEBUG 16040 if (soc_dma_debug_property_get(unit)) { 16041 p = (shared_block_t *) (((char*)buffer) - 16042 ( (((char*)&(((shared_block_t*)0)->user_data[0]))) - ((char*)(shared_block_t*)0) )); 16043 if (soc_cm_shared_good_range(unit, p)) { 16044 if (SHARED_GOOD_START(p) && SHARED_GOOD_END_DEBUG(p)) { 16045 length = WORDS2BYTES(soc_mem_entry_words(unit, mem)) * 16046 (effective_max - effective_min + 1); 16047 if (length > p->size) { 16048 LOG_WARN(BSL_LS_SOC_SOCMEM, 16049 (BSL_META_U(unit, 16050 "Suspicious DMA length: " 16051 "Desc:%s: Size:%u: length:%u\n"), 16052 p->description, p->size, length)); 16053 } 16054 } 16055 } else if (soc_mem_dmaable(unit, mem, copyno)) { 16056 LOG_ERROR(BSL_LS_SOC_SOCMEM, 16057 (BSL_META_U(unit, 16058 "ERROR:ATTN: Address:%p:" 16059 "probably not in shared memory region \n"), 16060 p)); 16061 } 16062 } 16063 #endif 16064 16065 soc_cm_get_id(unit, &dev_id, &rev_id); 16066 meminfo = &SOC_MEM_INFO(unit, mem); 16067 entry_dw = soc_mem_entry_words(unit, mem); 16068 #ifdef BCM_DNX_SUPPORT 16069 mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ? 16070 ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) 16071 : (array_index * soc_mem_index_count(unit, mem)); 16072 16073 #else 16074 mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem); 16075 #endif 16076 mem_array_cache_offset = mem_array_vmap_offset * entry_dw; 16077 16078 LOG_INFO(BSL_LS_SOC_SOCMEM, 16079 (BSL_META_U(unit, 16080 "soc_mem_array_write_range: unit %d memory %s.%s [%d:%d]\n"), 16081 unit, SOC_MEM_UFNAME(unit, mem), 16082 SOC_BLOCK_NAME(unit, copyno), 16083 index_min, index_max)); 16084 16085 #ifdef BCM_SAND_SUPPORT 16086 /* Write header + address + entry_dw data DWORDs */ 16087 /* coverity[negative_returns : FALSE] */ 16088 if (soc_mem_slamable(unit, mem, copyno) && !(entry_dw + 2 > CMIC_SCHAN_WORDS(unit))) { 16089 #else 16090 /* coverity[negative_returns : FALSE] */ 16091 if (soc_mem_slamable(unit, mem, copyno) && (dev_id != BCM56983_DEVICE_ID)) { 16092 #endif 16093 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 16094 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) 16095 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit) 16096 && (soc_feature(unit, soc_feature_xy_tcam) && 16097 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 16098 (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM)))) { 16099 count = effective_max - effective_min + 1; 16100 alloc_size = count * entry_dw * sizeof(uint32); 16101 cache_buffer = sal_alloc(alloc_size, "cache buffer"); 16102 if (cache_buffer == NULL) { 16103 return SOC_E_MEMORY; 16104 } 16105 } 16106 #endif 16107 16108 MEM_LOCK(unit, mem); 16109 16110 /* Write to one or all copies of the memory */ 16111 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16112 if (copyno_override) { 16113 blk = copyno_override; 16114 } else if (copyno != COPYNO_ALL && copyno != blk) { 16115 continue; 16116 } 16117 16118 rv = _soc_mem_dma_write(unit, flags, mem, array_index, blk, index_min, 16119 index_max, buffer, cache_buffer, vchan); 16120 if (copyno_override) break; 16121 } 16122 16123 if (rv >= 0) { 16124 uint8 *vmap, *vmap1 = NULL; 16125 16126 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16127 if ((cache_copyno != COPYNO_ALL) && (cache_copyno != blk)) { 16128 continue; 16129 } 16130 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 16131 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 16132 if (_SOC_MEM_CHK_L2_MEM(mem)) { 16133 if (mem == L2_ENTRY_1m) { 16134 vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno]; 16135 } else if (mem == L2_ENTRY_2m) { 16136 vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno]; 16137 } 16138 } 16139 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 16140 sal_memcpy(cache + mem_array_cache_offset + index_min * entry_dw, cache_buffer ? 16141 cache_buffer : buffer, 16142 (index_max - index_min + 1) * entry_dw * 4); 16143 for (i = index_min; i <= index_max; i++) { 16144 if (vmap1) { 16145 CACHE_VMAP_CLR(vmap, i); 16146 if (mem == L2_ENTRY_1m) { 16147 CACHE_VMAP_CLR(vmap1, i/2); 16148 } else { 16149 CACHE_VMAP_CLR(vmap1, i*2); 16150 CACHE_VMAP_CLR(vmap1, i*2 + 1); 16151 } 16152 } else { 16153 CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i); 16154 } 16155 } 16156 } 16157 } 16158 16159 #ifdef BCM_TRX_SUPPORT 16160 _soc_mem_aggr_cache_update(unit, mem, copyno, 0, 16161 index_min, index_max, array_index, buffer); 16162 #endif /* BCM_TRX_SUPPORT */ 16163 16164 } 16165 MEM_UNLOCK(unit, mem); 16166 if (NULL != meminfo->snoop_cb) { 16167 if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) { 16168 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE, 16169 copyno, effective_min, effective_max, buffer, 16170 meminfo->snoop_user_data); 16171 } 16172 if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) { 16173 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT, 16174 copyno, effective_min, effective_max, buffer, 16175 meminfo->snoop_user_data); 16176 } 16177 } 16178 16179 if (cache_buffer) { 16180 sal_free(cache_buffer); 16181 } 16182 return rv; 16183 } 16184 16185 for (i = index_min; i != index_limit; indices_reversed ? i-- : i++) { 16186 SOC_IF_ERROR_RETURN(soc_mem_array_write(unit, mem, array_index, copyno, 16187 i, buffer)); 16188 buffer = ((uint32 *)buffer + entry_dw); 16189 } 16190 return SOC_E_NONE; 16191 } 16192 16193 16194 16195 16196 /* 16197 * Efficiently write a range of chip's memory with the same memory entry. 16198 * When SLAM DMA is available, it is used, and the buffer must be allocated using soc_cm_salloc(). 16199 */ 16200 int soc_mem_array_fill_range( 16201 int unit, /* unit of the memory */ 16202 uint32 flags, /* flags */ 16203 soc_mem_t mem, /* Memory to be written to */ 16204 unsigned min_ar_index, /* min array index to be written to, not used in memories which are not arrays */ 16205 unsigned max_ar_index, /* max array index to be written to, not used in memories which are not arrays */ 16206 int copyno, /* Memory block to write to */ 16207 int index_min, /* first memory index to write to */ 16208 int index_max, /* last memory index to write to */ 16209 const void *buffer) /* buffer of the entry to write. If the memory can be written to by SLAM DMA, 16210 then the buffer must be allocated using soc_cm_salloc(). */ 16211 { 16212 uint32 entry_dw; 16213 int i, tmp; 16214 unsigned a_ind; 16215 soc_mem_info_t *meminfo; 16216 int blk, copyno_override = 0; /* If non-zero, will override copyno */ 16217 int rv = SOC_E_NONE, is_slam_allowed; 16218 16219 uint32 *cache, *cache_cp; 16220 int mem_array_vmap_offset, mem_array_cache_offset; 16221 16222 16223 /* if reloading, don't write to register */ 16224 if (SOC_IS_RELOADING(unit) || SOC_HW_ACCESS_DISABLE(unit)) 16225 { 16226 return SOC_E_NONE; 16227 } 16228 16229 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 16230 16231 if (!soc_mem_is_valid(unit, mem)) { 16232 return SOC_E_MEMORY; 16233 } 16234 16235 meminfo = &SOC_MEM_INFO(unit, mem); 16236 entry_dw = soc_mem_entry_words(unit, mem); 16237 16238 /* get legal values for indices, if too small/big use the memory's boundaries */ 16239 tmp = soc_mem_index_min(unit, mem); 16240 if (index_min < tmp) { 16241 index_min = tmp; 16242 } 16243 if (index_max < index_min) { 16244 index_max = index_min; 16245 } else { 16246 tmp = soc_mem_index_max(unit, mem); 16247 if (index_max > tmp) { 16248 index_max = tmp; 16249 } 16250 } 16251 16252 if (SOC_MEM_IS_ARRAY(unit, mem)) { 16253 soc_mem_array_info_t *maip = SOC_MEM_ARRAY_INFOP(unit, mem); 16254 if (maip) { 16255 if (max_ar_index >= maip->numels + maip->first_array_index) { 16256 max_ar_index = (maip->numels - 1) + maip->first_array_index; 16257 } else if (min_ar_index < maip->first_array_index) { 16258 min_ar_index = maip->first_array_index; 16259 } 16260 } 16261 } else { 16262 min_ar_index = max_ar_index = 0; 16263 } 16264 16265 /* use copyno_override for a broadcast write block */ 16266 soc_mem_write_copyno_update(unit, mem, ©no, ©no_override); 16267 16268 LOG_INFO(BSL_LS_SOC_SOCMEM, 16269 (BSL_META_U(unit, 16270 "memory %s[%u:%u].%s [%d:%d]\n"), 16271 SOC_MEM_UFNAME(unit, mem), 16272 min_ar_index, max_ar_index, SOC_BLOCK_NAME(unit, copyno), index_min, index_max)); 16273 16274 is_slam_allowed = !(flags & 1); 16275 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) 16276 /* Write header + address + entry_dw data DWORDs */ 16277 /* coverity[negative_returns : FALSE] */ 16278 if (is_slam_allowed && soc_mem_slamable(unit, mem, copyno) && !(entry_dw + 2 > CMIC_SCHAN_WORDS(unit))) { 16279 #else 16280 /* coverity[negative_returns : FALSE] */ 16281 if (is_slam_allowed && soc_mem_slamable(unit, mem, copyno)) { 16282 #endif 16283 16284 #ifdef BROADCOM_DEBUG 16285 if (soc_dma_debug_property_get(unit)) { 16286 shared_block_t *p = (shared_block_t *) (((char*)buffer) - 16287 ( (((char*)&(((shared_block_t*)0)->user_data[0]))) - ((char*)(shared_block_t*)0) )); 16288 int length = 0; 16289 if (soc_cm_shared_good_range(unit, p)) { 16290 if (SHARED_GOOD_START(p) && SHARED_GOOD_END_DEBUG(p)) { 16291 length = WORDS2BYTES(soc_mem_entry_words(unit, mem)) * 16292 (index_max - index_min + 1); 16293 if (length > p->size) { 16294 LOG_WARN(BSL_LS_SOC_SOCMEM, 16295 (BSL_META_U(unit, 16296 "Some problem in calling: Desc:%s: Size:%u: length:%d\n"), 16297 p->description, p->size, soc_mem_entry_bytes(unit, mem))); 16298 } 16299 } 16300 } else { 16301 LOG_ERROR(BSL_LS_SOC_SOCMEM, 16302 (BSL_META_U(unit, 16303 "ERROR:ATTN: Address:%p: probably not in shared memory region\n"), 16304 p)); 16305 } 16306 } 16307 #endif 16308 16309 MEM_LOCK(unit, mem); 16310 16311 #ifdef BCM_SBUSDMA_SUPPORT 16312 if (soc_feature(unit, soc_feature_sbusdma)) { 16313 /* Loop over the block instances and write to each one using SLAM DMA */ 16314 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16315 if (copyno_override) { 16316 blk = copyno_override; 16317 } else if (copyno != COPYNO_ALL && copyno != blk) { 16318 continue; 16319 } 16320 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE 16321 if (SOC_IS_JERICHO_2_ONLY(unit) && soc_sand_is_emulation_system(unit) && 16322 _soc_jr2_is_2nd_core(unit, mem, blk)) { 16323 break; /* No need to write the reset of the (non existing) instances in emulation */ 16324 } 16325 #endif 16326 16327 if ((rv = _soc_mem_array_sbusdma_write(unit, 0, mem, min_ar_index, 16328 max_ar_index, blk, index_min, 16329 index_max, (void*)buffer, TRUE, 16330 1, -1)) != SOC_E_NONE) { 16331 break; 16332 } 16333 16334 if (copyno_override) break; 16335 } 16336 16337 /* for petra, NOT update cache if vmap is not set when dma operation. */ 16338 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) 16339 if (rv == SOC_E_NONE) { 16340 uint8 *vmap; 16341 int cache_copyno; 16342 16343 cache_copyno = copyno; 16344 if ((copyno_override) && (copyno_override == soc_mem_broadcast_block_get(unit, mem))) { 16345 cache_copyno = COPYNO_ALL; 16346 } 16347 /* Loop over the block instances ignoring broadcast write block, and update cache */ 16348 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16349 if (cache_copyno != COPYNO_ALL && cache_copyno != blk) { 16350 continue; 16351 } 16352 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 16353 /* coverity[negative_returns : FALSE] */ 16354 /* coverity[negative_returns] */ 16355 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 16356 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 16357 if (!SOC_MEM_IS_ARRAY(unit, mem)) { 16358 min_ar_index = max_ar_index = 0; 16359 } 16360 for (a_ind = min_ar_index; a_ind <= max_ar_index; ++a_ind) { 16361 #ifdef BCM_DNX_SUPPORT 16362 mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ? 16363 ((a_ind - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) 16364 : (a_ind * soc_mem_index_count(unit, mem)); 16365 #else 16366 16367 mem_array_vmap_offset = a_ind * soc_mem_index_count(unit, mem); 16368 #endif 16369 mem_array_cache_offset = mem_array_vmap_offset * entry_dw; 16370 cache_cp = cache; 16371 cache_cp += mem_array_cache_offset + (index_min * entry_dw); 16372 for (i = index_min; i <= index_max; i++) { /* update cache */ 16373 sal_memcpy(cache_cp, buffer, entry_dw * 4); 16374 cache_cp += entry_dw; 16375 CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i); 16376 } 16377 } 16378 } 16379 } 16380 } 16381 #endif 16382 } else 16383 #endif 16384 { 16385 /** 16386 * the code above is intended for non-slambles dma, 16387 * so we write the array table by table 16388 */ 16389 int j; 16390 int chunk_size, chunk_entries, mem_size, entry_words; 16391 int index, index_end; 16392 uint32 *buf; 16393 16394 chunk_size = 2*1024*1024; /* 2MB: max DMA buffer size to allocate */ 16395 entry_words = soc_mem_entry_words(unit, mem); 16396 mem_size = (index_max - index_min + 1) * entry_words * 4; 16397 if (mem_size < chunk_size) { 16398 chunk_size = mem_size; 16399 } 16400 16401 buf = soc_cm_salloc(unit, chunk_size, "fill_table_using_table_dma"); 16402 if (buf == NULL) { 16403 MEM_UNLOCK(unit, mem); 16404 return SOC_E_MEMORY; 16405 } 16406 16407 chunk_entries = chunk_size / (entry_words * 4); 16408 16409 for (index = 0; index < chunk_entries; index++) { 16410 sal_memcpy(buf + (index * entry_words), 16411 buffer, entry_words * 4); 16412 } 16413 16414 /* Loop over the block instances and write to each one using table DMA */ 16415 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16416 if (copyno_override) { 16417 blk = copyno_override; 16418 } else if (copyno != COPYNO_ALL && copyno != blk) { 16419 continue; 16420 } 16421 16422 for (j=min_ar_index; j <= max_ar_index && rv == SOC_E_NONE; j++) { 16423 for (index = index_min; index <= index_max; index += chunk_entries) { 16424 index_end = index + chunk_entries - 1; 16425 if (index_end > index_max) { 16426 index_end = index_max; 16427 } 16428 16429 rv = soc_mem_array_write_range(unit, 0, mem, j, blk, index, index_end, buf); 16430 if (rv != SOC_E_NONE) { 16431 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, "soc_mem_write_range: " "write %s.%s[%d-%d] failed: %s\n"), 16432 SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, blk), index, index_end, soc_errmsg(rv))); 16433 break; 16434 } 16435 } 16436 } 16437 16438 if (copyno_override || rv != SOC_E_NONE) break; 16439 } 16440 soc_cm_sfree(unit, buf); 16441 } 16442 /* Cache have been updated for petra device */ 16443 #if !(defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) 16444 if (rv == SOC_E_NONE) { 16445 uint8 *vmap; 16446 16447 /* Loop over the block instances ignoring broadcast write block, and update cache */ 16448 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16449 if (copyno != COPYNO_ALL && copyno != blk) { 16450 continue; 16451 } 16452 16453 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 16454 16455 /* coverity[negative_returns : FALSE] */ 16456 /* coverity[negative_returns] */ 16457 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 16458 16459 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 16460 if (!SOC_MEM_IS_ARRAY(unit, mem)) { 16461 min_ar_index = max_ar_index = 0; 16462 } 16463 for (a_ind = min_ar_index; a_ind <= max_ar_index; ++a_ind) { 16464 int bytes_to_copy = entry_dw * 4; 16465 #ifdef BCM_DNX_SUPPORT 16466 mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ? 16467 ((a_ind - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) 16468 : (a_ind * soc_mem_index_count(unit, mem)); 16469 #else 16470 mem_array_vmap_offset = a_ind * soc_mem_index_count(unit, mem); 16471 #endif 16472 mem_array_cache_offset = mem_array_vmap_offset * entry_dw; 16473 cache_cp = cache; 16474 cache_cp += mem_array_cache_offset + (index_min * entry_dw); 16475 for (i = index_min; i <= index_max; i++) { /* update cache */ 16476 sal_memcpy(cache_cp, buffer, bytes_to_copy); 16477 cache_cp += entry_dw; 16478 CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i); 16479 } 16480 } 16481 } 16482 } 16483 } 16484 16485 #endif 16486 MEM_UNLOCK(unit, mem); 16487 if (NULL != meminfo->snoop_cb) { 16488 if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) { 16489 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE, 16490 copyno, index_min, index_max, (void*)buffer, 16491 meminfo->snoop_user_data); 16492 } 16493 if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) { 16494 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT, 16495 copyno, index_min, index_max, (void*)buffer, 16496 meminfo->snoop_user_data); 16497 } 16498 } 16499 } else { 16500 /* Loop over the block instances ignoring broadcast write block, fill the table per entry */ 16501 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16502 if (copyno != COPYNO_ALL && copyno != blk) { 16503 continue; 16504 } 16505 16506 for (a_ind = min_ar_index; a_ind <= max_ar_index; ++a_ind) { 16507 for (i = index_min; i <= index_max; i++) { 16508 SOC_IF_ERROR_RETURN(soc_mem_array_write(unit, mem, a_ind, blk, i, (void*)buffer)); 16509 } 16510 } 16511 } 16512 } 16513 return rv; 16514 } 16515 16516 /* 16517 * Efficiently write to a whole memory with a repeating entry. 16518 * When SLAM DMA is available, it is used, and the buffer must be allocated using soc_cm_salloc(). 16519 */ 16520 16521 int 16522 soc_mem_fill( 16523 int unit, /* unit of the memory */ 16524 soc_mem_t mem, /* Memory to be written to */ 16525 int copyno, /* Memory block to write to */ 16526 const void *buffer) /* buffer of the entry to repeatedly write. If the memory can be written to by SLAM DMA, 16527 then the buffer must be allocated using soc_cm_salloc(). */ 16528 { 16529 int rc; 16530 unsigned max_array_index = 0; 16531 unsigned min_array_index = 0; 16532 #ifdef SOC_MEM_DEBUG_SPEED 16533 sal_usecs_t start_time = sal_time_usecs(); 16534 int diff_time; 16535 #endif 16536 16537 if (!soc_mem_is_valid(unit, mem)) { 16538 return SOC_E_MEMORY; 16539 } 16540 if (SOC_MEM_IS_ARRAY(unit, mem)) { 16541 soc_mem_array_info_t *maip = SOC_MEM_ARRAY_INFOP(unit, mem); 16542 if (maip) { 16543 max_array_index = (maip->numels - 1) + maip->first_array_index; 16544 min_array_index = maip->first_array_index; 16545 } 16546 } 16547 rc = soc_mem_array_fill_range(unit, 0, mem, min_array_index, max_array_index, copyno, soc_mem_index_min(unit, mem), soc_mem_index_max(unit, mem), buffer); 16548 16549 #ifdef SOC_MEM_DEBUG_SPEED 16550 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 16551 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, "Total dma write time: %d usecs\n"), diff_time)); 16552 #endif 16553 return rc; 16554 } 16555 16556 #ifdef BCM_TRIDENT_SUPPORT 16557 STATIC int _soc_mem_clear_require_pipe_select(int unit, soc_mem_t mem) 16558 { 16559 if (!(soc_mem_is_valid(unit, mem))) { 16560 return FALSE; 16561 } else { 16562 switch (mem) { 16563 case L3_ENTRY_HIT_ONLYm: 16564 case L3_DEFIP_HIT_ONLYm: 16565 case FP_COUNTER_TABLEm: 16566 case FP_STORM_CONTROL_METERSm: 16567 case ING_PW_TERM_SEQ_NUMm: 16568 case ING_VINTF_COUNTER_TABLEm: 16569 case ING_SERVICE_COUNTER_TABLEm: 16570 case TRILL_DROP_STATSm: 16571 case DLB_HGT_GROUP_CONTROLm: 16572 case DLB_HGT_GROUP_STATSm: 16573 case DLB_HGT_FLOWSET_TIMESTAMP_PAGEm: 16574 case DLB_HGT_OPTIMAL_CANDIDATEm: 16575 case DLB_HGT_FLOWSET_PORTm: 16576 case DLB_HGT_FLOWSET_TIMESTAMPm: 16577 case EGR_FRAGMENT_ID_TABLEm: 16578 case EFP_METER_TABLEm: 16579 case EGR_PW_INIT_COUNTERSm: 16580 case EFP_COUNTER_TABLEm: 16581 case EGR_PERQ_XMT_COUNTERSm: 16582 case EGR_VINTF_COUNTER_TABLEm: 16583 case EGR_SERVICE_COUNTER_TABLEm: 16584 case EGR_PORT_REQUESTSm: 16585 case EGR_MMU_REQUESTSm: 16586 case EGR_MAX_USED_ENTRIESm: 16587 return TRUE; 16588 default: 16589 return FALSE; 16590 } 16591 } 16592 } 16593 #endif 16594 16595 /************************************************************************ 16596 * Routines for reading/writing sorted tables except ARL, * 16597 * and searching sorted tables including the ARL. * 16598 * Sorted tables are: IRULE, L3, MCAST, PVLAN * 16599 */ 16600 16601 #if defined(BCM_TRIDENT2_SUPPORT) 16602 STATIC int 16603 _soc_mem_clear_tcam_protect_clear_restore(int unit, 16604 soc_mem_t mem, 16605 int clear_restore, /* 0:clear, 1:restore*/ 16606 int *tcam_protect_write, 16607 int *config_128b_entries) 16608 { 16609 soc_mem_t defip_mem = L3_DEFIPm; 16610 soc_mem_t defip_pair_mem = L3_DEFIP_PAIR_128m; 16611 int qualified = 16612 soc_feature(unit, soc_feature_l3_defip_map) && 16613 (mem == L3_DEFIPm || 16614 mem == L3_DEFIP_LEVEL1m || 16615 mem == L3_DEFIP_ONLYm || 16616 mem == L3_DEFIP_DATA_ONLYm || 16617 mem == L3_DEFIP_HIT_ONLY_Xm || 16618 mem == L3_DEFIP_HIT_ONLY_Ym || 16619 mem == L3_DEFIP_HIT_ONLYm || 16620 mem == L3_DEFIP_PAIR_128m || 16621 mem == L3_DEFIP_PAIR_LEVEL1m || 16622 mem == L3_DEFIP_PAIR_128_ONLYm || 16623 mem == L3_DEFIP_PAIR_128_DATA_ONLYm || 16624 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm || 16625 mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym || 16626 mem == L3_DEFIP_PAIR_128_HIT_ONLYm); 16627 16628 if (!qualified) { 16629 return SOC_E_NONE; 16630 } 16631 16632 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 16633 defip_mem = L3_DEFIP_LEVEL1m; 16634 defip_pair_mem = L3_DEFIP_PAIR_LEVEL1m; 16635 } 16636 16637 if (clear_restore == 0) { /* clear */ 16638 *tcam_protect_write = SOC_CONTROL(unit)->tcam_protect_write; 16639 SOC_CONTROL(unit)->tcam_protect_write = FALSE; 16640 if (*tcam_protect_write) { 16641 if (soc_mem_index_count(unit, defip_mem)) { 16642 SOP_MEM_STATE(unit, defip_mem).index_max += 8; 16643 SOC_CONTROL(unit)->l3_defip_tcam_size++; 16644 } 16645 if (soc_mem_index_count(unit, defip_pair_mem)) { 16646 SOP_MEM_STATE(unit, defip_pair_mem).index_max += 4; 16647 SOC_CONTROL(unit)->l3_defip_tcam_size++; 16648 } 16649 *config_128b_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) + 4; 16650 16651 SOC_CONTROL(unit)->l3_defip_index_remap = 16652 soc_mem_index_count(unit, defip_pair_mem); 16653 return soc_l3_defip_indexes_init(unit, *config_128b_entries); 16654 } 16655 } else { /* restore */ 16656 SOC_CONTROL(unit)->tcam_protect_write = *tcam_protect_write; 16657 if (*tcam_protect_write) { 16658 if (soc_mem_index_count(unit, defip_mem)) { 16659 SOP_MEM_STATE(unit, defip_mem).index_max -= 8; 16660 SOC_CONTROL(unit)->l3_defip_tcam_size--; 16661 } 16662 if (soc_mem_index_count(unit, defip_pair_mem)) { 16663 SOP_MEM_STATE(unit, defip_pair_mem).index_max -= 4; 16664 SOC_CONTROL(unit)->l3_defip_tcam_size--; 16665 } 16666 SOC_CONTROL(unit)->l3_defip_index_remap = 16667 soc_mem_index_count(unit, defip_pair_mem); 16668 *config_128b_entries -= 4; 16669 return soc_l3_defip_indexes_init(unit, *config_128b_entries); 16670 } 16671 } 16672 return SOC_E_NONE; 16673 } 16674 #endif /* BCM_TRIDENT2_SUPPORT */ 16675 16676 /* 16677 * Function: 16678 * soc_mem_clearable_on_reset 16679 * Purpose: 16680 * Determine whether a table can be cleared during resetting 16681 * Returns: 16682 * 0 if not, 1 otherwise 16683 */ 16684 16685 int 16686 soc_mem_clearable_on_reset(int unit, soc_mem_t mem, int copyno) 16687 { 16688 int blk; 16689 #ifdef BCM_TOMAHAWK_SUPPORT 16690 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 16691 if (soc_mem_is_readonly(unit, mem)) { 16692 return FALSE; 16693 } 16694 switch (mem) { 16695 /* L3_MTU_VALUESm should always be cleared during initialization. 16696 * After clearing, the MTU_SIZEf was set to default value (0x3fff). 16697 * After "init soc;init misc", the MTU_SIZEf was set to zero. 16698 * Zero will cause L3 cases failure. 16699 */ 16700 case L3_MTU_VALUESm: 16701 case IS_TDM_CALENDAR0m: 16702 case IS_TDM_CALENDAR1m: 16703 case IS_TDM_CALENDAR0_PIPE0m: 16704 case IS_TDM_CALENDAR0_PIPE1m: 16705 case IS_TDM_CALENDAR0_PIPE2m: 16706 case IS_TDM_CALENDAR0_PIPE3m: 16707 case IS_TDM_CALENDAR1_PIPE0m: 16708 case IS_TDM_CALENDAR1_PIPE1m: 16709 case IS_TDM_CALENDAR1_PIPE2m: 16710 case IS_TDM_CALENDAR1_PIPE3m: 16711 case LINK_STATUSm: 16712 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 16713 case PKT_SCH_CALENDAR0_PIPE0m: 16714 case PKT_SCH_CALENDAR0_PIPE1m: 16715 case PKT_SCH_CALENDAR1_PIPE0m: 16716 case PKT_SCH_CALENDAR1_PIPE1m: 16717 #endif 16718 #if defined(BCM_TOMAHAWK2_SUPPORT) 16719 case PKT_SCH_CALENDAR0_PIPE2m: 16720 case PKT_SCH_CALENDAR0_PIPE3m: 16721 case PKT_SCH_CALENDAR1_PIPE2m: 16722 case PKT_SCH_CALENDAR1_PIPE3m: 16723 #endif 16724 return FALSE; 16725 default: 16726 break; 16727 } 16728 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16729 if (copyno != COPYNO_ALL && copyno != blk) { 16730 continue; 16731 } 16732 switch (SOC_BLOCK_TYPE(unit, blk)) { 16733 case SOC_BLK_IPIPE: 16734 case SOC_BLK_EPIPE: 16735 return TRUE; 16736 default: 16737 break; 16738 } 16739 } 16740 } else 16741 #endif 16742 { 16743 COMPILER_REFERENCE(unit); 16744 COMPILER_REFERENCE(mem); 16745 COMPILER_REFERENCE(copyno); 16746 COMPILER_REFERENCE(blk); 16747 } 16748 16749 return FALSE; 16750 } 16751 16752 /* 16753 * Function: 16754 * soc_mem_clear 16755 * Purpose: 16756 * Clears a memory. 16757 * Operates on all copies of the table if copyno is COPYNO_ALL. 16758 * Notes: 16759 * For non-sorted tables, all entries are cleared. For sorted 16760 * tables, only the entries known to contain data are cleared, 16761 * unless the force_all flag is on, in which case all entries 16762 * are cleared. The force_all flag is mainly intended for the first 16763 * initialization after a chip reset. 16764 */ 16765 16766 int 16767 soc_mem_clear(int unit, 16768 soc_mem_t mem, 16769 int copyno, 16770 int force_all) 16771 { 16772 int rv = SOC_E_NONE; 16773 #if defined(BCM_ESW_SUPPORT) 16774 int blk, index_min, index_max, index; 16775 #endif 16776 #if defined(BCM_FIREBOLT_SUPPORT) 16777 uint8 *vmap, *vmap1 = NULL; 16778 uint32 entry_dw, *cache; 16779 void *null_entry = soc_mem_entry_null(unit, mem); 16780 uint32 empty_entry[SOC_MAX_MEM_WORDS] = {0}; 16781 #if defined(INCLUDE_MEM_SCAN) && \ 16782 (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)) 16783 uint32 xy_null_entry[SOC_MAX_MEM_WORDS] = {0}; 16784 #endif /* INCLUDE_MEM_SCAN && (BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT) */ 16785 #endif /* BCM_FIREBOLT_SUPPORT */ 16786 16787 #ifdef BCM_TRIDENT_SUPPORT 16788 int(*pipe_select)(int, int, int) = NULL; 16789 int require_pipe_select = FALSE; 16790 #ifdef BCM_TRIDENT2_SUPPORT 16791 uint8 acc_type = 0; 16792 int tcam_protect_write = 0; 16793 int config_128b_entries = 0; 16794 #endif 16795 if (SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) { 16796 pipe_select = soc_trident_pipe_select; 16797 require_pipe_select = _soc_mem_clear_require_pipe_select(unit, mem); 16798 } 16799 #ifdef BCM_TRIDENT2_SUPPORT 16800 else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit)) { 16801 pipe_select = soc_trident2_pipe_select; 16802 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 16803 require_pipe_select = (acc_type == _SOC_ACC_TYPE_PIPE_SBS) ? TRUE : FALSE; 16804 } 16805 #endif 16806 else { 16807 pipe_select = NULL; 16808 } 16809 #endif 16810 _SOC_MEM_REPLACE_MEM(unit, mem); 16811 if (soc_mem_index_count(unit, mem) == 0) { 16812 return SOC_E_NONE; 16813 } 16814 16815 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE)); 16816 16817 if (SOC_HW_RESET(unit) && 16818 soc_mem_clearable_on_reset(unit, mem, copyno)) { 16819 return SOC_E_NONE; 16820 } 16821 16822 /* DISABLE_SBUS_MEMWR_PARITY_CHECK bit has to been cleared before return */ 16823 #if defined(BCM_TRIDENT2_SUPPORT) 16824 if (SOC_IS_TD2_TT2(unit) && (!SOC_IS_TOMAHAWKX(unit))) { 16825 soc_trident2_l3_memwr_parity_check(unit, mem, TRUE); 16826 } 16827 _soc_mem_clear_tcam_protect_clear_restore(unit, mem, 0, 16828 &tcam_protect_write, &config_128b_entries); 16829 #endif /* BCM_TRIDENT2_SUPPORT */ 16830 #if defined(BCM_TRIDENT3_SUPPORT) 16831 if (SOC_IS_TRIDENT3X(unit)) { 16832 (void)soc_trident3_l3_memwr_parity_check(unit, mem, TRUE); 16833 } 16834 #endif 16835 16836 #if defined(BCM_FIREBOLT_SUPPORT) 16837 if (SOC_IS_FBX(unit)) { 16838 if (!null_entry) { 16839 null_entry = empty_entry; 16840 } 16841 MEM_LOCK(unit, mem); 16842 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 16843 if (copyno != COPYNO_ALL && copyno != blk) { 16844 continue; 16845 } 16846 index_min = soc_mem_index_min(unit, mem); 16847 index_max = soc_mem_index_max(unit, mem); 16848 if (SOC_MEM_CLEAR_USE_DMA(unit)) { 16849 rv = _soc_xgs3_mem_clear_pipe(unit, mem, blk, null_entry); 16850 if (rv == SOC_E_UNAVAIL) { 16851 if (soc_mem_slamable(unit, mem, blk)) { 16852 rv = _soc_xgs3_mem_clear_slam(unit, mem, blk, null_entry); 16853 if (rv < 0) { 16854 goto check_cache; 16855 } 16856 #ifdef BCM_TRIDENT_SUPPORT 16857 if ((SOC_IS_TD_TT(unit) && !SOC_IS_TOMAHAWKX(unit)) && 16858 (require_pipe_select == TRUE) && (pipe_select != NULL)) { 16859 IP_ARBITER_LOCK(unit); 16860 /* Switch to Y-pipe */ 16861 (void)pipe_select(unit, TRUE, 1); 16862 (void)pipe_select(unit, FALSE, 1); 16863 rv = _soc_xgs3_mem_clear_slam(unit, mem, blk, null_entry); 16864 /* Restore to X-pipe */ 16865 (void)pipe_select(unit, TRUE, 0); 16866 (void)pipe_select(unit, FALSE, 0); 16867 IP_ARBITER_UNLOCK(unit); 16868 if (rv < 0) { 16869 goto check_cache; 16870 } 16871 } 16872 #endif 16873 } else { 16874 goto _clear_use_pio; 16875 } 16876 } 16877 if (rv < 0) { 16878 goto check_cache; 16879 } 16880 } else { 16881 _clear_use_pio: 16882 for (index = index_min; index <= index_max; index++) { 16883 /* Clear only index which are valid */ 16884 if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == FALSE) { 16885 if ((rv = soc_mem_write(unit, mem, blk, index, 16886 null_entry)) < 0) { 16887 LOG_ERROR(BSL_LS_SOC_SOCMEM, 16888 (BSL_META_U(unit, 16889 "soc_mem_clear: " 16890 "write %s.%s[%d] failed: %s\n"), 16891 SOC_MEM_UFNAME(unit, mem), 16892 SOC_BLOCK_NAME(unit, blk), 16893 index, soc_errmsg(rv))); 16894 goto done; 16895 } 16896 } 16897 } 16898 #ifdef BCM_TRIDENT_SUPPORT 16899 if ((SOC_IS_TD_TT(unit) && !SOC_IS_TOMAHAWKX(unit)) && 16900 (require_pipe_select == TRUE) && (pipe_select != NULL)) { 16901 IP_ARBITER_LOCK(unit); 16902 /* Switch to Y-pipe */ 16903 (void)pipe_select(unit, TRUE, 1); 16904 (void)pipe_select(unit, FALSE, 1); 16905 for (index = index_min; index <= index_max; index++) { 16906 /* Clear only index which are valid */ 16907 if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == FALSE) { 16908 if ((rv = soc_mem_write(unit, mem, blk, index, 16909 null_entry)) < 0) { 16910 LOG_ERROR(BSL_LS_SOC_SOCMEM, 16911 (BSL_META_U(unit, 16912 "soc_mem_clear: " 16913 "write %s.%s[%d] failed: %s\n"), 16914 SOC_MEM_UFNAME(unit, mem), 16915 SOC_BLOCK_NAME(unit, blk), 16916 index, soc_errmsg(rv))); 16917 /* Restore to X-pipe */ 16918 (void)pipe_select(unit, TRUE, 0); 16919 (void)pipe_select(unit, FALSE, 0); 16920 IP_ARBITER_UNLOCK(unit); 16921 goto done; 16922 } 16923 } 16924 } 16925 /* Restore to X-pipe */ 16926 (void)pipe_select(unit, TRUE, 0); 16927 (void)pipe_select(unit, FALSE, 0); 16928 IP_ARBITER_UNLOCK(unit); 16929 } 16930 #endif 16931 } 16932 check_cache: 16933 /* Update cache if active */ 16934 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 16935 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 16936 if (_SOC_MEM_CHK_L2_MEM(mem)) { 16937 if (mem == L2_ENTRY_1m) { 16938 vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[blk]; 16939 } else if (mem == L2_ENTRY_2m) { 16940 vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[blk]; 16941 } 16942 } 16943 entry_dw = soc_mem_entry_words(unit, mem); 16944 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit) && 16945 !SOC_WARM_BOOT(unit)) { 16946 #if defined(INCLUDE_MEM_SCAN) && \ 16947 (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)) 16948 if (soc_feature(unit, soc_feature_xy_tcam) && 16949 (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) && 16950 (!(SOC_MEM_INFO(unit, mem).flags & 16951 SOC_MEM_FLAG_EXT_CAM))) { 16952 _soc_mem_tcam_dm_to_xy(unit, mem, 1, null_entry, 16953 xy_null_entry, NULL); 16954 } 16955 #endif /* INCLUDE_MEM_SCAN && (BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT) */ 16956 for (index = index_min; index <= index_max; index++) { 16957 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) || 16958 SOC_HW_ACCESS_DISABLE(unit)) { 16959 CACHE_VMAP_CLR(vmap, index); 16960 } else if (vmap1) { 16961 CACHE_VMAP_CLR(vmap, index); 16962 if (mem == L2_ENTRY_1m) { 16963 CACHE_VMAP_CLR(vmap1, index/2); 16964 } else { 16965 CACHE_VMAP_CLR(vmap1, index*2); 16966 CACHE_VMAP_CLR(vmap1, index*2 + 1); 16967 } 16968 } else { 16969 sal_memcpy(cache + index * entry_dw, null_entry, 16970 entry_dw * 4); 16971 CACHE_VMAP_CLR(vmap, index); 16972 #if defined(INCLUDE_MEM_SCAN) && \ 16973 (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)) 16974 if (soc_feature(unit, soc_feature_xy_tcam) && 16975 (SOC_MEM_INFO(unit, mem).flags & 16976 SOC_MEM_FLAG_CAM) && 16977 (!(SOC_MEM_INFO(unit, mem).flags & 16978 SOC_MEM_FLAG_EXT_CAM))) { 16979 /* Update memscan TCAM cache if necessary */ 16980 soc_mem_scan_tcam_cache_update(unit, mem, 16981 index, index, 16982 xy_null_entry); 16983 } 16984 #endif /* INCLUDE_MEM_SCAN && (BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT) */ 16985 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 16986 #ifdef BCM_WARM_BOOT_SUPPORT 16987 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) || 16988 SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) { 16989 soc_mem_overlay_tcam_update(unit, mem, blk, 16990 index, index); 16991 } 16992 #endif 16993 #endif 16994 } 16995 } 16996 } 16997 } 16998 #ifdef BCM_TRIDENT2_SUPPORT 16999 /* For MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1, update software shadow table. */ 17000 if (SOC_IS_TRIDENT2(unit)) { 17001 if (mem == MMU_INTFI_XPIPE_FC_MAP_TBL0m || 17002 mem == MMU_INTFI_XPIPE_FC_MAP_TBL1m || 17003 mem == MMU_INTFI_YPIPE_FC_MAP_TBL0m || 17004 mem == MMU_INTFI_YPIPE_FC_MAP_TBL1m){ 17005 rv = soc_trident2_fc_map_shadow_clear(unit, mem); 17006 goto done; 17007 } 17008 } 17009 #endif 17010 goto done; /* Required if block iter does not execute even once */ 17011 } 17012 #endif /* BCM_FIREBOLT_SUPPORT */ 17013 17014 #if defined(BCM_XGS12_FABRIC_SUPPORT) 17015 if (copyno != COPYNO_ALL) { 17016 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 17017 } 17018 17019 MEM_LOCK(unit, mem); 17020 17021 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 17022 if (copyno != COPYNO_ALL && copyno != blk) { 17023 continue; 17024 } 17025 17026 index_min = soc_mem_index_min(unit, mem); 17027 index_max = soc_mem_index_max(unit, mem); 17028 17029 switch (mem) { 17030 #if defined(BCM_XGS_SWITCH_SUPPORT) 17031 case L3_IPMCm: 17032 #endif 17033 #ifdef BCM_XGS12_FABRIC_SUPPORT 17034 case MEM_UCm: 17035 case MEM_MCm: 17036 case MEM_VIDm: 17037 case MEM_IPMCm: 17038 #ifdef BCM_HERCULES15_SUPPORT 17039 case MEM_EGR_MODMAPm: 17040 case MEM_ING_MODMAPm: 17041 case MEM_ING_SRCMODBLKm: 17042 case MEM_TRUNK_PORT_POOLm: 17043 #endif /* BCM_HERCULES15_SUPPORT */ 17044 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 17045 #ifdef BCM_XGS_SWITCH_SUPPORT 17046 case EGR_MASKm: 17047 case MAC_BLOCKm: 17048 case PORT_TABm: 17049 case STG_TABm: 17050 case TRUNK_GROUPm: 17051 case TRUNK_BITMAPm: 17052 case TRUNK_EGR_MASKm: 17053 case VLAN_TABm: 17054 #endif /* BCM_XGS_SWITCH_SUPPORT */ 17055 /* NOTE: fall through from above */ 17056 /* Tables where all entries should be cleared to null value */ 17057 for (index = index_min; index <= index_max; index++) { 17058 if ((rv = soc_mem_write(unit, mem, blk, index, 17059 soc_mem_entry_null(unit, mem))) < 0) { 17060 LOG_ERROR(BSL_LS_SOC_SOCMEM, 17061 (BSL_META_U(unit, 17062 "soc_mem_clear: " 17063 "write %s.%s[%d] failed: %s\n"), 17064 SOC_MEM_UFNAME(unit, mem), 17065 SOC_BLOCK_NAME(unit, blk), 17066 index, soc_errmsg(rv))); 17067 goto done; 17068 } 17069 } 17070 break; 17071 #if defined(BCM_5690) || defined(BCM_5665) 17072 case GFILTER_FFPCOUNTERSm: 17073 case GFILTER_FFPPACKETCOUNTERSm: 17074 #if defined(BCM_5695) 17075 case GFILTER_FFP_IN_PROFILE_COUNTERSm: 17076 case GFILTER_FFP_OUT_PROFILE_COUNTERSm: 17077 #endif 17078 case GFILTER_METERINGm: 17079 #endif 17080 #if defined(BCM_5673) || defined(BCM_5674) 17081 case XFILTER_FFPCOUNTERSm: 17082 case XFILTER_FFPOPPACKETCOUNTERSm: 17083 case XFILTER_FFPIPPACKETCOUNTERSm: 17084 case XFILTER_FFPOPBYTECOUNTERSm: 17085 case XFILTER_FFPIPBYTECOUNTERSm: 17086 case XFILTER_METERINGm: 17087 #endif 17088 #if defined(BCM_5690) || defined(BCM_5665) || \ 17089 defined(BCM_5673) || defined(BCM_5674) 17090 if (soc_feature(unit, soc_feature_filter_metering)) { 17091 /* NOTE: fall through from above */ 17092 /* Tables where all entries should be cleared to null value */ 17093 for (index = index_min; index <= index_max; index++) { 17094 if ((rv = soc_mem_write(unit, mem, blk, index, 17095 soc_mem_entry_null(unit, 17096 mem))) < 0) { 17097 LOG_ERROR(BSL_LS_SOC_SOCMEM, 17098 (BSL_META_U(unit, 17099 "soc_mem_clear: " 17100 "write %s.%s[%d] failed: %s\n"), 17101 SOC_MEM_UFNAME(unit, mem), 17102 SOC_BLOCK_NAME(unit, blk), 17103 index, soc_errmsg(rv))); 17104 goto done; 17105 } 17106 } 17107 break; 17108 } /* else fall thru to default */ 17109 #endif /* BCM_XGS_SWITCH_SUPPORT */ 17110 default: 17111 LOG_ERROR(BSL_LS_SOC_SOCMEM, 17112 (BSL_META_U(unit, 17113 "soc_mem_clear: don't know how to clear %s\n"), 17114 SOC_MEM_UFNAME(unit, mem))); 17115 rv = SOC_E_PARAM; 17116 goto done; 17117 } 17118 } 17119 #endif /* XGS12_FABRIC */ 17120 17121 rv = SOC_E_NONE; 17122 goto done; 17123 17124 done: 17125 MEM_UNLOCK(unit, mem); 17126 17127 /* DISABLE_SBUS_MEMWR_PARITY_CHECK bit has to be cleared before return */ 17128 #if defined(BCM_TRIDENT2_SUPPORT) 17129 if (SOC_IS_TD2_TT2(unit) && (!SOC_IS_TOMAHAWKX(unit))) { 17130 soc_trident2_l3_memwr_parity_check(unit, mem, FALSE); 17131 } 17132 _soc_mem_clear_tcam_protect_clear_restore(unit, mem, 1, 17133 &tcam_protect_write, &config_128b_entries); 17134 #endif /* BCM_TRIDENT2_SUPPORT */ 17135 #if defined(BCM_TRIDENT3_SUPPORT) 17136 if (SOC_IS_TRIDENT3X(unit)) { 17137 (void)soc_trident3_l3_memwr_parity_check(unit, mem, FALSE); 17138 } 17139 #endif 17140 17141 LOG_INFO(BSL_LS_SOC_SOCMEM, 17142 (BSL_META_U(unit, 17143 "soc_mem_clear: unit %d memory %s.%s returns %s\n"), 17144 unit, SOC_MEM_UFNAME(unit, mem), 17145 SOC_BLOCK_NAME(unit, copyno), soc_errmsg(rv))); 17146 17147 return rv; 17148 } 17149 17150 /* 17151 * Function: 17152 * _soc_mem_search 17153 * Purpose: 17154 * Helper function for soc_mem_search. Does the raw search 17155 * without worrying about special memory cases. 17156 * Parameters: 17157 * See soc_mem_search, below. 17158 * Returns: 17159 * SOC_E_NOT_FOUND 17160 * Entry not found: in this case, if 17161 * table is sorted, then index_ptr gets the 17162 * location in which the entry should be 17163 * inserted. 17164 * SOC_E_NONE Entry is found: index_ptr gets location 17165 * SOC_E_XXX If internal error occurs 17166 * Notes: 17167 * See soc_mem_search, below. 17168 */ 17169 17170 STATIC int 17171 _soc_mem_search(int unit, 17172 soc_mem_t mem, 17173 int copyno, 17174 int *index_ptr, 17175 void *key_data, 17176 void *entry_data, 17177 int lowest_match) 17178 { 17179 int base, count, mid, last_read = -1; 17180 int rv, r; 17181 17182 /* 17183 * Establish search range within table. For filter, optimize using 17184 * cached start/count of rule set for mask specified by FSEL. Note 17185 * that all rules using a given FSEL are necessarily contiguous. 17186 */ 17187 base = soc_mem_index_min(unit, mem); 17188 count = soc_mem_entries(unit, mem, copyno); 17189 17190 while (count > 0) { 17191 mid = base + count / 2; 17192 17193 if ((rv = soc_mem_read(unit, mem, copyno, mid, entry_data)) < 0) { 17194 LOG_ERROR(BSL_LS_SOC_SOCMEM, 17195 (BSL_META_U(unit, 17196 "soc_mem_search: read %s.%s[%d] failed\n"), 17197 SOC_MEM_UFNAME(unit, mem), 17198 SOC_BLOCK_NAME(unit, copyno), mid)); 17199 return rv; 17200 } 17201 17202 last_read = mid; 17203 17204 r = soc_mem_compare_key(unit, mem, key_data, entry_data); 17205 17206 if (r == 0) { 17207 if (lowest_match) { 17208 count = count / 2; /* Must treat same as < 0 */ 17209 } else { 17210 if (index_ptr != NULL) { 17211 *index_ptr = mid; /* Don't care if it's lowest match */ 17212 } 17213 return SOC_E_NONE; /* Found */ 17214 } 17215 } else if (r < 0) { 17216 count = count / 2; 17217 } else { 17218 base = mid + 1; 17219 count = (count - 1) / 2; 17220 } 17221 } 17222 17223 *index_ptr = base; 17224 17225 /* 17226 * base is the expected position of the entry (insertion point). 17227 * If lowest_match is true, we may have actually found it, and 17228 * we have to check again here. 17229 */ 17230 17231 if (lowest_match && base <= soc_mem_index_max(unit, mem)) { 17232 if (last_read != base && /* Optimize out read if possible */ 17233 (rv = soc_mem_read(unit, mem, copyno, base, entry_data)) < 0) { 17234 LOG_ERROR(BSL_LS_SOC_SOCMEM, 17235 (BSL_META_U(unit, 17236 "soc_mem_search: read %s.%s[%d] failed\n"), 17237 SOC_MEM_UFNAME(unit, mem), 17238 SOC_BLOCK_NAME(unit, copyno), base)); 17239 return rv; 17240 } 17241 17242 if (soc_mem_compare_key(unit, mem, key_data, entry_data) == 0) { 17243 return SOC_E_NONE; /* Found */ 17244 } 17245 } 17246 17247 /* If bitmap conflict found, return SOC_E_CONFIG */ 17248 return SOC_E_NOT_FOUND; /* No error; not found */ 17249 } 17250 17251 /* Special hash mem lookup routine used only in context of generic lookup failure 17252 due to parity/ecc error in order to do bank specific lookups or accelerate 17253 mem cache indexing by fetching bucket index from h/w */ 17254 STATIC int 17255 _soc_mem_bank_lookup(int unit, soc_mem_t mem, int copyno, int32 banks, 17256 void *key, void *result, int *index_ptr) 17257 { 17258 schan_msg_t schan_msg; 17259 int rv, entry_dw, allow_intr=0; 17260 uint8 at; 17261 int type, index, err_info=0; 17262 uint32 *data; 17263 int src_blk, dst_blk, acc_type, data_byte_len; 17264 int opcode, nack; 17265 uint32 bank_ignore_mask; 17266 17267 entry_dw = soc_mem_entry_words(unit, mem); 17268 17269 schan_msg_clear(&schan_msg); 17270 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 17271 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 17272 dst_blk = SOC_BLOCK2SCH(unit, copyno); 17273 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 17274 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 17275 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 17276 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 17277 (mem == L3_ENTRY_IPV6_MULTICASTm) 17278 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 17279 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 17280 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 17281 #endif 17282 #if defined(BCM_TOMAHAWK3_SUPPORT) 17283 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 17284 || (mem == L3_TUNNEL_QUADm) 17285 #endif 17286 #if defined(BCM_TOMAHAWK_SUPPORT) 17287 || _SOC_MEM_CHK_FPEM_MEM(mem) 17288 #endif 17289 ))) { 17290 /* don't set bank id in cos */ 17291 bank_ignore_mask = 0; 17292 } else { 17293 bank_ignore_mask = banks & 0x3; 17294 } 17295 data_byte_len = entry_dw * 4; 17296 17297 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 17298 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 17299 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 17300 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 17301 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 17302 (mem == L3_ENTRY_IPV6_MULTICASTm) 17303 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 17304 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 17305 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 17306 #endif 17307 #if defined(BCM_TOMAHAWK3_SUPPORT) 17308 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 17309 || (mem == L3_TUNNEL_QUADm) 17310 #endif 17311 #if defined(BCM_TOMAHAWK_SUPPORT) 17312 || _SOC_MEM_CHK_FPEM_MEM(mem) 17313 #endif 17314 ))) { 17315 /* set bank ignore mask in lower 20 bits */ 17316 if (banks && banks != SOC_MEM_HASH_BANK_ALL) { 17317 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 17318 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED); 17319 } else { 17320 #ifdef BCM_TRIUMPH3_SUPPORT 17321 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks); 17322 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM); 17323 #endif /* BCM_TRIUMPH3_SUPPORT */ 17324 } 17325 } 17326 } 17327 17328 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG, 17329 dst_blk, src_blk, acc_type, data_byte_len, 0, 17330 bank_ignore_mask); 17331 17332 /* Fill in entry data */ 17333 sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4); 17334 17335 if (SOC_IS_SAND(unit)) { 17336 allow_intr = 1; 17337 } 17338 17339 /* 17340 * Execute S-Channel "lookup insert" command packet consisting of 17341 * (header word + address word + entry_dw), and read back 17342 * (header word + response word + entry_dw) data words. 17343 */ 17344 17345 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 17346 17347 /* Check result */ 17348 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 17349 NULL, NULL, &nack); 17350 if (opcode != TABLE_LOOKUP_DONE_MSG) { 17351 LOG_ERROR(BSL_LS_SOC_SOCMEM, 17352 (BSL_META_U(unit, 17353 "soc_mem_bank_lookup: " 17354 "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n"))); 17355 soc_schan_dump(unit, &schan_msg, entry_dw + 2); 17356 return SOC_E_INTERNAL; 17357 } 17358 17359 if (soc_feature(unit, soc_feature_new_sbus_format) && 17360 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 17361 type = schan_msg.genresp_v2.response.type; 17362 err_info = schan_msg.genresp_v2.response.err_info; 17363 index = schan_msg.genresp_v2.response.index; 17364 data = schan_msg.genresp_v2.data; 17365 } else { 17366 type = schan_msg.genresp.response.type; 17367 index = schan_msg.genresp.response.index; 17368 data = schan_msg.genresp.data; 17369 } 17370 if ((nack != 0) || (rv == SOC_E_FAIL)) { 17371 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 17372 rv = SOC_E_NOT_FOUND; 17373 } else { 17374 rv = SOC_E_FAIL; 17375 17376 if (!(SOC_IS_TRIUMPH3(unit) || (SOC_IS_TRIDENT2(unit) 17377 || (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TITAN2PLUS(unit))) 17378 || (SOC_IS_TOMAHAWKX(unit)) || SOC_IS_APACHE(unit) 17379 || SOC_IS_TRIDENT3X(unit))) { 17380 index = schan_msg.dwords[2] & 0xffff; 17381 } 17382 if (err_info == SCHAN_GEN_RESP_ERR_INFO_ERROR_IN_LP_TABLE) { 17383 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 17384 "_soc_mem_bank_lookup: Encountered error on LP table " 17385 "for memory %s, banks[0x%0x], err_rsp_index[%d] !!\n"), 17386 SOC_MEM_NAME(unit, mem), banks, index)); 17387 #if defined(BCM_TOMAHAWK_SUPPORT) 17388 if (SOC_IS_TOMAHAWKX(unit)) { 17389 if (SOC_FAILURE(soc_th_lp_to_fv_index_remap(unit, mem, &index))) { 17390 return SOC_E_INTERNAL; 17391 } 17392 } 17393 #endif 17394 } 17395 } 17396 } else { 17397 if (result != NULL) { 17398 sal_memcpy(result, data, entry_dw * sizeof(uint32)); 17399 } 17400 } 17401 *index_ptr = index; 17402 17403 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 17404 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 17405 "Bank lookup table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem), 17406 banks)); 17407 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 17408 soc_mem_entry_dump(unit, mem, data, BSL_VERBOSE|BSL_LS_SOC_COMMON); 17409 } 17410 if (SOC_FAILURE(rv)) { 17411 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 17412 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 17413 " Not found\n"))); 17414 } else { 17415 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 17416 " Fail, bkt:%d\n"), index)); 17417 } 17418 } else { 17419 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 17420 " (index=%d)\n"), index)); 17421 } 17422 } 17423 17424 return rv; 17425 } 17426 17427 #ifdef BCM_TRIDENT2_SUPPORT 17428 STATIC INLINE int 17429 _soc_mem_shared_hash_entries_per_bkt(int unit, soc_mem_t mem) 17430 { 17431 #if defined(BCM_TRIDENT3_SUPPORT) 17432 if (SOC_IS_TRIDENT3X(unit)) { 17433 return 4; 17434 } 17435 #endif /* defined(BCM_TRIDENT3_SUPPORT) */ 17436 switch(mem) { 17437 case L2Xm: 17438 case L3_ENTRY_ONLYm: 17439 case L3_ENTRY_IPV4_UNICASTm: 17440 case L3_ENTRY_SINGLEm: 17441 case L3_TUNNEL_SINGLEm: 17442 case L3_ENTRY_ONLY_SINGLEm: 17443 case VLAN_XLATE_1_SINGLEm: 17444 case VLAN_XLATE_2_SINGLEm: 17445 case VLAN_XLATE_1_DOUBLEm: 17446 case VLAN_XLATE_2_DOUBLEm: 17447 case EGR_VLAN_XLATE_1_SINGLEm: 17448 case EGR_VLAN_XLATE_2_SINGLEm: 17449 case EGR_VLAN_XLATE_1_DOUBLEm: 17450 case EGR_VLAN_XLATE_2_DOUBLEm: 17451 case MPLS_ENTRY_SINGLEm: 17452 return 4; 17453 case L3_ENTRY_IPV6_UNICASTm: 17454 case L3_ENTRY_IPV4_MULTICASTm: 17455 case MPLS_ENTRYm: 17456 return 2; 17457 case L3_ENTRY_IPV6_MULTICASTm: 17458 return 1; 17459 case L3_ENTRY_DOUBLEm: 17460 case L3_TUNNEL_DOUBLEm: 17461 case EXACT_MATCH_2m: 17462 case EXACT_MATCH_2_PIPE0m: 17463 case EXACT_MATCH_2_PIPE1m: 17464 case EXACT_MATCH_2_PIPE2m: 17465 case EXACT_MATCH_2_PIPE3m: 17466 #ifdef BCM_TOMAHAWK3_SUPPORT 17467 if (SOC_IS_TOMAHAWK3(unit)) { 17468 return 2; 17469 } else 17470 #endif 17471 { 17472 return 4; 17473 } 17474 17475 case EXACT_MATCH_4m: 17476 case EXACT_MATCH_4_PIPE0m: 17477 case EXACT_MATCH_4_PIPE1m: 17478 case EXACT_MATCH_4_PIPE2m: 17479 case EXACT_MATCH_4_PIPE3m: 17480 case L3_ENTRY_QUADm: 17481 case L3_TUNNEL_QUADm: 17482 #ifdef BCM_TOMAHAWK3_SUPPORT 17483 if (SOC_IS_TOMAHAWK3(unit)) { 17484 return 1; 17485 } else 17486 #endif 17487 { 17488 return 4; 17489 } 17490 default: 17491 return 4; 17492 } 17493 } 17494 #endif /* BCM_TRIDENT2_SUPPORT */ 17495 17496 STATIC int 17497 _soc_mem_hash_entries_per_bkt(int unit, soc_mem_t mem) 17498 { 17499 if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) { 17500 if (mem == L2_ENTRY_2m || mem == L3_ENTRY_2m || mem == VLAN_XLATE_EXTDm 17501 || mem == MPLS_ENTRY_EXTDm) { 17502 return 2; 17503 } else if (mem == L3_ENTRY_4m) { 17504 return 1; 17505 } else { 17506 return 4; 17507 } 17508 } 17509 #if defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 17510 else if (soc_feature(unit, soc_feature_hr2_dual_hash) || 17511 SOC_IS_KATANA2(unit) || SOC_IS_TRIDENT(unit)) { 17512 switch (mem) { 17513 case L3_ENTRY_ONLYm: 17514 case L3_ENTRY_IPV4_UNICASTm: 17515 return 8; 17516 case L2Xm: 17517 case L3_ENTRY_IPV6_UNICASTm: 17518 case L3_ENTRY_IPV4_MULTICASTm: 17519 return 4; 17520 case L3_ENTRY_IPV6_MULTICASTm: 17521 return 2; 17522 default: 17523 return 4; 17524 } 17525 } 17526 #endif /* BCM_HURRICANE2_SUPPORT */ 17527 #ifdef BCM_TRIDENT2_SUPPORT 17528 else { 17529 return _soc_mem_shared_hash_entries_per_bkt(unit, mem); 17530 } 17531 #endif /* BCM_TRIDENT2_SUPPORT */ 17532 return 4; 17533 } 17534 17535 STATIC int 17536 _soc_hash_mem_entry_base_get(int unit, soc_mem_t mem, int bank, int base_index, 17537 int num_entries) 17538 { 17539 if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) { 17540 return base_index * num_entries; 17541 } else if (soc_feature(unit, soc_feature_shared_hash_mem)) { 17542 if (((mem == L2Xm) || 17543 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 17544 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 17545 (mem == L3_ENTRY_IPV6_MULTICASTm))) { 17546 return base_index * num_entries; 17547 } else { 17548 return (base_index/num_entries) * num_entries; 17549 } 17550 } else { 17551 num_entries *= 2; 17552 if (bank) { 17553 return ((base_index * num_entries ) + 4); 17554 } else { 17555 return base_index * num_entries; 17556 } 17557 } 17558 } 17559 17560 STATIC void 17561 _soc_mem_entry_get_key(int unit, soc_mem_t mem, void *entry, void *key) 17562 { 17563 #ifdef BCM_ISM_SUPPORT 17564 if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) { 17565 /* Use ism routines */ 17566 (void)soc_gen_key_from_entry(unit, mem, entry, key); 17567 } else 17568 #endif /* BCM_ISM_SUPPORT */ 17569 { 17570 /* Else use key field */ 17571 if (SOC_MEM_FIELD_VALID(unit, mem, KEYf)) { 17572 uint32 key_buff[SOC_MAX_MEM_FIELD_WORDS]; 17573 soc_mem_field_get(unit, mem, entry, KEYf, key_buff); 17574 soc_mem_field_set(unit, mem, key, KEYf, key_buff); 17575 } else { 17576 LOG_ERROR(BSL_LS_SOC_SOCMEM, 17577 (BSL_META_U(unit, 17578 "Unable to retreive key for %s.\n"), 17579 SOC_MEM_NAME(unit, mem))); 17580 } 17581 } 17582 } 17583 17584 17585 /* NOTE: index1 is used for legacy dual hash only */ 17586 STATIC int 17587 _soc_mem_cache_lookup(int unit, soc_mem_t mem, int copyno, int32 banks, 17588 void *key, void *result, int index0, int index1, 17589 int *index_ptr, uint32 *cache, uint8 *vmap) 17590 { 17591 int i, rc; 17592 uint32 bmap = 0; 17593 uint32 *entry_ptr, match_key[SOC_MAX_MEM_WORDS]; 17594 uint32 entry_dw = soc_mem_entry_words(unit, mem); 17595 #ifdef BCM_ISM_SUPPORT 17596 _soc_ism_mem_banks_t ism_banks; 17597 #endif /* BCM_ISM_SUPPORT */ 17598 17599 #ifdef BCM_ISM_SUPPORT 17600 if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) { 17601 rc = soc_ism_get_banks_for_mem(unit, mem, ism_banks.banks, 17602 ism_banks.bank_size, &ism_banks.count); 17603 if (SOC_FAILURE(rc) || ism_banks.count == 0) { 17604 if (index_ptr) { 17605 *index_ptr = -1; 17606 } 17607 return SOC_E_NOT_FOUND; 17608 } 17609 for (i = 0; i < ism_banks.count; i++) { 17610 bmap |= 1 << ism_banks.banks[i]; 17611 } 17612 bmap &= banks; 17613 } else 17614 #endif /* BCM_ISM_SUPPORT */ 17615 #ifdef BCM_TRIDENT2_SUPPORT 17616 if (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 17617 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 17618 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 17619 (mem == L3_ENTRY_IPV6_MULTICASTm) 17620 #if defined(BCM_TOMAHAWK_SUPPORT) 17621 || _SOC_MEM_CHK_FPEM_MEM(mem) 17622 #endif 17623 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 17624 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) || 17625 (mem == L3_ENTRY_QUADm) 17626 #endif 17627 )) { 17628 #ifdef BCM_APACHE_SUPPORT 17629 if (SOC_IS_APACHE(unit)) { 17630 SOC_IF_ERROR_RETURN 17631 (soc_apache_hash_bank_phy_bitmap_get(unit, mem, &bmap)); 17632 } else 17633 #endif /* BCM_APACHE_SUPPORT */ 17634 #ifdef BCM_TOMAHAWK_SUPPORT 17635 if (SOC_IS_TOMAHAWKX(unit)) { 17636 #ifdef BCM_TOMAHAWK3_SUPPORT 17637 if (SOC_IS_TOMAHAWK3(unit)) { 17638 SOC_IF_ERROR_RETURN 17639 (soc_tomahawk3_hash_bank_phy_bitmap_get(unit, mem, &bmap)); 17640 } else 17641 #endif /* BCM_TOMAHAWK3_SUPPORT */ 17642 { 17643 SOC_IF_ERROR_RETURN 17644 (soc_tomahawk_hash_bank_phy_bitmap_get(unit, mem, &bmap)); 17645 } 17646 } else 17647 #endif /* BCM_TOMAHAWK_SUPPORT */ 17648 #ifdef BCM_HELIX5_SUPPORT 17649 if (SOC_IS_HELIX5(unit)) { 17650 SOC_IF_ERROR_RETURN 17651 (soc_hx5_hash_bank_phy_bitmap_get(unit, mem, &bmap)); 17652 } else 17653 #endif /* BCM_HELIX5_SUPPORT */ 17654 #ifdef BCM_TRIDENT3_SUPPORT 17655 if (SOC_IS_TRIDENT3X(unit)) { 17656 SOC_IF_ERROR_RETURN 17657 (soc_td3_hash_bank_phy_bitmap_get(unit, mem, &bmap)); 17658 } else 17659 #endif /* BCM_TRIDENT3_SUPPORT */ 17660 { 17661 SOC_IF_ERROR_RETURN 17662 (soc_trident2_hash_bank_bitmap_get(unit, mem, &bmap)); 17663 } 17664 /* For L2X and L3_ENTRY tables, if banks is zero, it means all banks 17665 * banks should be either specific bank bitmap or an indication that 17666 * specifying all banks. 17667 */ 17668 (banks) ? bmap &= banks : bmap; 17669 } else 17670 #endif /* BCM_TRIDENT2_SUPPORT */ 17671 { /* Dual hash */ 17672 bmap = 0x3; 17673 (banks) ? bmap &= banks : bmap; 17674 } 17675 /* Issue lookups on all specified & applicable banks */ 17676 if (bmap) { 17677 int e, entries, entry_base, match, index = -1; 17678 17679 entries = _soc_mem_hash_entries_per_bkt(unit, mem); 17680 for (i = 0; i < 32; i++) { 17681 if (bmap & (1 << i)) { 17682 if (index1 == -1) { 17683 rc = _soc_mem_bank_lookup(unit, mem, copyno, 1 << i, key, 17684 result, &index); 17685 } else { /* Legacy dual hash: bucket indexes are already known */ 17686 index = i ? index1 : index0; 17687 rc = SOC_E_FAIL; 17688 } 17689 if (SOC_FAILURE(rc)) { /* Case where correction has not yet happened */ 17690 if (rc == SOC_E_NOT_FOUND) { 17691 continue; 17692 } else if (rc == SOC_E_INTERNAL) { 17693 return rc; 17694 } else if (rc == SOC_E_FAIL) { 17695 /* Check and compare key with all entries in the bucket */ 17696 if (!SOC_IS_TD2_TT2(unit)) { 17697 /* All other devices return the bucket */ 17698 LOG_VERBOSE(BSL_LS_SOC_COMMON, 17699 (BSL_META_U(unit, 17700 "Check in bucket: %d\n"), 17701 index)); 17702 entry_base = _soc_hash_mem_entry_base_get(unit, mem, i, 17703 index, entries); 17704 } else { 17705 /* TD and TD2 return the index */ 17706 if (mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm 17707 #if defined(BCM_TOMAHAWK_SUPPORT) 17708 || mem == EXACT_MATCH_2m 17709 || mem == EXACT_MATCH_2_PIPE0m 17710 || mem == EXACT_MATCH_2_PIPE1m 17711 || mem == EXACT_MATCH_2_PIPE2m 17712 || mem == EXACT_MATCH_2_PIPE3m 17713 #endif /* BCM_TOMAHAWK_SUPPORT */ 17714 #if defined(BCM_TRIDENT3_SUPPORT) 17715 || mem == VLAN_XLATE_1_DOUBLEm 17716 || mem == VLAN_XLATE_2_DOUBLEm 17717 || mem == EGR_VLAN_XLATE_1_DOUBLEm 17718 || mem == EGR_VLAN_XLATE_2_DOUBLEm 17719 #endif 17720 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 17721 || mem == L3_ENTRY_DOUBLEm 17722 #endif /* BCM_TRIDENT3_SUPPORT */ 17723 ) { 17724 index = index/2; 17725 } else if (mem == L3_ENTRY_IPV6_MULTICASTm 17726 #if defined(BCM_TOMAHAWK_SUPPORT) 17727 || mem == EXACT_MATCH_4m 17728 || mem == EXACT_MATCH_4_PIPE0m 17729 || mem == EXACT_MATCH_4_PIPE1m 17730 || mem == EXACT_MATCH_4_PIPE2m 17731 || mem == EXACT_MATCH_4_PIPE3m 17732 #endif /* BCM_TOMAHAWK_SUPPORT */ 17733 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 17734 || mem == L3_ENTRY_QUADm 17735 #endif 17736 ) { 17737 index = index/4; 17738 } else if (SOC_IS_TRIDENT3X(unit)&& 17739 (mem == SUBPORT_ID_TO_SGPP_MAPm || 17740 mem == ING_DNAT_ADDRESS_TYPEm || 17741 mem == ING_VP_VLAN_MEMBERSHIPm || 17742 mem == EGR_VP_VLAN_MEMBERSHIPm)) { 17743 /* 17744 * When SER error exist on thers memories on TD3 17745 * SBUS lookup will return ECC view index in RSP_WRD 17746 */ 17747 index *= 2; 17748 } 17749 LOG_VERBOSE(BSL_LS_SOC_COMMON, 17750 (BSL_META_U(unit, 17751 "Check at index: %d\n"), 17752 index)); 17753 entry_base = index; 17754 } 17755 LOG_VERBOSE(BSL_LS_SOC_COMMON, 17756 (BSL_META_U(unit, 17757 "Base entry: %d\n"), entry_base)); 17758 for (e = 0; e < entries; e++) { 17759 /* Try with only cached entries */ 17760 if (CACHE_VMAP_TST(vmap, entry_base+e)) { 17761 match = 0; 17762 entry_ptr = cache + ((entry_base+e) * entry_dw); 17763 sal_memset(match_key, 0, sizeof(match_key)); 17764 /* If match found then return else continue */ 17765 LOG_VERBOSE(BSL_LS_SOC_COMMON, 17766 (BSL_META_U(unit, 17767 "Check cached entry at " 17768 "index: %d\n"), entry_base+e)); 17769 if (soc_feature(unit, soc_feature_ism_memory) && 17770 soc_mem_is_mview(unit, mem) && !(mem == L2_ENTRY_1m || 17771 mem == L2_ENTRY_2m)) { /* L2 key compare routine exists for TR3 */ 17772 uint32 entry_key[SOC_MAX_MEM_WORDS]; 17773 17774 sal_memset(entry_key, 0, sizeof(entry_key)); 17775 _soc_mem_entry_get_key(unit, mem, entry_ptr, match_key); 17776 _soc_mem_entry_get_key(unit, mem, key, entry_key); 17777 if (sal_memcmp(entry_key, match_key, entry_dw * 4)) { 17778 continue; 17779 } else { 17780 match = 1; 17781 } 17782 } else if (soc_mem_cmp_fn(unit, mem)) { 17783 if (soc_mem_compare_key(unit, mem, entry_ptr, key)) { 17784 continue; 17785 } else { 17786 match = 1; 17787 } 17788 } else { 17789 uint32 entry_key[SOC_MAX_MEM_WORDS]; 17790 17791 sal_memset(entry_key, 0, sizeof(entry_key)); 17792 _soc_mem_entry_get_key(unit, mem, entry_ptr, match_key); 17793 _soc_mem_entry_get_key(unit, mem, key, entry_key); 17794 if (sal_memcmp(entry_key, match_key, entry_dw * 4)) { 17795 continue; 17796 } else { 17797 match = 1; 17798 } 17799 } 17800 if (match) { 17801 if (result) { 17802 sal_memcpy(result, entry_ptr, entry_dw * 4); 17803 } 17804 if (index_ptr) { 17805 *index_ptr = entry_base+e; 17806 } 17807 return SOC_E_NONE; 17808 } 17809 } 17810 } 17811 } 17812 } else { /* Case where correction completes before this routine */ 17813 if (index_ptr) { 17814 *index_ptr = index; 17815 } 17816 return SOC_E_NONE; 17817 } 17818 } 17819 } 17820 } 17821 if (index_ptr) { 17822 *index_ptr = -1; 17823 } 17824 return SOC_E_NOT_FOUND; 17825 } 17826 17827 /* 17828 * Function: 17829 * soc_mem_generic_lookup 17830 * Purpose: 17831 * Send a lookup message over the S-Channel and receive the response. 17832 * Parameters: 17833 * unit - StrataSwitch unit # 17834 * banks - For dual hashing, which halves are selected (inverted) 17835 * Note: used to create a bitmap for ISM mems. (All banks: -1) 17836 * key - entry to look up 17837 * result - entry to receive entire found entry 17838 * index_ptr (OUT) - If found, receives table index where found 17839 * Returns: 17840 * SOC_E_INTERNAL if retries exceeded or other internal error 17841 * SOC_E_NOT_FOUND if the entry is not found. 17842 * SOC_E_NONE (0) on success (entry found): 17843 */ 17844 17845 int 17846 soc_mem_generic_lookup(int unit, soc_mem_t mem, int copyno, int32 banks, 17847 void *key, void *result, int *index_ptr) 17848 { 17849 schan_msg_t schan_msg; 17850 int rv, entry_dw, allow_intr=0; 17851 uint8 at; 17852 int type, index, index_valid, err_info=0; 17853 uint32 *data; 17854 int src_blk, dst_blk, acc_type, data_byte_len; 17855 int opcode, nack; 17856 uint32 bank_ignore_mask; 17857 #ifdef BCM_TRIUMPH_SUPPORT 17858 int rv1 = SOC_E_NONE; 17859 #endif 17860 #ifdef BCM_TRIDENT3_SUPPORT 17861 soc_mem_t phy_mem; 17862 #endif 17863 #if defined(BCM_GREYHOUND2_SUPPORT) 17864 uint32 key_type = 0; 17865 #endif /* BCM_GREYHOUND2_SUPPORT */ 17866 #ifdef BCM_TOMAHAWK3_SUPPORT 17867 int j = 0, k = 0, l = 0; 17868 schan_msg_t schan_msg_dupl; 17869 uint16 dev_id; 17870 uint8 rev_id; 17871 int dw = 0; 17872 uint32 *entry = NULL; 17873 void *entry_data1; 17874 int entry_size; 17875 17876 soc_cm_get_id(unit, &dev_id, &rev_id); 17877 #endif 17878 #ifdef BCM_TRIDENT3_SUPPORT 17879 if (soc_feature(unit, soc_feature_flex_flow)) { 17880 if (SOC_MEM_IS_VIEW(unit, mem)) { 17881 rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem); 17882 if (rv != SOC_E_NONE) { 17883 return rv; 17884 } 17885 mem = phy_mem; 17886 } 17887 } 17888 #endif 17889 17890 _SOC_MEM_REPLACE_MEM(unit, mem); 17891 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 17892 assert(SOC_MEM_IS_VALID(unit, mem)); 17893 assert(soc_attached(unit)); 17894 17895 if (copyno == MEM_BLOCK_ANY) { 17896 /* coverity[overrun-local : FALSE] */ 17897 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 17898 } 17899 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 17900 LOG_WARN(BSL_LS_SOC_SOCMEM, 17901 (BSL_META_U(unit, 17902 "soc_mem_generic_lookup: invalid block %d for memory %s\n"), 17903 copyno, SOC_MEM_NAME(unit, mem))); 17904 return SOC_E_PARAM; 17905 } 17906 17907 #if defined(BCM_GREYHOUND2_SUPPORT) 17908 if (soc_feature(unit, soc_feature_vxlan_lite_riot) && (mem == L2Xm)) { 17909 key_type = soc_mem_field32_get(unit, mem, key, KEY_TYPEf); 17910 /* Use SW to lookup a L2 entry when key_type is VFI_MULTICAST */ 17911 if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) { 17912 return soc_mem_gh2_l2_sw_lookup(unit, mem, copyno, banks, 17913 key, result, index_ptr); 17914 } 17915 } 17916 #endif /* BCM_GREYHOUND2_SUPPORT */ 17917 17918 entry_dw = soc_mem_entry_words(unit, mem); 17919 17920 MEM_LOCK(unit, mem); 17921 #if defined(BCM_TRIUMPH3_SUPPORT) 17922 if (soc_feature(unit, soc_feature_esm_correction) && 17923 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 17924 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 17925 SOC_ESM_LOCK(unit); 17926 } 17927 #endif 17928 schan_msg_clear(&schan_msg); 17929 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 17930 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 17931 dst_blk = SOC_BLOCK2SCH(unit, copyno); 17932 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 17933 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 17934 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 17935 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 17936 (mem == L3_ENTRY_IPV6_MULTICASTm) 17937 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 17938 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 17939 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 17940 #endif 17941 #if defined(BCM_TOMAHAWK3_SUPPORT) 17942 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 17943 || (mem == L3_TUNNEL_QUADm) 17944 #endif 17945 #if defined(BCM_TRIDENT3_SUPPORT) 17946 || (mem == VLAN_XLATE_1_SINGLEm) 17947 || (mem == VLAN_XLATE_1_DOUBLEm) 17948 || (mem == EGR_VLAN_XLATE_1_SINGLEm) 17949 || (mem == EGR_VLAN_XLATE_1_DOUBLEm) 17950 || (mem == VLAN_XLATE_2_SINGLEm) 17951 || (mem == VLAN_XLATE_2_DOUBLEm) 17952 || (mem == EGR_VLAN_XLATE_2_SINGLEm) 17953 || (mem == EGR_VLAN_XLATE_2_DOUBLEm) 17954 #endif 17955 #if defined(BCM_TOMAHAWK_SUPPORT) 17956 || _SOC_MEM_CHK_FPEM_MEM(mem) 17957 #endif 17958 ))) { 17959 /* don't set bank id in cos */ 17960 bank_ignore_mask = 0; 17961 } else { 17962 bank_ignore_mask = banks & 0x3; 17963 } 17964 data_byte_len = entry_dw * 4; 17965 17966 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 17967 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 17968 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 17969 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 17970 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 17971 (mem == L3_ENTRY_IPV6_MULTICASTm) 17972 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 17973 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 17974 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 17975 #endif 17976 #if defined(BCM_TOMAHAWK3_SUPPORT) 17977 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 17978 || (mem == L3_TUNNEL_QUADm) 17979 #endif 17980 #if defined(BCM_TRIDENT3_SUPPORT) 17981 || (mem == VLAN_XLATE_1_SINGLEm) 17982 || (mem == VLAN_XLATE_1_DOUBLEm) 17983 || (mem == EGR_VLAN_XLATE_1_SINGLEm) 17984 || (mem == EGR_VLAN_XLATE_1_DOUBLEm) 17985 || (mem == VLAN_XLATE_2_SINGLEm) 17986 || (mem == VLAN_XLATE_2_DOUBLEm) 17987 || (mem == EGR_VLAN_XLATE_2_SINGLEm) 17988 || (mem == EGR_VLAN_XLATE_2_DOUBLEm) 17989 || (mem == MPLS_ENTRYm) 17990 #endif 17991 #if defined(BCM_TOMAHAWK_SUPPORT) 17992 || _SOC_MEM_CHK_FPEM_MEM(mem) 17993 #endif 17994 ))) { 17995 /* set bank ignore mask in lower 20 bits */ 17996 if (banks && banks != SOC_MEM_HASH_BANK_ALL) { 17997 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 17998 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED); 17999 } else { 18000 #ifdef BCM_TRIUMPH3_SUPPORT 18001 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks); 18002 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM); 18003 #endif /* BCM_TRIUMPH3_SUPPORT */ 18004 } 18005 } 18006 } 18007 18008 /* BCM56960 supports 2 different modes for lookup 18009 * Any width match mode - Bit 17 of SBUS address set to 0 18010 * Exact width match mode - Bit 17 of SBUS address set to 1 18011 * Below code sets lookup mode to exact width match mode for BCM56960 18012 */ 18013 if (soc_feature(unit, soc_feature_exact_width_match_mode)) { 18014 if ((mem == L3_ENTRY_IPV4_UNICASTm) || 18015 (mem == L3_ENTRY_IPV4_MULTICASTm) || 18016 (mem == L3_ENTRY_IPV6_UNICASTm) || 18017 (mem == L3_ENTRY_IPV6_MULTICASTm) 18018 #if defined(BCM_TOMAHAWK_SUPPORT) 18019 || _SOC_MEM_CHK_FPEM_MEM(mem) 18020 #endif 18021 ) { 18022 /* Set bit 17 of SBUS address to select exact width match mode */ 18023 schan_msg.gencmd.address |= (1 << 17); 18024 } 18025 } 18026 #ifdef BCM_TOMAHAWK3_SUPPORT 18027 if (dev_id == BCM56983_DEVICE_ID) { 18028 sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg)); 18029 dw = soc_mem_entry_words(unit, mem); 18030 entry_size = dw * sizeof(uint32); 18031 entry = sal_alloc(entry_size, "entry_size"); 18032 sal_memset((void *)entry, 0, sizeof(uint32) * dw); 18033 entry_data1 = entry; 18034 l = sizeof(uint32); 18035 if ((acc_type == 9 || acc_type == 14)) { 18036 for (j = 0; j < 4; j++) { 18037 switch(j) { 18038 case 0 : acc_type = 0; 18039 break; 18040 case 1 : acc_type = 1; 18041 break; 18042 case 2 : acc_type = 6; 18043 break; 18044 case 3 : acc_type = 7; 18045 break; 18046 } 18047 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg)); 18048 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG, 18049 dst_blk, src_blk, acc_type, data_byte_len, 0, 18050 bank_ignore_mask); 18051 18052 /* Fill in entry data */ 18053 sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4); 18054 18055 /* 18056 * Execute S-Channel "lookup insert" command packet consisting of 18057 * (header word + address word + entry_dw), and read back 18058 * (header word + response word + entry_dw) data words. 18059 */ 18060 18061 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 18062 for (k = 0; k < dw; k++) { 18063 *(uint32 *)((uint8 *)entry_data1 + l*k) = 18064 *(uint32 *)((uint8 *)schan_msg.genresp_v2.data + l*k) | 18065 *(uint32 *)((uint8 *)entry_data1 + l*k); 18066 } 18067 18068 /* Check result */ 18069 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 18070 NULL, NULL, &nack); 18071 if (opcode != TABLE_LOOKUP_DONE_MSG) { 18072 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18073 (BSL_META_U(unit, 18074 "soc_mem_generic_lookup: " 18075 "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n"))); 18076 soc_schan_dump(unit, &schan_msg, entry_dw + 2); 18077 #if defined(BCM_TRIUMPH3_SUPPORT) 18078 if (soc_feature(unit, soc_feature_esm_correction) && 18079 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 18080 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 18081 SOC_ESM_UNLOCK(unit); 18082 } 18083 #endif 18084 MEM_UNLOCK(unit, mem); 18085 return SOC_E_INTERNAL; 18086 } 18087 if (rv != SOC_E_NONE) { 18088 break; 18089 } 18090 } 18091 sal_memcpy(schan_msg.genresp_v2.data, entry_data1, entry_dw * 4); 18092 goto resume; 18093 } else if (acc_type == 15) { 18094 sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg)); 18095 for (j = 0; j < 2; j++) { 18096 switch(j) { 18097 case 0 : acc_type = 0; 18098 break; 18099 case 1 : acc_type = 6; 18100 break; 18101 } 18102 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg)); 18103 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG, 18104 dst_blk, src_blk, acc_type, data_byte_len, 0, 18105 bank_ignore_mask); 18106 18107 /* Fill in entry data */ 18108 sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4); 18109 18110 /* 18111 * Execute S-Channel "lookup insert" command packet consisting of 18112 * (header word + address word + entry_dw), and read back 18113 * (header word + response word + entry_dw) data words. 18114 */ 18115 18116 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 18117 for (k = 0; k < dw; k++) { 18118 *(uint32 *)((uint8 *)entry_data1 + l*k) = 18119 *(uint32 *)((uint8 *)schan_msg.genresp_v2.data + l*k) | 18120 *(uint32 *)((uint8 *)entry_data1 + l*k); 18121 } 18122 /* Check result */ 18123 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 18124 NULL, NULL, &nack); 18125 18126 if (opcode != TABLE_LOOKUP_DONE_MSG) { 18127 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18128 (BSL_META_U(unit, 18129 "soc_mem_generic_lookup: " 18130 "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n"))); 18131 soc_schan_dump(unit, &schan_msg, entry_dw + 2); 18132 #if defined(BCM_TRIUMPH3_SUPPORT) 18133 if (soc_feature(unit, soc_feature_esm_correction) && 18134 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 18135 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 18136 SOC_ESM_UNLOCK(unit); 18137 } 18138 #endif 18139 MEM_UNLOCK(unit, mem); 18140 return SOC_E_INTERNAL; 18141 } 18142 if (rv != SOC_E_NONE) { 18143 break; 18144 } 18145 } 18146 sal_memcpy(schan_msg.genresp_v2.data, entry_data1, entry_dw * 4); 18147 goto resume; 18148 } else if (acc_type == 16) { 18149 acc_type = 0; 18150 } 18151 } 18152 #endif 18153 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG, 18154 dst_blk, src_blk, acc_type, data_byte_len, 0, 18155 bank_ignore_mask); 18156 18157 /* Fill in entry data */ 18158 sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4); 18159 18160 if (SOC_IS_SAND(unit)) { 18161 allow_intr = 1; 18162 } 18163 18164 /* 18165 * Execute S-Channel "lookup insert" command packet consisting of 18166 * (header word + address word + entry_dw), and read back 18167 * (header word + response word + entry_dw) data words. 18168 */ 18169 18170 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 18171 18172 /* Check result */ 18173 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 18174 NULL, NULL, &nack); 18175 if (opcode != TABLE_LOOKUP_DONE_MSG) { 18176 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18177 (BSL_META_U(unit, 18178 "soc_mem_generic_lookup: " 18179 "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n"))); 18180 soc_schan_dump(unit, &schan_msg, entry_dw + 2); 18181 #if defined(BCM_TRIUMPH3_SUPPORT) 18182 if (soc_feature(unit, soc_feature_esm_correction) && 18183 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 18184 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 18185 SOC_ESM_UNLOCK(unit); 18186 } 18187 #endif 18188 MEM_UNLOCK(unit, mem); 18189 return SOC_E_INTERNAL; 18190 } 18191 #ifdef BCM_TOMAHAWK3_SUPPORT 18192 resume: 18193 #endif 18194 18195 if (soc_feature(unit, soc_feature_new_sbus_format) && 18196 !soc_feature(unit, soc_feature_new_sbus_old_resp)) { 18197 type = schan_msg.genresp_v2.response.type; 18198 err_info = schan_msg.genresp_v2.response.err_info; 18199 index = schan_msg.genresp_v2.response.index; 18200 data = schan_msg.genresp_v2.data; 18201 } else { 18202 type = schan_msg.genresp.response.type; 18203 index = schan_msg.genresp.response.index; 18204 data = schan_msg.genresp.data; 18205 } 18206 if ((nack != 0) || (rv == SOC_E_FAIL)) { 18207 if (index_ptr) { 18208 *index_ptr = -1; 18209 } 18210 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 18211 rv = SOC_E_NOT_FOUND; 18212 #if defined(BCM_TRIDENT2_SUPPORT) 18213 if (soc_feature(unit, soc_feature_shared_hash_ins) && 18214 (mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm)) { 18215 /* Check for banks != 'All' to distinguish from normal lookup. 18216 * The special handling code always passes unique bank numbers. 18217 */ 18218 if (index_ptr && (banks != SOC_MEM_HASH_BANK_ALL)) { 18219 *index_ptr = schan_msg.genresp.response.index; 18220 } 18221 } 18222 #endif /* BCM_TRIDENT2_SUPPORT */ 18223 } else { 18224 if (SOC_SER_CORRECTION_SUPPORT(unit)) { 18225 uint32 *cache; 18226 uint8 *vmap; 18227 LOG_VERBOSE(BSL_LS_SOC_SER,(BSL_META_U(unit, 18228 "soc_mem_generic_lookup: rv=%d, nack=%d, type=%d, index=%d\n"), 18229 rv, nack, type, index)); 18230 if (err_info == SCHAN_GEN_RESP_ERR_INFO_ERROR_IN_LP_TABLE) { 18231 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18232 "soc_mem_generic_lookup: Encountered error on LP table " 18233 "for memory %s, banks[0x%0x], err_rsp_index[%d] !!\n"), 18234 SOC_MEM_NAME(unit, mem), banks, index)); 18235 #if defined(BCM_TOMAHAWK_SUPPORT) 18236 if (SOC_IS_TOMAHAWKX(unit)) { 18237 if (SOC_FAILURE(soc_th_lp_to_fv_index_remap(unit, mem, &index))) { 18238 MEM_UNLOCK(unit, mem); 18239 return SOC_E_INTERNAL; 18240 } 18241 } 18242 #endif 18243 } 18244 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 18245 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 18246 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 18247 int index0 = index, index1 = -1; 18248 if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIUMPH2(unit) 18249 || SOC_IS_KATANA2(unit)) { 18250 18251 index0 = schan_msg.dwords[2] & 0xffff; 18252 index1 = schan_msg.dwords[2] >> 16; 18253 } 18254 rv = _soc_mem_cache_lookup(unit, mem, copyno, banks, key, 18255 result, index0, index1, 18256 index_ptr, cache, vmap); 18257 } 18258 } else { 18259 rv = SOC_E_FAIL; 18260 } 18261 } 18262 } else { 18263 if (result != NULL) { 18264 sal_memcpy(result, data, entry_dw * sizeof(uint32)); 18265 } 18266 #ifdef BCM_TRIUMPH_SUPPORT 18267 if (soc_feature(unit, soc_feature_etu_support) && 18268 mem == EXT_L2_ENTRY_2m) { 18269 soc_mem_t ext_mem; 18270 int ext_index; 18271 18272 rv1 = soc_tcam_raw_index_to_mem_index(unit, index, 18273 &ext_mem, &ext_index); 18274 if (SOC_FAILURE(rv1)) { 18275 #if defined(BCM_TRIUMPH3_SUPPORT) 18276 if (soc_feature(unit, soc_feature_esm_correction) && 18277 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 18278 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 18279 SOC_ESM_UNLOCK(unit); 18280 } 18281 #endif 18282 MEM_UNLOCK(unit, mem); 18283 return rv1; 18284 } 18285 if (mem != ext_mem) { 18286 #if defined(BCM_TRIUMPH3_SUPPORT) 18287 if (soc_feature(unit, soc_feature_esm_correction) && 18288 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 18289 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 18290 SOC_ESM_UNLOCK(unit); 18291 } 18292 #endif 18293 MEM_UNLOCK(unit, mem); 18294 return SOC_E_INTERNAL; 18295 } 18296 index = ext_index; 18297 } 18298 #endif /* BCM_TRIUMPH_SUPPORT */ 18299 if (index_ptr != NULL) { 18300 *index_ptr = index; 18301 } 18302 index_valid = (index >= 0 && 18303 index <= soc_mem_index_max(unit, mem)); 18304 if (!index_valid) { 18305 #if defined(BCM_HURRICANE3_SUPPORT) 18306 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 18307 (mem == L2Xm)) { 18308 if (index & SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit)) { 18309 /* Check whether the entry is located at L2_OVERFLOW_ENTRY */ 18310 if ((index & ~SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit)) <= 18311 soc_mem_index_max(unit, L2_ENTRY_OVERFLOWm)) { 18312 rv = SOC_E_NONE; 18313 } 18314 } 18315 } else 18316 #endif /* BCM_HURRICANE3_SUPPORT */ 18317 { 18318 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18319 (BSL_META_U(unit, 18320 "soc_mem_generic_lookup: " 18321 "invalid index %d for memory %s\n"), 18322 index, SOC_MEM_NAME(unit, mem))); 18323 rv = SOC_E_INTERNAL; 18324 } 18325 } 18326 } 18327 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 18328 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18329 "Lookup table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem), 18330 banks)); 18331 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 18332 soc_mem_entry_dump(unit, mem, data, BSL_VERBOSE|BSL_LS_SOC_COMMON); 18333 } 18334 if (SOC_FAILURE(rv)) { 18335 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 18336 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18337 " Not found\n"))); 18338 } else { 18339 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18340 " Fail\n"))); 18341 } 18342 } else { 18343 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18344 " (index=%d)\n"), index)); 18345 } 18346 } 18347 #if defined(BCM_TRIUMPH3_SUPPORT) 18348 if (soc_feature(unit, soc_feature_esm_correction) && 18349 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 18350 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 18351 SOC_ESM_UNLOCK(unit); 18352 } 18353 #endif 18354 MEM_UNLOCK(unit, mem); 18355 return rv; 18356 } 18357 18358 #ifdef ALPM_ENABLE 18359 #define _SOC_ALPM_MEM_OP_RETRY_TO 1000000 18360 #define _SOC_ALPM_MEM_OP_RETRY_COUNT 5 18361 18362 STATIC int 18363 _soc_mem_alpm_ser_correction(int unit, soc_mem_t mem, int blk, 18364 int addr, int copyno, int index, 18365 int bkt_ptr) 18366 { 18367 int rv, pipe; 18368 int bank = 0, ent = 0; 18369 int acc_type = 0; 18370 uint32 entry[SOC_MAX_MEM_WORDS]; 18371 int ent_cnt = 1, bank_cnt = 1; 18372 #if defined (BCM_TRIDENT2_SUPPORT) 18373 int len = 0; 18374 uint32 value = 0; 18375 _soc_ser_sram_info_t sram_info; 18376 18377 _soc_sram_info_init(unit, &sram_info); 18378 #endif 18379 18380 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 18381 #ifdef BCM_TOMAHAWK3_SUPPORT 18382 if (SOC_IS_TOMAHAWK3(unit)) { 18383 mem = L3_DEFIP_ALPM_LEVEL3_ECCm; 18384 } else 18385 #endif 18386 { 18387 mem = L3_DEFIP_ALPM_ECCm; 18388 } 18389 bkt_ptr = -1; 18390 } else if (SOC_IS_TRIDENT2PLUS(unit)) { 18391 mem = L3_DEFIP_ALPM_ECCm; 18392 } else if (SOC_IS_APACHE(unit)) { 18393 mem = L3_DEFIP_ALPM_ECCm; 18394 bkt_ptr = -1; 18395 } 18396 18397 #if defined(BCM_TOMAHAWK_SUPPORT) 18398 if (SOC_IS_TOMAHAWK(unit) || SOC_IS_TOMAHAWKPLUS(unit) || 18399 SOC_IS_TOMAHAWK2(unit)) { 18400 SOC_IF_ERROR_RETURN 18401 (soc_tomahawk_mem_sram_info_get(unit, mem, index, &sram_info)); 18402 } else 18403 #endif /* BCM_TOMAHAWK_SUPPORT */ 18404 #if defined (BCM_TRIDENT2_SUPPORT) 18405 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) { 18406 SOC_IF_ERROR_RETURN 18407 (_soc_trident2_mem_sram_info_get(unit, mem, index, &sram_info)); 18408 } 18409 #endif /* BCM_TRIDENT2_SUPPORT */ 18410 18411 if (bkt_ptr != -1) { 18412 /* Need traverse to find actual parity error index*/ 18413 switch (mem) { 18414 case L3_DEFIP_ALPM_ECCm: 18415 case L3_DEFIP_ALPM_IPV4_1m: 18416 case L3_DEFIP_ALPM_IPV6_64m: 18417 ent_cnt = 4; 18418 break; 18419 case L3_DEFIP_ALPM_IPV6_64_1m: 18420 ent_cnt = 3; 18421 break; 18422 case L3_DEFIP_ALPM_IPV6_128m: 18423 ent_cnt = 2; 18424 break; 18425 case L3_DEFIP_ALPM_IPV4m: 18426 default: 18427 ent_cnt = 6; 18428 break; 18429 } 18430 bank_cnt = 4; 18431 } 18432 18433 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 18434 /* determine 1st pipe which has the problem */ 18435 if (NUM_PIPE(unit) == 4 || SOC_IS_TRIDENT3X(unit)) { 18436 acc_type = (pipe == 0)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_0 : 18437 (pipe == 1)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_1 : 18438 (pipe == 2)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_2 : 18439 _SOC_MEM_ADDR_ACC_TYPE_PIPE_3; 18440 } else if (NUM_PIPE(unit) == 2) { 18441 acc_type = (pipe == 0) ? _SOC_MEM_ADDR_ACC_TYPE_PIPE_X: 18442 _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y; 18443 } else if (NUM_PIPE(unit) == 8) { 18444 acc_type = (pipe == 0)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_0 : 18445 (pipe == 1)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_1 : 18446 (pipe == 2)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_2 : 18447 (pipe == 3)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_3 : 18448 (pipe == 4)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_4 : 18449 (pipe == 5)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_5 : 18450 (pipe == 6)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_6 : 18451 _SOC_MEM_ADDR_ACC_TYPE_PIPE_7; 18452 } 18453 18454 for (ent = 0; ent < ent_cnt; ent++) { 18455 for (bank = 0; bank < bank_cnt; bank ++) { 18456 if (bkt_ptr != -1) { 18457 index = (ent << 16) | (bkt_ptr << 2) | (bank); 18458 } 18459 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18460 "unit %d: inline ALPM correction LOOP: pipe:%d index %d\n"), 18461 unit, pipe, index)); 18462 /* Only multi-pipe need to confirm which pipe has the parity error */ 18463 if (NUM_PIPE(unit) > 1) { 18464 rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS, mem, copyno, 18465 acc_type, index, entry); 18466 18467 #if defined (BCM_TRIDENT2_SUPPORT) /* Check XOR bank */ 18468 if (rv != SOC_E_FAIL && 18469 (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit) || 18470 SOC_IS_TOMAHAWK(unit) || SOC_IS_TOMAHAWKPLUS(unit) || 18471 SOC_IS_TOMAHAWK2(unit))) { 18472 if (SOC_REG_IS_VALID(unit, sram_info.force_reg)) { 18473 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18474 "unit %d: inline ALPM correction: will read " 18475 "pipe %d, index %d again with " 18476 "forcing XOR generation\n"), 18477 unit, pipe, index)); 18478 len = soc_reg_field_length(unit, sram_info.force_reg, 18479 sram_info.force_field); 18480 value = (1 << len) - 1; 18481 soc_reg_field32_modify(unit, sram_info.force_reg, 18482 REG_PORT_ANY, 18483 sram_info.force_field, value); 18484 rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS, 18485 mem, copyno, 18486 acc_type, index, entry); 18487 soc_reg_field32_modify(unit, sram_info.force_reg, 18488 REG_PORT_ANY, 18489 sram_info.force_field, 0); 18490 } 18491 } 18492 #endif 18493 if (SOC_E_FAIL == rv) { 18494 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18495 "unit %d: inline ALPM correction: will try ser_correction for pipe %d, index %d\n"), 18496 unit, pipe, index)); 18497 18498 /* Once we found the bad pipe on TD2, restore the entire bucket 18499 * across 4 banks. This could be done via call soc_ser_sram_correction 18500 * 4 times with 4 indexes on 4 banks. 18501 */ 18502 if (SOC_IS_TRIDENT2X(unit)) { 18503 for (bank = 0; bank < 4; bank ++) { 18504 index = (index & (~0x3)) | (bank); 18505 rv = soc_ser_sram_correction(unit, pipe, blk, addr, mem, copyno, 18506 index, NULL); 18507 } 18508 } else { 18509 rv = soc_ser_sram_correction(unit, pipe, blk, addr, mem, copyno, 18510 index, NULL); 18511 } 18512 if (SOC_FAILURE(rv)) { 18513 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18514 "unit %d: inline ALPM correction: ser_correction FAILED for pipe %d, index %d\n"), 18515 unit, pipe, index)); 18516 } else { 18517 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18518 "unit %d: inline ALPM correction: ser_correction passed for pipe %d, index %d\n"), 18519 unit, pipe, index)); 18520 } 18521 return rv; 18522 } else if (SOC_SUCCESS(rv)) { 18523 /* 18524 * IPRC_NACK is only set on MEMRD if a 2-bit error is detected. 18525 * If a 1-bit error is detected, NACK is not set, and corrected data is returned 18526 * So if soc_mem_pipe_select_read returns success, we don't know if there 18527 * is 1b error or not, the best choice is to correct all pipes one by one 18528 */ 18529 int pipe_tmp, bank_tmp, index_tmp; 18530 index_tmp = index; 18531 if (pipe == (NUM_PIPE(unit) - 1)) { 18532 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18533 "unit %d: inline ALPM correction: MEMRD of " 18534 "index %d from all pipes return success," 18535 "it should be 1-bit error!" 18536 "Correct all pipes for now!\n"),unit, index)); 18537 /* 18538 * Recover all pipes in increasing pipe num order 18539 */ 18540 for (pipe_tmp = 0; 18541 pipe_tmp < NUM_PIPE(unit); 18542 pipe_tmp++) { 18543 if (SOC_IS_TRIDENT2X(unit)) { 18544 for (bank_tmp = 0; 18545 bank_tmp < 4; 18546 bank_tmp ++) { 18547 index_tmp = (index_tmp & (~0x3)) | 18548 (bank_tmp); 18549 (void)soc_ser_sram_correction(unit, 18550 pipe_tmp, 18551 blk, addr, 18552 mem, 18553 copyno, 18554 index_tmp, 18555 NULL); 18556 } 18557 } else if (SOC_IS_TOMAHAWKX(unit) || 18558 SOC_IS_TRIDENT3X(unit)) { 18559 (void)soc_ser_sram_correction(unit, 18560 pipe_tmp, 18561 blk, addr, 18562 mem, 18563 copyno, 18564 index_tmp, 18565 NULL); 18566 } 18567 } 18568 } 18569 } 18570 }else { 18571 rv = soc_ser_sram_correction(unit, pipe, blk, addr, mem, copyno, 18572 index, NULL); 18573 if (SOC_FAILURE(rv)) { 18574 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18575 "unit %d: inline ALPM correction: ser_correction FAILED for pipe %d, index %d\n"), 18576 unit, pipe, index)); 18577 } else { 18578 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18579 "unit %d: inline ALPM correction: ser_correction passed for pipe %d, index %d\n"), 18580 unit, pipe, index)); 18581 } 18582 return rv; 18583 } 18584 } 18585 } 18586 } 18587 /* Means we could not find any pipe which had problem 18588 * Should not happen, just let caller retry operation */ 18589 LOG_WARN(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18590 "unit %d: inline ALPM correction: ser_correction illegal pipe %d for index %d !! \n"), 18591 unit, pipe, index)); 18592 return SOC_E_NONE; 18593 } 18594 18595 /* 18596 * Function: 18597 * soc_mem_alpm_lookup 18598 * Purpose: 18599 * Send a lookup message over the S-Channel and receive the response 18600 * from ALPM memories. ALPM memories have special needs bcoz the entries 18601 * are not hashed. 18602 * Parameters: 18603 * unit - StrataSwitch unit # 18604 * banks - Banks 18605 * Note: used to create a bitmap for ISM mems. (All banks: -1) 18606 * key - entry to look up 18607 * result - entry to receive entire found entry 18608 * index_ptr (OUT) - If found, receives table index where found 18609 * Returns: 18610 * SOC_E_INTERNAL if retries exceeded or other internal error 18611 * SOC_E_NOT_FOUND if the entry is not found. 18612 * SOC_E_NONE (0) on success (entry found): 18613 */ 18614 18615 int 18616 soc_mem_alpm_lookup(int unit, soc_mem_t mem, int bucket_index, 18617 int copyno, uint32 banks_disable, 18618 void *key, void *result, int *index_ptr) 18619 { 18620 schan_msg_t schan_msg; 18621 uint8 at; 18622 uint32 *data; 18623 int rv, entry_dw, allow_intr=0; 18624 int type, index; 18625 int _soc_alpm_lookup_retry = 0; 18626 int src_blk, dst_blk, acc_type, data_byte_len; 18627 int opcode, nack; 18628 uint32 bank_ignore_mask; 18629 int bkt_ptr = -1; 18630 18631 assert(SOC_MEM_IS_VALID(unit, mem)); 18632 assert(soc_attached(unit)); 18633 18634 if (SAL_BOOT_SIMULATION) { 18635 #if defined(ALPM_ENABLE) 18636 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 18637 if (index_ptr) { 18638 *index_ptr = bucket_index << (soc_alpm_cmn_banks_get(unit) / 2); 18639 } 18640 #endif 18641 #endif 18642 return SOC_E_NOT_FOUND; 18643 } 18644 18645 /* Only applicable to ALPM memories */ 18646 if ((mem != L3_DEFIP_ALPM_IPV6_128m) && 18647 (mem != L3_DEFIP_ALPM_IPV6_64m) && 18648 (mem != L3_DEFIP_ALPM_IPV6_64_1m) && 18649 (mem != L3_DEFIP_ALPM_IPV4m) && 18650 (mem != L3_DEFIP_ALPM_IPV4_1m)) { 18651 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18652 (BSL_META_U(unit, 18653 "soc_mem_alpm_lookup: not supported non-ALPM memories %s\n"), 18654 SOC_MEM_NAME(unit, mem))); 18655 return SOC_E_PARAM; 18656 } 18657 18658 if (copyno == MEM_BLOCK_ANY) { 18659 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 18660 } 18661 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 18662 LOG_WARN(BSL_LS_SOC_SOCMEM, 18663 (BSL_META_U(unit, 18664 "soc_mem_alpm_lookup: invalid block %d for memory %s\n"), 18665 copyno, SOC_MEM_NAME(unit, mem))); 18666 return SOC_E_PARAM; 18667 } 18668 18669 entry_dw = soc_mem_entry_words(unit, mem); 18670 18671 SOC_CONTROL_LOCK(unit); 18672 SHR_BITSET(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_LOOKUP); 18673 SOC_CONTROL_UNLOCK(unit); 18674 _retry: 18675 schan_msg_clear(&schan_msg); 18676 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 18677 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 18678 dst_blk = SOC_BLOCK2SCH(unit, copyno); 18679 #ifdef BCM_ISM_SUPPORT 18680 if (soc_feature(unit, soc_feature_ism_memory)) { 18681 /* don't set bank id in cos */ 18682 bank_ignore_mask = 0; 18683 } else 18684 #endif /* BCM_ISM_SUPPORT */ 18685 { 18686 bank_ignore_mask = banks_disable & 0x3; 18687 } 18688 data_byte_len = entry_dw * 4; 18689 18690 /* ALPM entries are not hashed */ 18691 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 18692 /* Address contains bank disable, and bucket pointer */ 18693 /* Bucket index and bank disable 18694 * addr[TD2: 13:0, TH: 12:0, TH2: 13:0] - bucket 18695 * addr[TD2: 17:14, TH: 16:13, TH2: 17:14] - bank disable[3:0] 18696 */ 18697 #if defined(BCM_TOMAHAWK_SUPPORT) 18698 if (SOC_IS_TOMAHAWK(unit)) { 18699 schan_msg.gencmd.address &= ~(0x0001ffff); 18700 schan_msg.gencmd.address |= 18701 (((banks_disable & 0xf) << 13) | (bucket_index & ALPM_CTRL(unit).bkt_mask)); 18702 } else if (SOC_IS_TRIDENT3X(unit)) { 18703 /* TD3 only has 4 bits for bank disable bitmap */ 18704 schan_msg.gencmd.address &= ~(0x0001ffff); 18705 schan_msg.gencmd.address |= 18706 (((banks_disable & 0xf) << 13) | (bucket_index & ALPM_CTRL(unit).bkt_mask)); 18707 } else 18708 #endif /* BCM_TOMAHAWK_SUPPORT */ 18709 { 18710 schan_msg.gencmd.address &= ~(0x0003ffff); 18711 schan_msg.gencmd.address |= 18712 (((banks_disable & 0xf) << 14) | (bucket_index & SOC_TD2_ALPM_BKT_MASK)); 18713 } 18714 18715 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG, 18716 dst_blk, src_blk, acc_type, data_byte_len, 0, 18717 bank_ignore_mask); 18718 18719 /* Fill in entry data */ 18720 sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4); 18721 18722 if (SOC_IS_SAND(unit)) { 18723 allow_intr = 1; 18724 } 18725 18726 /* 18727 * Execute S-Channel "lookup insert" command packet consisting of 18728 * (header word + address word + entry_dw), and read back 18729 * (header word + response word + entry_dw) data words. 18730 */ 18731 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 18732 18733 /* Check result */ 18734 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 18735 NULL, NULL, &nack); 18736 if (opcode != TABLE_LOOKUP_DONE_MSG) { 18737 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18738 (BSL_META_U(unit, 18739 "soc_mem_generic_lookup: " 18740 "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n"))); 18741 soc_schan_dump(unit, &schan_msg, entry_dw + 2); 18742 return SOC_E_INTERNAL; 18743 } 18744 18745 type = schan_msg.genresp_v2.response.type; 18746 index = schan_msg.genresp_v2.response.index; 18747 data = schan_msg.genresp_v2.data; 18748 18749 if ((nack != 0) || (rv == SOC_E_FAIL)) { 18750 if (index_ptr) { 18751 *index_ptr = -1; 18752 } 18753 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 18754 rv = SOC_E_NOT_FOUND; 18755 } else { 18756 LOG_WARN(BSL_LS_SOC_SOCMEM, 18757 (BSL_META_U(unit, 18758 "unit %d: ALPM lookup operation[%s] encountered " 18759 "parity error !! Resp_type %d Resp_index %d\n"), 18760 unit, SOC_MEM_NAME(unit, mem), type, index)); 18761 _soc_alpm_lookup_retry++; 18762 if (type == SCHAN_GEN_RESP_TYPE_FOUND) { 18763 bkt_ptr = bucket_index; 18764 } 18765 if (SOC_CONTROL(unit)->alpm_lookup_retry) { 18766 (void)_soc_mem_alpm_ser_correction(unit, 18767 mem, 18768 schan_msg.gencmd.header.v2.dst_blk, 18769 schan_msg.gencmd.address, 18770 copyno, index, 18771 bkt_ptr); 18772 18773 18774 if (_soc_alpm_lookup_retry < _SOC_ALPM_MEM_OP_RETRY_COUNT) { 18775 if (sal_sem_take(SOC_CONTROL(unit)->alpm_lookup_retry, 18776 _SOC_ALPM_MEM_OP_RETRY_TO) < 0) { 18777 LOG_WARN(BSL_LS_SOC_SOCMEM, 18778 (BSL_META_U(unit, 18779 "unit %d: Retry ALPM lookup operation..\n"), unit)); 18780 goto _retry; 18781 } else { 18782 LOG_WARN(BSL_LS_SOC_SOCMEM, 18783 (BSL_META_U(unit, 18784 "unit %d: Retry ALPM lookup operation..\n"), unit)); 18785 goto _retry; 18786 } 18787 } else { 18788 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18789 (BSL_META_U(unit, 18790 "unit %d: Aborting ALPM lookup operation " 18791 "due to un-correctable error !!\n"), unit)); 18792 rv = SOC_E_INTERNAL; 18793 } 18794 } else { 18795 rv = SOC_E_INTERNAL; 18796 } 18797 } 18798 } else { 18799 if (result != NULL) { 18800 sal_memcpy(result, data, entry_dw * sizeof(uint32)); 18801 } 18802 if (index_ptr != NULL) { 18803 *index_ptr = index; 18804 } 18805 } 18806 SOC_CONTROL_LOCK(unit); 18807 SHR_BITCLR(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_LOOKUP); 18808 SOC_CONTROL_UNLOCK(unit); 18809 18810 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 18811 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18812 "Lookup table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem), 18813 banks_disable)); 18814 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 18815 soc_mem_entry_dump(unit, mem, data, BSL_VERBOSE|BSL_LS_SOC_COMMON); 18816 } 18817 if (SOC_FAILURE(rv)) { 18818 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 18819 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18820 " Not found\n"))); 18821 } else { 18822 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18823 " Fail\n"))); 18824 } 18825 } else { 18826 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18827 " (index=%d)\n"), index)); 18828 } 18829 } 18830 18831 return rv; 18832 } 18833 18834 /* 18835 * Function: 18836 * soc_mem_alpm_insert 18837 * Purpose: 18838 * Insert an entry into ALPM memory. 18839 * Parameters: 18840 * unit - StrataSwitch unit # 18841 * banks - For dual hashing, which halves are selected (inverted) 18842 * Note: used to create a bitmap for ISM mems. (All banks: -1) 18843 * entry - entry to insert 18844 * old_entry - old entry if existing entry was replaced 18845 * Returns: 18846 * SOC_E_NONE - success 18847 * SOC_E_EXISTS - existing entry was replaced 18848 * SOC_E_FULL - full 18849 * SOC_E_BUSY - modfifo full 18850 * Notes: 18851 * Uses hardware insertion; sends an INSERT message over the 18852 * S-Channel. 18853 */ 18854 18855 int 18856 soc_mem_alpm_insert(int unit, soc_mem_t mem, int bucket, 18857 int copyno, int32 banks_disable, 18858 void *entry, void *old_entry, int *index_ptr) 18859 { 18860 schan_msg_t schan_msg; 18861 uint8 at, *vmap; 18862 uint32 *data, *cache; 18863 int rv, entry_dw, index_valid; 18864 int type, index, allow_intr=0; 18865 int _soc_alpm_insert_retry = 0; 18866 int src_blk, dst_blk, acc_type, data_byte_len; 18867 int opcode, nack; 18868 int type2 = -1, index2 = 0; 18869 uint32 data2[CMIC_SCHAN_WORDS_ALLOC - 2]; 18870 int bkt_ptr = -1; 18871 uint8 _alpm_lock = 0; 18872 18873 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 18874 assert(SOC_MEM_IS_VALID(unit, mem)); 18875 assert(soc_attached(unit)); 18876 18877 if (SAL_BOOT_SIMULATION) { 18878 #if defined(ALPM_ENABLE) 18879 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 18880 if (index_ptr) { 18881 *index_ptr = bucket << (soc_alpm_cmn_banks_get(unit) / 2); 18882 } 18883 #endif 18884 #endif 18885 18886 return SOC_E_NONE; 18887 } 18888 18889 /* Only applicable to ALPM memories */ 18890 if ((mem != L3_DEFIP_ALPM_IPV6_128m) && 18891 (mem != L3_DEFIP_ALPM_IPV6_64m) && 18892 (mem != L3_DEFIP_ALPM_IPV6_64_1m) && 18893 (mem != L3_DEFIP_ALPM_IPV4m) && 18894 (mem != L3_DEFIP_ALPM_IPV4_1m)) { 18895 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18896 (BSL_META_U(unit, 18897 "soc_mem_alpm_insert: not supported non-ALPM memories %s\n"), 18898 SOC_MEM_NAME(unit, mem))); 18899 return SOC_E_PARAM; 18900 } 18901 18902 if (copyno == MEM_BLOCK_ANY) { 18903 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 18904 } 18905 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 18906 LOG_WARN(BSL_LS_SOC_SOCMEM, 18907 (BSL_META_U(unit, 18908 "soc_mem_alpm_insert: invalid block %d for memory %s\n"), 18909 copyno, SOC_MEM_NAME(unit, mem))); 18910 return SOC_E_PARAM; 18911 } 18912 18913 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 18914 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18915 "Insert table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem), 18916 banks_disable)); 18917 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 18918 soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON); 18919 } 18920 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 18921 "\n"))); 18922 } 18923 18924 entry_dw = soc_mem_entry_words(unit, mem); 18925 18926 SOC_CONTROL_LOCK(unit); 18927 SHR_BITSET(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_INSERT); 18928 SOC_CONTROL_UNLOCK(unit); 18929 18930 _retry: 18931 schan_msg_clear(&schan_msg); 18932 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 18933 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 18934 dst_blk = SOC_BLOCK2SCH(unit, copyno); 18935 data_byte_len = entry_dw * 4; 18936 18937 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 18938 /* Address contains bank disable, and bucket pointer */ 18939 /* Bucket index and bank disable 18940 * addr[TD2: 13:0, TH: 12:0, TH2: 13:0] - bucket 18941 * addr[TD2: 17:14, TH: 16:13, TH2: 17:14] - bank disable[3:0] 18942 */ 18943 #if defined(BCM_TOMAHAWK_SUPPORT) 18944 if (SOC_IS_TOMAHAWK(unit)) { 18945 schan_msg.gencmd.address &= ~(0x0001ffff); 18946 schan_msg.gencmd.address |= 18947 (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask)); 18948 } else if (SOC_IS_TRIDENT3X(unit)) { 18949 /* TD3 only has 4 bits for bank disable bitmap */ 18950 schan_msg.gencmd.address &= ~(0x0001ffff); 18951 schan_msg.gencmd.address |= 18952 (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask)); 18953 } else 18954 #endif 18955 { 18956 schan_msg.gencmd.address &= ~(0x0003ffff); 18957 schan_msg.gencmd.address |= 18958 (((banks_disable & 0xf) << 14) | (bucket & SOC_TD2_ALPM_BKT_MASK)); 18959 } 18960 18961 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG, 18962 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 18963 18964 /* Fill in packet data */ 18965 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 18966 18967 /* Only lock one time */ 18968 if (0 == _alpm_lock) { 18969 SOC_ALPM_LPM_LOCK(unit); 18970 _alpm_lock = 1; 18971 } 18972 18973 /* 18974 * Execute S-Channel "table insert" command packet consisting of 18975 * (header word + address word + entry_dw), and read back 18976 * (header word + response word + entry_dw) data words. 18977 */ 18978 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 18979 18980 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 18981 NULL, NULL, &nack); 18982 if (opcode != TABLE_INSERT_DONE_MSG) { 18983 LOG_ERROR(BSL_LS_SOC_SOCMEM, 18984 (BSL_META_U(unit, 18985 "soc_mem_alpm_insert: " 18986 "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n"))); 18987 soc_schan_dump(unit, &schan_msg, 1); 18988 SOC_ALPM_LPM_UNLOCK(unit); 18989 return SOC_E_INTERNAL; 18990 } 18991 type = schan_msg.genresp_v2.response.type; 18992 index = schan_msg.genresp_v2.response.index; 18993 data = schan_msg.genresp_v2.data; 18994 18995 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 18996 (BSL_META_U(unit, 18997 "SBUS INSERT: nack:%d rv:%d type:%d index:%d \n "), 18998 nack, rv, type, index)); 18999 19000 if (_soc_alpm_insert_retry && (nack == 0 && rv == SOC_E_NONE)) { 19001 if (type == SCHAN_GEN_RESP_TYPE_REPLACED) { 19002 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 19003 (BSL_META_U(unit, 19004 "SBUS INSERT failed, replaced at retry %d \n"), 19005 _soc_alpm_insert_retry)); 19006 /* After SER actions, the entry in bad pipe could be 19007 * inserted/replaced, we too consider that as success. 19008 */ 19009 if (type2 == SCHAN_GEN_RESP_TYPE_INSERTED || 19010 type2 == SCHAN_GEN_RESP_TYPE_REPLACED) { 19011 /* recover the values needed for success ops */ 19012 type = type2; 19013 index = index2; 19014 if (type == SCHAN_GEN_RESP_TYPE_REPLACED) { 19015 data = data2; 19016 } 19017 } else { 19018 /* SBUS fails at the first time (type is error). 19019 * We still get index, but lose info of being inserted/replaced 19020 * and old entry if it's replaced. 19021 */ 19022 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 19023 (BSL_META_U(unit, 19024 "SBUS INSERT fails 1st with error. The old entry is lost \n "))); 19025 } 19026 } 19027 } 19028 if ((nack != 0) || (rv == SOC_E_FAIL)) { 19029 if (index_ptr) { 19030 *index_ptr = -1; 19031 } 19032 if (type == SCHAN_GEN_RESP_TYPE_FULL) { 19033 LOG_INFO(BSL_LS_SOC_SOCMEM, 19034 (BSL_META_U(unit, 19035 "Insert table[%s]: hash bucket full\n"), 19036 SOC_MEM_NAME(unit, mem))); 19037 rv = SOC_E_FULL; 19038 } else if (type == SCHAN_GEN_RESP_TYPE_ERROR || 19039 type == SCHAN_GEN_RESP_TYPE_INSERTED || 19040 type == SCHAN_GEN_RESP_TYPE_REPLACED) { 19041 LOG_WARN(BSL_LS_SOC_SOCMEM, 19042 (BSL_META_U(unit, 19043 "unit %d: ALPM insert operation[%s] encountered " 19044 "parity error !! Resp_type %d Resp_index %d\n"), 19045 unit, SOC_MEM_NAME(unit, mem), type, index)); 19046 _soc_alpm_insert_retry++; 19047 if (type == SCHAN_GEN_RESP_TYPE_INSERTED || 19048 type == SCHAN_GEN_RESP_TYPE_REPLACED) { 19049 type2 = type; 19050 index2 = index; 19051 if (type == SCHAN_GEN_RESP_TYPE_REPLACED) { 19052 sal_memcpy(data2, schan_msg.genresp_v2.data, entry_dw * 4); 19053 } 19054 bkt_ptr = bucket; 19055 } 19056 19057 if (SOC_CONTROL(unit)->alpm_insert_retry) { 19058 (void)_soc_mem_alpm_ser_correction(unit, 19059 mem, 19060 schan_msg.gencmd.header.v2.dst_blk, 19061 schan_msg.gencmd.address, 19062 copyno, index, 19063 bkt_ptr); 19064 if (_soc_alpm_insert_retry < _SOC_ALPM_MEM_OP_RETRY_COUNT) { 19065 19066 if (sal_sem_take(SOC_CONTROL(unit)->alpm_insert_retry, 19067 _SOC_ALPM_MEM_OP_RETRY_TO) < 0) { 19068 LOG_WARN(BSL_LS_SOC_SOCMEM, 19069 (BSL_META_U(unit, 19070 "unit %d: Retry ALPM insert operation..\n"), unit)); 19071 goto _retry; 19072 } else { 19073 LOG_WARN(BSL_LS_SOC_SOCMEM, 19074 (BSL_META_U(unit, 19075 "unit %d: Retry ALPM insert operation..\n"), unit)); 19076 goto _retry; 19077 } 19078 } else { 19079 LOG_ERROR(BSL_LS_SOC_SOCMEM, 19080 (BSL_META_U(unit, 19081 "unit %d: Aborting ALPM insert operation " 19082 "due to un-correctable error !!\n"), unit)); 19083 rv = SOC_E_INTERNAL; 19084 } 19085 } else { 19086 rv = SOC_E_INTERNAL; 19087 } 19088 } else { 19089 rv = SOC_E_FAIL; 19090 } 19091 } else { 19092 if (index_ptr != NULL) { 19093 *index_ptr = index; 19094 } 19095 /* 19096 First insertion will write H/W data even if SER error exists, then second insertion will 19097 return success with SCHAN_GEN_RESP_TYPE_REPLACED response type. 19098 We should treat this case as success. 19099 */ 19100 if (type == SCHAN_GEN_RESP_TYPE_REPLACED && !_soc_alpm_insert_retry) { 19101 if (old_entry != NULL) { 19102 sal_memcpy(old_entry, data, entry_dw * sizeof(uint32)); 19103 } 19104 rv = SOC_E_EXISTS; 19105 } 19106 /* Update cache if active */ 19107 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 19108 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 19109 index_valid = (index >= 0 && 19110 index <= soc_mem_index_max(unit, mem)); 19111 if (index_valid && cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 19112 sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4); 19113 CACHE_VMAP_SET(vmap, index); 19114 } 19115 } 19116 SOC_ALPM_LPM_UNLOCK(unit); 19117 19118 if (!SOC_FAILURE(rv) || (rv == SOC_E_EXISTS)) { 19119 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) { 19120 _soc_trident2_alpm_bkt_view_set(unit, index, mem); 19121 } 19122 #if defined(ALPM_ENABLE) 19123 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 19124 else { 19125 soc_alpm_cmn_bkt_view_set(unit, index, mem); 19126 } 19127 #endif 19128 #endif 19129 } 19130 SOC_CONTROL_LOCK(unit); 19131 SHR_BITCLR(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_INSERT); 19132 SOC_CONTROL_UNLOCK(unit); 19133 19134 return rv; 19135 } 19136 19137 /* 19138 * Function: 19139 * soc_mem_alpm_delete 19140 * Purpose: 19141 * Delete an ALPM entry 19142 * Parameters: 19143 * unit - StrataSwitch unit # 19144 * banks - For dual hashing, which halves are selected (inverted) 19145 * Note: used to create a bitmap for ISM mems. (All banks: -1) 19146 * entry - entry to delete 19147 * old_entry - old entry if entry was found and deleted 19148 * Returns: 19149 * SOC_E_NONE - success 19150 * SOC_E_NOT_FOUND - full 19151 * SOC_E_BUSY - modfifo full 19152 * Notes: 19153 * Uses hardware deletion; sends an DELETE message over the 19154 * S-Channel. 19155 */ 19156 19157 int 19158 soc_mem_alpm_delete(int unit, soc_mem_t mem, int bucket, 19159 int copyno, int32 banks_disable, 19160 void *entry, void *old_entry, int *index_ptr) 19161 { 19162 schan_msg_t schan_msg; 19163 uint8 at, *vmap; 19164 uint32 *data, *cache; 19165 int rv, entry_dw, index_valid; 19166 int type, index, allow_intr=0; 19167 int _soc_alpm_delete_retry = 0; 19168 void *null_entry = soc_mem_entry_null(unit, mem); 19169 int src_blk, dst_blk, acc_type, data_byte_len; 19170 int opcode, nack; 19171 uint32 bank_ignore_mask; 19172 int type2 = -1, index2 = 0; 19173 uint32 data2[CMIC_SCHAN_WORDS_ALLOC - 2]; 19174 int bkt_ptr = -1; 19175 uint8 _alpm_lock = 0; 19176 19177 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 19178 assert(SOC_MEM_IS_VALID(unit, mem)); 19179 assert(soc_attached(unit)); 19180 19181 if (SAL_BOOT_SIMULATION) { 19182 #if defined(ALPM_ENABLE) 19183 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 19184 if (index_ptr) { 19185 *index_ptr = bucket << (soc_alpm_cmn_banks_get(unit) / 2); 19186 } 19187 #endif 19188 #endif 19189 return SOC_E_NONE; 19190 } 19191 19192 /* Only applicable to ALPM memories */ 19193 if ((mem != L3_DEFIP_ALPM_IPV6_128m) && 19194 (mem != L3_DEFIP_ALPM_IPV6_64m) && 19195 (mem != L3_DEFIP_ALPM_IPV6_64_1m) && 19196 (mem != L3_DEFIP_ALPM_IPV4m) && 19197 (mem != L3_DEFIP_ALPM_IPV4_1m)) { 19198 LOG_ERROR(BSL_LS_SOC_SOCMEM, 19199 (BSL_META_U(unit, 19200 "soc_mem_alpm_delete: not supported non-ALPM memories %s\n"), 19201 SOC_MEM_NAME(unit, mem))); 19202 return SOC_E_PARAM; 19203 } 19204 19205 if (copyno == MEM_BLOCK_ANY) { 19206 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 19207 } 19208 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 19209 LOG_WARN(BSL_LS_SOC_SOCMEM, 19210 (BSL_META_U(unit, 19211 "soc_mem_alpm_delete: invalid block %d for memory %s\n"), 19212 copyno, SOC_MEM_NAME(unit, mem))); 19213 return SOC_E_PARAM; 19214 } 19215 19216 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 19217 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 19218 "Delete table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem), 19219 banks_disable)); 19220 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 19221 soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON); 19222 } 19223 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 19224 "\n"))); 19225 } 19226 19227 entry_dw = soc_mem_entry_words(unit, mem); 19228 19229 SOC_CONTROL_LOCK(unit); 19230 SHR_BITSET(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_DELETE); 19231 SOC_CONTROL_UNLOCK(unit); 19232 19233 _retry: 19234 schan_msg_clear(&schan_msg); 19235 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 19236 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 19237 dst_blk = SOC_BLOCK2SCH(unit, copyno); 19238 #ifdef BCM_ISM_SUPPORT 19239 if (soc_feature(unit, soc_feature_ism_memory)) { 19240 /* don't set bank id in cos */ 19241 bank_ignore_mask = 0; 19242 } else 19243 #endif /* BCM_ISM_SUPPORT */ 19244 { 19245 bank_ignore_mask = banks_disable & 0x3; 19246 } 19247 data_byte_len = entry_dw * 4; 19248 19249 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 19250 19251 /* Address contains bank disable, and bucket pointer */ 19252 /* Bucket index and bank disable 19253 * addr[TD2: 13:0, TH: 12:0, TH2: 13:0] - bucket 19254 * addr[TD2: 17:14, TH: 16:13, TH2: 17:14] - bank disable[3:0] 19255 */ 19256 #if defined(BCM_TOMAHAWK_SUPPORT) 19257 if (SOC_IS_TOMAHAWK(unit)) { 19258 schan_msg.gencmd.address &= ~(0x0001ffff); 19259 schan_msg.gencmd.address |= 19260 (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask)); 19261 } else if (SOC_IS_TRIDENT3X(unit)) { 19262 /* TD3 only has 4 bits for bank disable bitmap */ 19263 schan_msg.gencmd.address &= ~(0x0001ffff); 19264 schan_msg.gencmd.address |= 19265 (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask)); 19266 } else 19267 #endif 19268 { 19269 schan_msg.gencmd.address &= ~(0x0003ffff); 19270 schan_msg.gencmd.address |= 19271 (((banks_disable & 0xf) << 14) | (bucket & SOC_TD2_ALPM_BKT_MASK)); 19272 } 19273 19274 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG, 19275 dst_blk, src_blk, acc_type, data_byte_len, 0, 19276 bank_ignore_mask); 19277 19278 /* Fill in packet data */ 19279 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 19280 19281 if (SOC_IS_SAND(unit)) { 19282 allow_intr = 1; 19283 } 19284 19285 /* Only lock one time */ 19286 if (0 == _alpm_lock) { 19287 SOC_ALPM_LPM_LOCK(unit); 19288 _alpm_lock = 1; 19289 } 19290 19291 /* 19292 * Execute S-Channel "table delete" command packet consisting of 19293 * (header word + address word + entry_dw), and read back 19294 * (header word + response word + entry_dw) data words. 19295 */ 19296 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 19297 19298 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 19299 NULL, NULL, &nack); 19300 if (opcode != TABLE_DELETE_DONE_MSG) { 19301 LOG_ERROR(BSL_LS_SOC_SOCMEM, 19302 (BSL_META_U(unit, 19303 "soc_mem_generic_delete: " 19304 "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n"))); 19305 soc_schan_dump(unit, &schan_msg, 1); 19306 SOC_ALPM_LPM_UNLOCK(unit); 19307 return SOC_E_INTERNAL; 19308 } 19309 19310 type = schan_msg.genresp_v2.response.type; 19311 index = schan_msg.genresp_v2.response.index; 19312 data = schan_msg.genresp_v2.data; 19313 19314 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 19315 (BSL_META_U(unit, 19316 "SBUS DELETE: nack:%d rv:%d type:%d index:%d \n"), 19317 nack, rv, type, index)); 19318 19319 if (_soc_alpm_delete_retry && (nack != 0 || rv == SOC_E_FAIL)) { 19320 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 19321 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 19322 (BSL_META_U(unit, 19323 "SBUS DELETE failed, not found at retry %d \n"), 19324 _soc_alpm_delete_retry)); 19325 /* After SER actions, the entry in bad pipe could be deleted. 19326 * We too consider that as success. 19327 */ 19328 nack = 0; 19329 rv = SOC_E_NONE; 19330 if (type2 == SCHAN_GEN_RESP_TYPE_DELETED) { 19331 /* recover the values needed for success ops */ 19332 type = type2; 19333 index = index2; 19334 data = data2; 19335 } else { 19336 /* SBUS fails at the first time (type is error). 19337 * We lose the deleted entry's contect and its index. 19338 */ 19339 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 19340 (BSL_META_U(unit, 19341 "SBUS INSERT fails 1st with error. The deleted index" 19342 " and old entry is lost \n"))); 19343 } 19344 } 19345 } 19346 if ((nack != 0) || (rv == SOC_E_FAIL)) { 19347 if (index_ptr) { 19348 *index_ptr = -1; 19349 } 19350 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 19351 LOG_INFO(BSL_LS_SOC_SOCMEM, 19352 (BSL_META_U(unit, 19353 "Delete table[%s]: Not found\n"), 19354 SOC_MEM_NAME(unit, mem))); 19355 rv = SOC_E_NOT_FOUND; 19356 } else if (type == SCHAN_GEN_RESP_TYPE_ERROR || 19357 type == SCHAN_GEN_RESP_TYPE_DELETED) { 19358 LOG_WARN(BSL_LS_SOC_SOCMEM, 19359 (BSL_META_U(unit, 19360 "unit %d: ALPM delete operation[%s] encountered " 19361 "parity error !! Resp_type %d Resp_index %d\n"), 19362 unit, SOC_MEM_NAME(unit, mem), type, index)); 19363 _soc_alpm_delete_retry++; 19364 if (type == SCHAN_GEN_RESP_TYPE_DELETED) { 19365 type2 = type; 19366 index2 = index; 19367 sal_memcpy(data2, schan_msg.genresp_v2.data, entry_dw * 4); 19368 bkt_ptr = bucket; 19369 } 19370 if (SOC_CONTROL(unit)->alpm_delete_retry) { 19371 (void)_soc_mem_alpm_ser_correction(unit, 19372 mem, 19373 schan_msg.gencmd.header.v2.dst_blk, 19374 schan_msg.gencmd.address, 19375 copyno, index, 19376 bkt_ptr); 19377 if (_soc_alpm_delete_retry < _SOC_ALPM_MEM_OP_RETRY_COUNT) { 19378 19379 if (sal_sem_take(SOC_CONTROL(unit)->alpm_delete_retry, 19380 _SOC_ALPM_MEM_OP_RETRY_TO) < 0) { 19381 LOG_WARN(BSL_LS_SOC_SOCMEM, 19382 (BSL_META_U(unit, 19383 "unit %d: Retry ALPM delete operation..\n"), unit)); 19384 goto _retry; 19385 } else { 19386 LOG_WARN(BSL_LS_SOC_SOCMEM, 19387 (BSL_META_U(unit, 19388 "unit %d: Retry ALPM delete operation..\n"), unit)); 19389 goto _retry; 19390 } 19391 } else { 19392 LOG_ERROR(BSL_LS_SOC_SOCMEM, 19393 (BSL_META_U(unit, 19394 "unit %d: Aborting ALPM delete operation " 19395 "due to un-correctable error !!\n"), unit)); 19396 rv = SOC_E_INTERNAL; 19397 } 19398 } else { 19399 rv = SOC_E_INTERNAL; 19400 } 19401 } else { 19402 rv = SOC_E_FAIL; 19403 } 19404 } else { 19405 if (old_entry != NULL) { 19406 sal_memcpy(old_entry, data, entry_dw * sizeof(uint32)); 19407 } 19408 if (index_ptr != NULL) { 19409 *index_ptr = index; 19410 } 19411 /* Update cache if active */ 19412 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 19413 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 19414 index_valid = (index >= 0 && 19415 index <= soc_mem_index_max(unit, mem)); 19416 19417 if (index_valid && cache != NULL && CACHE_VMAP_TST(vmap, index) 19418 && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 19419 sal_memcpy(cache + index * entry_dw, null_entry, entry_dw * 4); 19420 CACHE_VMAP_SET(vmap, index); 19421 } 19422 } 19423 SOC_ALPM_LPM_UNLOCK(unit); 19424 SOC_CONTROL_LOCK(unit); 19425 SHR_BITCLR(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_DELETE); 19426 SOC_CONTROL_UNLOCK(unit); 19427 19428 return rv; 19429 } 19430 #endif /* ALPM_ENABLE */ 19431 19432 #ifdef BCM_TRX_SUPPORT 19433 #define HASH_DUAL 0 19434 #define HASH_SHARED 1 19435 #define HASH_MULTI 2 19436 STATIC int 19437 _soc_mem_dual_hash_get(int unit, soc_mem_t mem, int hash_sel, int bank, 19438 void *entry_data); 19439 19440 STATIC int 19441 soc_hash_mem_bank_type_get (int unit, soc_mem_t mem, uint32* type) 19442 { 19443 #ifdef BCM_TRX_SUPPORT 19444 if (SOC_IS_TRX(unit)) { 19445 _SOC_MEM_REPLACE_MEM(unit, mem); 19446 switch (mem) { 19447 /* Intentional fall through */ 19448 /* coverity[unterminated_case] */ 19449 case MPLS_ENTRYm: 19450 if (SOC_IS_SC_CQ(unit)) { 19451 return SOC_E_UNAVAIL; 19452 } 19453 case VLAN_XLATEm: 19454 /* Intentional fall through */ 19455 /* coverity[unterminated_case] */ 19456 case EGR_VLAN_XLATEm: 19457 #ifdef BCM_ISM_SUPPORT 19458 if (soc_feature(unit, soc_feature_ism_memory) && 19459 soc_mem_is_mview(unit, mem)) { 19460 *type = HASH_MULTI; 19461 return SOC_E_NONE; 19462 } 19463 #endif 19464 case VLAN_MACm: 19465 case AXP_WRX_WCDm: 19466 case AXP_WRX_SVP_ASSIGNMENTm: 19467 #ifdef BCM_TRIDENT2_SUPPORT 19468 case ING_VP_VLAN_MEMBERSHIPm: 19469 case EGR_VP_VLAN_MEMBERSHIPm: 19470 case ING_DNAT_ADDRESS_TYPEm: 19471 case L2_ENDPOINT_IDm: 19472 case ENDPOINT_QUEUE_MAPm: 19473 #endif 19474 #ifdef BCM_TRIDENT3_SUPPORT 19475 case SUBPORT_ID_TO_SGPP_MAPm: 19476 #endif 19477 #ifdef BCM_KATANA2_SUPPORT 19478 case EGR_MP_GROUPm: 19479 #endif 19480 #ifdef BCM_SABER2_SUPPORT 19481 case MP_GROUPm: 19482 #endif 19483 *type = HASH_DUAL; 19484 return SOC_E_NONE; 19485 #ifdef BCM_ISM_SUPPORT 19486 case L2_ENTRY_1m: 19487 case L2_ENTRY_2m: 19488 case L3_ENTRY_1m: 19489 case L3_ENTRY_2m: 19490 case L3_ENTRY_4m: 19491 case VLAN_XLATE_EXTDm: 19492 case MPLS_ENTRY_EXTDm: 19493 if (soc_feature(unit, soc_feature_ism_memory) && 19494 soc_mem_is_mview(unit, mem)) { 19495 *type = HASH_MULTI; 19496 return SOC_E_NONE; 19497 } 19498 break; 19499 #endif /* BCM_ISM_SUPPORT */ 19500 default: 19501 break; 19502 } 19503 } 19504 #endif /* BCM_TRX_SUPPORT */ 19505 19506 #ifdef BCM_FIREBOLT_SUPPORT 19507 if (SOC_IS_FBX(unit)) { 19508 switch (mem) { 19509 case L2Xm: 19510 #ifdef BCM_TRIDENT2_SUPPORT 19511 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 19512 *type = HASH_SHARED; 19513 return SOC_E_NONE; 19514 } 19515 #endif /* BCM_TRIDENT2_SUPPORT */ 19516 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 19517 defined(BCM_TRX_SUPPORT) 19518 if (soc_feature(unit, soc_feature_dual_hash)) { 19519 *type = HASH_DUAL; 19520 return SOC_E_NONE; 19521 } 19522 #endif 19523 /* Insert via ARL_INSERT_CMD_MSG, not TABLE_INSERT_CMD_MSG */ 19524 break; 19525 #if defined(INCLUDE_L3) 19526 case L3_ENTRY_ONLYm: 19527 case L3_ENTRY_IPV4_UNICASTm: 19528 case L3_ENTRY_IPV4_MULTICASTm: 19529 case L3_ENTRY_IPV6_UNICASTm: 19530 case L3_ENTRY_IPV6_MULTICASTm: 19531 #ifdef BCM_TRIDENT2_SUPPORT 19532 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 19533 *type = HASH_SHARED; 19534 return SOC_E_NONE; 19535 } 19536 #endif /* BCM_TRIDENT2_SUPPORT */ 19537 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \ 19538 defined(BCM_RAVEN_SUPPORT) 19539 if (soc_feature(unit, soc_feature_dual_hash)) { 19540 *type = HASH_DUAL; 19541 return SOC_E_NONE; 19542 } 19543 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT || BCM_TRX_SUPPORT */ 19544 #endif /* INCLUDE_L3 */ 19545 /* Insert via L3_INSERT_CMD_MSG, not TABLE_INSERT_CMD_MSG */ 19546 break; 19547 case VLAN_MACm: 19548 #if defined(BCM_RAVEN_SUPPORT) 19549 if (soc_feature(unit, soc_feature_dual_hash) && 19550 (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) { 19551 *type = HASH_DUAL; 19552 return SOC_E_NONE; 19553 } else 19554 #endif 19555 { 19556 /* Via memory read/write */ 19557 } 19558 break; 19559 #if defined(BCM_TOMAHAWK_SUPPORT) 19560 case EXACT_MATCH_2m: 19561 case EXACT_MATCH_2_PIPE0m: 19562 case EXACT_MATCH_2_PIPE1m: 19563 case EXACT_MATCH_2_PIPE2m: 19564 case EXACT_MATCH_2_PIPE3m: 19565 case EXACT_MATCH_4m: 19566 case EXACT_MATCH_4_PIPE0m: 19567 case EXACT_MATCH_4_PIPE1m: 19568 case EXACT_MATCH_4_PIPE2m: 19569 case EXACT_MATCH_4_PIPE3m: 19570 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 19571 case L3_ENTRY_SINGLEm: 19572 case L3_ENTRY_DOUBLEm: 19573 case L3_ENTRY_QUADm: 19574 case VLAN_XLATE_1_SINGLEm: 19575 case VLAN_XLATE_2_SINGLEm: 19576 case VLAN_XLATE_1_DOUBLEm: 19577 case VLAN_XLATE_2_DOUBLEm: 19578 case EGR_VLAN_XLATE_1_SINGLEm: 19579 case EGR_VLAN_XLATE_2_SINGLEm: 19580 case EGR_VLAN_XLATE_1_DOUBLEm: 19581 case EGR_VLAN_XLATE_2_DOUBLEm: 19582 case MPLS_ENTRY_SINGLEm: 19583 case L3_TUNNEL_SINGLEm: 19584 case L3_TUNNEL_DOUBLEm: 19585 case L3_TUNNEL_QUADm: 19586 #endif 19587 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 19588 *type = HASH_SHARED; 19589 return SOC_E_NONE; 19590 } 19591 #endif 19592 default: 19593 break; 19594 } 19595 } 19596 #endif 19597 #ifdef BCM_ISM_SUPPORT 19598 if (soc_feature(unit, soc_feature_ism_memory) && 19599 soc_mem_is_hashed(unit, mem) && 19600 soc_mem_is_mview(unit, mem)) { 19601 *type = HASH_MULTI; 19602 return SOC_E_NONE; 19603 } 19604 #endif /* BCM_ISM_SUPPORT */ 19605 19606 return SOC_E_INTERNAL; 19607 } 19608 19609 19610 STATIC int 19611 soc_hash_mem_dual_hash_info_get (int unit, soc_mem_t mem, dual_hash_info_t *hash_info) 19612 { 19613 int rv = SOC_E_INTERNAL; 19614 19615 switch (mem) { 19616 case L2Xm: 19617 SOC_IF_ERROR_RETURN 19618 (soc_fb_l2x_entry_bank_hash_sel_get(unit, 0, 19619 &(hash_info->hash_sel0))); 19620 SOC_IF_ERROR_RETURN 19621 (soc_fb_l2x_entry_bank_hash_sel_get(unit, 1, 19622 &(hash_info->hash_sel1))); 19623 hash_info->bucket_size = SOC_L2X_BUCKET_SIZE; 19624 hash_info->base_mem = mem; 19625 rv = SOC_E_NONE; 19626 break; 19627 #ifdef BCM_TRX_SUPPORT 19628 case VLAN_XLATEm: 19629 #ifdef BCM_TRIDENT3_SUPPORT 19630 case SUBPORT_ID_TO_SGPP_MAPm: 19631 #endif 19632 if (!SOC_IS_TRX(unit)) { 19633 break; 19634 } 19635 #endif 19636 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRX_SUPPORT) 19637 case VLAN_MACm: 19638 if (SOC_IS_FIREBOLT2(unit)) { 19639 break; 19640 } 19641 #ifdef BCM_TRX_SUPPORT 19642 #ifdef BCM_TRIDENT2_SUPPORT 19643 if (SOC_IS_TD2_TT2(unit)) { 19644 SOC_IF_ERROR_RETURN 19645 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19646 SOC_IF_ERROR_RETURN 19647 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19648 hash_info->bucket_size = SOC_VLAN_XLATE_BUCKET_SIZE; 19649 hash_info->base_mem = mem; 19650 rv = SOC_E_NONE; 19651 } else 19652 #endif 19653 { 19654 if (mem == VLAN_XLATEm) { 19655 SOC_IF_ERROR_RETURN 19656 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19657 SOC_IF_ERROR_RETURN 19658 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19659 hash_info->bucket_size = SOC_VLAN_XLATE_BUCKET_SIZE; 19660 hash_info->base_mem = mem; 19661 rv = SOC_E_NONE; 19662 } else 19663 #endif 19664 { 19665 SOC_IF_ERROR_RETURN 19666 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &(hash_info->hash_sel0))); 19667 19668 SOC_IF_ERROR_RETURN 19669 (soc_fb_rv_vlanmac_hash_sel_get(unit, 1, &(hash_info->hash_sel1))); 19670 hash_info->bucket_size = SOC_VLAN_MAC_BUCKET_SIZE; 19671 hash_info->base_mem = mem; 19672 rv = SOC_E_NONE; 19673 } 19674 } 19675 break; 19676 #endif 19677 19678 #if defined(BCM_TRX_SUPPORT) 19679 case MPLS_ENTRYm: 19680 SOC_IF_ERROR_RETURN 19681 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19682 SOC_IF_ERROR_RETURN 19683 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19684 hash_info->bucket_size = SOC_MPLS_ENTRY_BUCKET_SIZE; 19685 hash_info->base_mem = mem; 19686 rv = SOC_E_NONE; 19687 break; 19688 case EGR_VLAN_XLATEm: 19689 SOC_IF_ERROR_RETURN 19690 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19691 SOC_IF_ERROR_RETURN 19692 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19693 hash_info->bucket_size = SOC_EGR_VLAN_XLATE_BUCKET_SIZE; 19694 hash_info->base_mem = mem; 19695 rv = SOC_E_NONE; 19696 break; 19697 case AXP_WRX_WCDm: 19698 case AXP_WRX_SVP_ASSIGNMENTm: 19699 SOC_IF_ERROR_RETURN 19700 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19701 SOC_IF_ERROR_RETURN 19702 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19703 hash_info->bucket_size = SOC_WLAN_BUCKET_SIZE; 19704 hash_info->base_mem = mem; 19705 rv = SOC_E_NONE; 19706 break; 19707 #ifdef BCM_TRIDENT2_SUPPORT 19708 case ING_VP_VLAN_MEMBERSHIPm: 19709 SOC_IF_ERROR_RETURN 19710 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19711 SOC_IF_ERROR_RETURN 19712 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19713 hash_info->bucket_size = SOC_ING_VP_VLAN_MEMBER_BUCKET_SIZE; 19714 hash_info->base_mem = mem; 19715 rv = SOC_E_NONE; 19716 break; 19717 case EGR_VP_VLAN_MEMBERSHIPm: 19718 SOC_IF_ERROR_RETURN 19719 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19720 SOC_IF_ERROR_RETURN 19721 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19722 hash_info->bucket_size = SOC_EGR_VP_VLAN_MEMBER_BUCKET_SIZE; 19723 hash_info->base_mem = mem; 19724 rv = SOC_E_NONE; 19725 break; 19726 case ING_DNAT_ADDRESS_TYPEm: 19727 SOC_IF_ERROR_RETURN 19728 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19729 SOC_IF_ERROR_RETURN 19730 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19731 hash_info->bucket_size = SOC_ING_DNAT_ADDRESS_TYPE_BUCKET_SIZE; 19732 hash_info->base_mem = mem; 19733 rv = SOC_E_NONE; 19734 break; 19735 case L2_ENDPOINT_IDm: 19736 SOC_IF_ERROR_RETURN 19737 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19738 SOC_IF_ERROR_RETURN 19739 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19740 hash_info->bucket_size = SOC_L2_ENDPOINT_ID_BUCKET_SIZE; 19741 hash_info->base_mem = mem; 19742 rv = SOC_E_NONE; 19743 break; 19744 case ENDPOINT_QUEUE_MAPm: 19745 SOC_IF_ERROR_RETURN 19746 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19747 SOC_IF_ERROR_RETURN 19748 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19749 hash_info->bucket_size = SOC_ENDPOINT_QUEUE_MAP_BUCKET_SIZE; 19750 hash_info->base_mem = mem; 19751 rv = SOC_E_NONE; 19752 break; 19753 19754 #endif 19755 #ifdef BCM_KATANA2_SUPPORT 19756 case EGR_MP_GROUPm: 19757 19758 SOC_IF_ERROR_RETURN 19759 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19760 SOC_IF_ERROR_RETURN 19761 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19762 hash_info->bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE; 19763 hash_info->base_mem = mem; 19764 rv = SOC_E_NONE; 19765 break; 19766 #endif 19767 #ifdef BCM_SABER2_SUPPORT 19768 case MP_GROUPm: 19769 19770 SOC_IF_ERROR_RETURN 19771 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0)); 19772 SOC_IF_ERROR_RETURN 19773 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1)); 19774 hash_info->bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE; 19775 hash_info->base_mem = mem; 19776 rv = SOC_E_NONE; 19777 break; 19778 #endif 19779 #endif /* BCM_TRX_SUPPORT */ 19780 #if defined(INCLUDE_L3) 19781 case L3_ENTRY_ONLYm: 19782 case L3_ENTRY_IPV4_UNICASTm: 19783 case L3_ENTRY_IPV4_MULTICASTm: 19784 case L3_ENTRY_IPV6_UNICASTm: 19785 case L3_ENTRY_IPV6_MULTICASTm: 19786 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \ 19787 defined(BCM_RAVEN_SUPPORT) 19788 if (soc_feature(unit, soc_feature_dual_hash)) { 19789 SOC_IF_ERROR_RETURN 19790 (soc_fb_l3x_entry_bank_hash_sel_get(unit, 0, 19791 &(hash_info->hash_sel0))); 19792 SOC_IF_ERROR_RETURN 19793 (soc_fb_l3x_entry_bank_hash_sel_get(unit, 1, 19794 &(hash_info->hash_sel1))); 19795 hash_info->bucket_size = SOC_L3X_BUCKET_SIZE(unit); 19796 hash_info->base_mem = L3_ENTRY_IPV4_UNICASTm; 19797 #if defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 19798 if (soc_feature(unit, soc_feature_hr2_dual_hash) || 19799 SOC_IS_KATANA2(unit) || SOC_IS_TRIDENT(unit)) { 19800 hash_info->bucket_size = 19801 _soc_mem_hash_entries_per_bkt(unit, mem); 19802 } 19803 #endif /* BCM_HURRICANE2_SUPPORT */ 19804 rv = SOC_E_NONE; 19805 } 19806 #endif 19807 break; 19808 #endif 19809 default: 19810 break; 19811 } 19812 return rv; 19813 } 19814 19815 STATIC int 19816 soc_ser_hash_mem_bank_correction(int unit, soc_mem_t mem, schan_msg_t* schan_msg, 19817 uint32 base_index, uint32 size) 19818 { 19819 int i, rv; 19820 uint32 recovery_view_index; 19821 _soc_ser_correct_info_t spci; 19822 sal_memset(&spci, 0, sizeof(spci)); 19823 19824 spci.flags = SOC_SER_SRC_MEM | SOC_SER_REG_MEM_KNOWN; 19825 /* If one entry has parity error, mem access in other 19826 * entry of same bucket will trigger SBUS NACK. So 19827 * all entties need to be corrected. */ 19828 spci.flags |= SOC_SER_SKIP_HARD_FALT_CHECK; 19829 spci.reg = INVALIDr; 19830 spci.mem = mem; 19831 spci.pipe_num = SOC_PIPE_ANY; 19832 spci.blk_type = SOC_BLOCK_ANY; 19833 spci.sblk = 0; 19834 spci.addr = schan_msg->gencmd.address; 19835 recovery_view_index = base_index; 19836 19837 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 19838 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_APACHE(unit)) { 19839 switch (mem) { 19840 case L3_ENTRY_ONLYm: 19841 case L3_ENTRY_IPV4_UNICASTm: 19842 spci.mem = L3_ENTRY_ONLY_ECCm; 19843 recovery_view_index = base_index; 19844 break; 19845 case L3_ENTRY_IPV4_MULTICASTm: 19846 case L3_ENTRY_IPV6_UNICASTm: 19847 spci.mem = L3_ENTRY_ONLY_ECCm; 19848 recovery_view_index = base_index * 2; 19849 break; 19850 case L3_ENTRY_IPV6_MULTICASTm: 19851 spci.mem = L3_ENTRY_ONLY_ECCm; 19852 recovery_view_index = base_index * 4; 19853 break; 19854 case L2Xm: 19855 #ifdef BCM_TOMAHAWK3_SUPPORT 19856 if (SOC_IS_TOMAHAWK3(unit)) { 19857 spci.mem = L2_ENTRY_ECCm; 19858 } else 19859 #endif 19860 { 19861 spci.mem = L2_ENTRY_ONLY_ECCm; 19862 } 19863 recovery_view_index = base_index; 19864 break; 19865 case VLAN_MACm: 19866 case VLAN_XLATEm: 19867 spci.mem = VLAN_XLATE_ECCm; 19868 recovery_view_index = base_index; 19869 break; 19870 case EGR_VLAN_XLATEm: 19871 spci.mem = EGR_VLAN_XLATE_ECCm; 19872 recovery_view_index = base_index; 19873 break; 19874 case MPLS_ENTRYm: 19875 spci.mem = MPLS_ENTRY_ECCm; 19876 recovery_view_index = base_index; 19877 #ifdef BCM_APACHE_SUPPORT 19878 if (SOC_IS_APACHE(unit)) { 19879 /* No ECC view for MPLS_ENTRY */ 19880 spci.mem = MPLS_ENTRYm; 19881 recovery_view_index = base_index; 19882 } 19883 #endif 19884 break; 19885 case EXACT_MATCH_2m: 19886 #ifdef BCM_TOMAHAWK3_SUPPORT 19887 if (SOC_IS_TOMAHAWK3(unit)) { 19888 spci.mem = EXACT_MATCH_ECCm; 19889 recovery_view_index = base_index*2; 19890 } else 19891 #endif 19892 { 19893 spci.mem = FPEM_ECCm; 19894 recovery_view_index = base_index/2; 19895 } 19896 break; 19897 case EXACT_MATCH_2_PIPE0m: 19898 spci.pipe_num = 0; 19899 spci.mem = FPEM_ECCm; 19900 recovery_view_index = base_index/2; 19901 break; 19902 case EXACT_MATCH_2_PIPE1m: 19903 spci.pipe_num = 1; 19904 spci.mem = FPEM_ECCm; 19905 recovery_view_index = base_index/2; 19906 break; 19907 case EXACT_MATCH_2_PIPE2m: 19908 spci.pipe_num = 2; 19909 spci.mem = FPEM_ECCm; 19910 recovery_view_index = base_index/2; 19911 break; 19912 case EXACT_MATCH_2_PIPE3m: 19913 spci.pipe_num = 3; 19914 spci.mem = FPEM_ECCm; 19915 recovery_view_index = base_index/2; 19916 break; 19917 case EXACT_MATCH_4m: 19918 #ifdef BCM_TOMAHAWK3_SUPPORT 19919 if (SOC_IS_TOMAHAWK3(unit)) { 19920 spci.mem = EXACT_MATCH_ECCm; 19921 recovery_view_index = base_index*4; 19922 } else 19923 #endif 19924 { 19925 spci.mem = FPEM_ECCm; 19926 recovery_view_index = base_index/4; 19927 } 19928 break; 19929 case EXACT_MATCH_4_PIPE0m: 19930 spci.pipe_num = 0; 19931 spci.mem = FPEM_ECCm; 19932 recovery_view_index = base_index/4; 19933 break; 19934 case EXACT_MATCH_4_PIPE1m: 19935 spci.pipe_num = 1; 19936 spci.mem = FPEM_ECCm; 19937 recovery_view_index = base_index/4; 19938 break; 19939 case EXACT_MATCH_4_PIPE2m: 19940 spci.pipe_num = 2; 19941 spci.mem = FPEM_ECCm; 19942 recovery_view_index = base_index/4; 19943 break; 19944 case EXACT_MATCH_4_PIPE3m: 19945 spci.pipe_num = 3; 19946 spci.mem = FPEM_ECCm; 19947 recovery_view_index = base_index/4; 19948 break; 19949 #ifdef BCM_TOMAHAWK3_SUPPORT 19950 case L3_ENTRY_SINGLEm: 19951 if (SOC_IS_TOMAHAWK3(unit)) { 19952 spci.mem = L3_ENTRY_ECCm; 19953 recovery_view_index = base_index; 19954 } 19955 break; 19956 case L3_ENTRY_DOUBLEm: 19957 if (SOC_IS_TOMAHAWK3(unit)) { 19958 spci.mem = L3_ENTRY_ECCm; 19959 recovery_view_index = base_index * 2; 19960 } 19961 break; 19962 case L3_ENTRY_QUADm: 19963 if (SOC_IS_TOMAHAWK3(unit)) { 19964 spci.mem = L3_ENTRY_ECCm; 19965 recovery_view_index = base_index * 4; 19966 } 19967 break; 19968 case L3_TUNNEL_SINGLEm: 19969 if (SOC_IS_TOMAHAWK3(unit)) { 19970 spci.mem = L3_TUNNEL_ECCm; 19971 recovery_view_index = base_index; 19972 } 19973 break; 19974 case L3_TUNNEL_DOUBLEm: 19975 if (SOC_IS_TOMAHAWK3(unit)) { 19976 spci.mem = L3_TUNNEL_ECCm; 19977 recovery_view_index = base_index * 2; 19978 } 19979 break; 19980 case L3_TUNNEL_QUADm: 19981 if (SOC_IS_TOMAHAWK3(unit)) { 19982 spci.mem = L3_TUNNEL_ECCm; 19983 recovery_view_index = base_index * 4; 19984 } 19985 break; 19986 case MPLS_ENTRY_SINGLEm: 19987 if (SOC_IS_TOMAHAWK3(unit)) { 19988 spci.mem = MPLS_ENTRY_ECCm; 19989 recovery_view_index = base_index; 19990 } 19991 break; 19992 #endif 19993 default: 19994 break; 19995 } 19996 } else 19997 #endif 19998 { 19999 switch (mem) { 20000 case L3_ENTRY_ONLYm: 20001 case L3_ENTRY_IPV4_UNICASTm: 20002 spci.mem = L3_ENTRY_ONLYm; 20003 recovery_view_index = base_index; 20004 break; 20005 case L3_ENTRY_IPV4_MULTICASTm: 20006 case L3_ENTRY_IPV6_UNICASTm: 20007 spci.mem = L3_ENTRY_ONLYm; 20008 recovery_view_index = base_index * 2; 20009 break; 20010 case L3_ENTRY_IPV6_MULTICASTm: 20011 spci.mem = L3_ENTRY_ONLYm; 20012 recovery_view_index = base_index * 4; 20013 break; 20014 #if defined(BCM_TRIDENT3_SUPPORT) 20015 case VLAN_XLATE_1_SINGLEm: 20016 case VLAN_XLATE_1_DOUBLEm: 20017 if (SOC_IS_TRIDENT3X(unit)) { 20018 spci.mem = VLAN_XLATE_1_ECCm; 20019 recovery_view_index = base_index; 20020 } 20021 break; 20022 case VLAN_XLATE_2_SINGLEm: 20023 case VLAN_XLATE_2_DOUBLEm: 20024 if (SOC_IS_TRIDENT3X(unit)) { 20025 spci.mem = VLAN_XLATE_2_ECCm; 20026 recovery_view_index = base_index; 20027 } 20028 break; 20029 case EGR_VLAN_XLATE_1_SINGLEm: 20030 case EGR_VLAN_XLATE_1_DOUBLEm: 20031 if (SOC_IS_TRIDENT3X(unit)) { 20032 spci.mem = EGR_VLAN_XLATE_1_ECCm; 20033 recovery_view_index = base_index; 20034 } 20035 break; 20036 case EGR_VLAN_XLATE_2_SINGLEm: 20037 case EGR_VLAN_XLATE_2_DOUBLEm: 20038 if (SOC_IS_TRIDENT3X(unit)) { 20039 spci.mem = EGR_VLAN_XLATE_2_ECCm; 20040 recovery_view_index = base_index; 20041 } 20042 break; 20043 case ING_VP_VLAN_MEMBERSHIPm: 20044 if (SOC_IS_TRIDENT3X(unit)) { 20045 spci.mem = ING_VP_VLAN_MEMBERSHIP_ECCm; 20046 recovery_view_index = base_index/2; 20047 size /= 2; 20048 } 20049 break; 20050 case EGR_VP_VLAN_MEMBERSHIPm: 20051 if (SOC_IS_TRIDENT3X(unit)) { 20052 spci.mem = EGR_VP_VLAN_MEMBERSHIP_ECCm; 20053 recovery_view_index = base_index/2; 20054 size /= 2; 20055 } 20056 break; 20057 case ING_DNAT_ADDRESS_TYPEm: 20058 if (SOC_IS_TRIDENT3X(unit)) { 20059 spci.mem = ING_DNAT_ADDRESS_TYPE_ECCm; 20060 recovery_view_index = base_index/2; 20061 size /= 2; 20062 } 20063 break; 20064 case SUBPORT_ID_TO_SGPP_MAPm: 20065 if (SOC_IS_TRIDENT3X(unit)) { 20066 spci.mem = SUBPORT_ID_TO_SGPP_MAP_ECCm; 20067 recovery_view_index = base_index/2; 20068 size /= 2; 20069 } 20070 break; 20071 case EXACT_MATCH_4m: 20072 if (SOC_IS_TRIDENT3X(unit)) { 20073 spci.mem = EXACT_MATCH_ECCm; 20074 recovery_view_index = base_index*4; 20075 } 20076 break; 20077 case EXACT_MATCH_2m: 20078 if (SOC_IS_TRIDENT3X(unit)) { 20079 spci.mem = EXACT_MATCH_ECCm; 20080 recovery_view_index = base_index*2; 20081 } 20082 break; 20083 case EXACT_MATCH_4_PIPE0m: 20084 if (SOC_IS_TRIDENT3X(unit)) { 20085 spci.pipe_num = 0; 20086 spci.mem = EXACT_MATCH_ECC_PIPE0m; 20087 recovery_view_index = base_index*4; 20088 } 20089 break; 20090 case EXACT_MATCH_2_PIPE0m: 20091 if (SOC_IS_TRIDENT3X(unit)) { 20092 spci.pipe_num = 0; 20093 spci.mem = EXACT_MATCH_ECC_PIPE0m; 20094 recovery_view_index = base_index*2; 20095 } 20096 break; 20097 case EXACT_MATCH_4_PIPE1m: 20098 if (SOC_IS_TRIDENT3X(unit)) { 20099 spci.pipe_num = 1; 20100 spci.mem = EXACT_MATCH_ECC_PIPE1m; 20101 recovery_view_index = base_index*4; 20102 } 20103 break; 20104 case EXACT_MATCH_2_PIPE1m: 20105 if (SOC_IS_TRIDENT3X(unit)) { 20106 spci.pipe_num = 1; 20107 spci.mem = EXACT_MATCH_ECC_PIPE1m; 20108 recovery_view_index = base_index*2; 20109 } 20110 break; 20111 case L3_ENTRY_SINGLEm: 20112 if (SOC_IS_TRIDENT3X(unit)) { 20113 spci.mem = L3_ENTRY_ECCm; 20114 recovery_view_index = base_index; 20115 } 20116 break; 20117 case L3_ENTRY_DOUBLEm: 20118 if (SOC_IS_TRIDENT3X(unit)) { 20119 spci.mem = L3_ENTRY_ECCm; 20120 recovery_view_index = base_index * 2; 20121 } 20122 break; 20123 case L3_ENTRY_QUADm: 20124 if (SOC_IS_TRIDENT3X(unit)) { 20125 spci.mem = L3_ENTRY_ECCm; 20126 recovery_view_index = base_index * 4; 20127 } 20128 break; 20129 #endif 20130 case VLAN_MACm: 20131 if (SOC_IS_TRIDENT2PLUS(unit)) { 20132 spci.mem = VLAN_XLATE_ECCm; 20133 recovery_view_index = base_index; 20134 } 20135 break; 20136 default: 20137 break; 20138 } 20139 } 20140 20141 for (i = 0; i < size; i++) { 20142 spci.index = recovery_view_index + i; 20143 rv = soc_ser_correction(unit, &spci); 20144 if (SOC_FAILURE(rv)) { 20145 /* Report failed to correct event flag to 20146 * application */ 20147 soc_event_generate(unit, 20148 SOC_SWITCH_EVENT_PARITY_ERROR, 20149 SOC_SWITCH_EVENT_DATA_ERROR_FAILEDTOCORRECT, 20150 spci.mem, 20151 spci.index); 20152 return rv; 20153 } 20154 } 20155 return SOC_E_NONE; 20156 } 20157 20158 20159 STATIC int 20160 soc_hash_mem_inline_recovery(int unit, soc_mem_t mem, schan_msg_t* schan_msg, 20161 int32 bank, void *entry) 20162 { 20163 uint32 type, bank_idx, bucket_index; 20164 int half_bucket, hash_sel, hash_base; 20165 #if defined(BCM_TRIDENT2_SUPPORT) 20166 uint32 bucket = 0; 20167 int index, num_banks, bank_ids[7]; 20168 #endif 20169 #ifdef BCM_ISM_SUPPORT 20170 int ism_index; 20171 uint8 num_ent; 20172 uint32 result; 20173 _soc_ism_mem_banks_t mem_banks; 20174 #endif 20175 dual_hash_info_t hash_info = {0}; 20176 20177 SOC_IF_ERROR_RETURN(soc_hash_mem_bank_type_get(unit, mem, &type)); 20178 20179 switch (type) { 20180 case HASH_DUAL: 20181 #ifdef BCM_TRIDENT3_SUPPORT 20182 if (SOC_IS_TRIDENT3X(unit)) { 20183 for (bank_idx = 0; bank_idx < 2; bank_idx++) { 20184 SOC_IF_ERROR_RETURN 20185 (soc_td3_hash_bucket_get(unit, mem, bank_idx, 20186 entry, &bucket)); 20187 index = soc_td3_hash_index_get(unit, mem, bank_idx, 20188 bucket); 20189 SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem, 20190 schan_msg, index, 4)); 20191 } 20192 } else 20193 #endif /* BCM_TRIDENT3_SUPPORT */ 20194 { 20195 SOC_IF_ERROR_RETURN(soc_hash_mem_dual_hash_info_get(unit, mem, &hash_info)); 20196 half_bucket = hash_info.bucket_size / 2; 20197 /* For dual bank hash table, one entry may be located in one of two 20198 * different hash buckets, thus different entry index in two banks, 20199 * any parity error in these two buckets will cause insert/delete fail. 20200 * We have to restore both buckets. 20201 */ 20202 for (bank_idx = 0; bank_idx < 2; bank_idx++) { 20203 hash_sel = (bank_idx == 0) ? hash_info.hash_sel0 : hash_info.hash_sel1; 20204 hash_base = _soc_mem_dual_hash_get(unit, mem, hash_sel, bank_idx, 20205 entry); 20206 if (hash_base == -1) { 20207 return SOC_E_INTERNAL; 20208 } 20209 bucket_index = hash_base * hash_info.bucket_size + bank_idx * half_bucket; 20210 SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem, 20211 schan_msg, bucket_index, 20212 half_bucket)); 20213 } 20214 } 20215 break; 20216 case HASH_SHARED: 20217 #if defined(BCM_TRIDENT2_SUPPORT) 20218 20219 #ifdef BCM_APACHE_SUPPORT 20220 if (SOC_IS_APACHE(unit)) { 20221 SOC_IF_ERROR_RETURN 20222 (soc_apache_hash_bank_count_get(unit, mem, &num_banks)); 20223 } else 20224 #endif /* APACHE_SUPPORT */ 20225 #ifdef BCM_TOMAHAWK_SUPPORT 20226 if (SOC_IS_TOMAHAWKX(unit)) { 20227 #ifdef BCM_TOMAHAWK3_SUPPORT 20228 if (SOC_IS_TOMAHAWK3(unit)) { 20229 SOC_IF_ERROR_RETURN 20230 (soc_tomahawk3_hash_bank_count_get(unit, mem, &num_banks)); 20231 } else 20232 #endif /* BCM_TOMAHAWK3_SUPPORT */ 20233 { 20234 SOC_IF_ERROR_RETURN 20235 (soc_tomahawk_hash_bank_count_get(unit, mem, &num_banks)); 20236 } 20237 } else 20238 #endif /* BCM_TOMAHAWK_SUPPORT */ 20239 #ifdef BCM_HELIX5_SUPPORT 20240 if (SOC_IS_HELIX5(unit)) { 20241 SOC_IF_ERROR_RETURN 20242 (soc_helix5_hash_bank_count_get(unit, mem, &num_banks)); 20243 } else 20244 #endif /* BCM_HELIX5_SUPPORT */ 20245 #ifdef BCM_TRIDENT3_SUPPORT 20246 if (SOC_IS_TRIDENT3X(unit)) { 20247 SOC_IF_ERROR_RETURN 20248 (soc_trident3_hash_bank_count_get(unit, mem, &num_banks)); 20249 } else 20250 #endif /* BCM_TRIDENT3_SUPPORT */ 20251 { 20252 SOC_IF_ERROR_RETURN 20253 (soc_trident2_hash_bank_count_get(unit, mem, &num_banks)); 20254 } 20255 for (bank_idx = 0; bank_idx < num_banks; bank_idx++) { 20256 20257 #ifdef BCM_APACHE_SUPPORT 20258 if (SOC_IS_APACHE(unit)) { 20259 SOC_IF_ERROR_RETURN 20260 (soc_apache_hash_bank_number_get(unit, mem, bank_idx, 20261 &bank_ids[bank_idx])); 20262 SOC_IF_ERROR_RETURN 20263 (soc_ap_hash_bucket_get(unit, mem, bank_ids[bank_idx], 20264 entry, &bucket)); 20265 index = soc_ap_hash_index_get(unit, mem, bank_ids[bank_idx], bucket); 20266 } else 20267 #endif /* BCM_APACHE_SUPPORT */ 20268 #ifdef BCM_TOMAHAWK_SUPPORT 20269 if (SOC_IS_TOMAHAWKX(unit)) { 20270 #ifdef BCM_TOMAHAWK3_SUPPORT 20271 if (SOC_IS_TOMAHAWK3(unit)) { 20272 SOC_IF_ERROR_RETURN 20273 (soc_tomahawk3_hash_bank_number_get(unit, mem, bank_idx, 20274 &bank_ids[bank_idx])); 20275 SOC_IF_ERROR_RETURN 20276 (soc_tomahawk3_hash_bucket_get(unit, mem, bank_ids[bank_idx], 20277 entry, &bucket)); 20278 index = soc_tomahawk3_hash_index_get(unit, mem, bank_ids[bank_idx], bucket); 20279 } else 20280 #endif /* BCM_TOMAHAWK3_SUPPORT */ 20281 { 20282 SOC_IF_ERROR_RETURN 20283 (soc_tomahawk_hash_bank_number_get(unit, mem, bank_idx, 20284 &bank_ids[bank_idx])); 20285 SOC_IF_ERROR_RETURN 20286 (soc_th_hash_bucket_get(unit, mem, bank_ids[bank_idx], 20287 entry, &bucket)); 20288 index = soc_th_hash_index_get(unit, mem, bank_ids[bank_idx], bucket); 20289 } 20290 } else 20291 #endif /* BCM_TOMAHAWK_SUPPORT */ 20292 #ifdef BCM_HELIX5_SUPPORT 20293 if (SOC_IS_HELIX5(unit)) { 20294 SOC_IF_ERROR_RETURN 20295 (soc_hx5_hash_bank_number_get(unit, mem, bank_idx, 20296 &bank_ids[bank_idx])); 20297 SOC_IF_ERROR_RETURN 20298 (soc_hx5_hash_bucket_get(unit, mem, bank_ids[bank_idx], 20299 entry, &bucket)); 20300 index = soc_hx5_hash_index_get(unit, mem, bank_ids[bank_idx], 20301 bucket); 20302 } else 20303 #endif /* BCM_HELIX5_SUPPORT */ 20304 #ifdef BCM_TRIDENT3_SUPPORT 20305 if (SOC_IS_TRIDENT3X(unit)) { 20306 SOC_IF_ERROR_RETURN 20307 (soc_td3_hash_bank_number_get(unit, mem, bank_idx, 20308 &bank_ids[bank_idx])); 20309 SOC_IF_ERROR_RETURN 20310 (soc_td3_hash_bucket_get(unit, mem, bank_ids[bank_idx], 20311 entry, &bucket)); 20312 index = soc_td3_hash_index_get(unit, mem, bank_ids[bank_idx], 20313 bucket); 20314 } else 20315 #endif /* BCM_TRIDENT3_SUPPORT */ 20316 { 20317 SOC_IF_ERROR_RETURN 20318 (soc_trident2_hash_bank_number_get(unit, mem, bank_idx, 20319 &bank_ids[bank_idx])); 20320 SOC_IF_ERROR_RETURN 20321 (soc_hash_bucket_get(unit, mem, bank_ids[bank_idx], 20322 entry, &bucket)); 20323 index = soc_hash_index_get(unit, mem, bank_ids[bank_idx], bucket); 20324 } 20325 SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem, 20326 schan_msg, index, 4)); 20327 } 20328 #endif 20329 break; 20330 case HASH_MULTI: 20331 #ifdef BCM_ISM_SUPPORT 20332 sal_memset(&mem_banks, 0, sizeof(mem_banks)); 20333 SOC_IF_ERROR_RETURN(soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks, 20334 mem_banks.bank_size, &mem_banks.count)); 20335 for (bank_idx = 0; bank_idx < mem_banks.count; bank_idx++) { 20336 bank = (uint32)1 << mem_banks.banks[bank_idx]; 20337 SOC_IF_ERROR_RETURN(soc_generic_hash(unit, mem, entry, bank, 0, &ism_index, 20338 &result, &bucket_index, &num_ent)); 20339 SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem, 20340 schan_msg, bucket_index * num_ent, 20341 num_ent)); 20342 } 20343 #endif 20344 break; 20345 default: 20346 return SOC_E_FAIL; 20347 } 20348 return SOC_E_NONE; 20349 } 20350 #endif 20351 20352 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 20353 /* TH: 20354 * For insert, delete operations to all hash tables, SER event could be only for 20355 * functional view (fv). rsp_word indicates index to _ECC view and not to funct 20356 * view - and ser_correction should be invoked with correct _ECC view. 20357 */ 20358 STATIC int 20359 _soc_inline_ser_mem_remap(int unit, soc_mem_t *mem, int *pipe, int *iratio) 20360 { 20361 int out_pipe = SOC_PIPE_ANY, out_iratio = 1; 20362 soc_mem_t out_mem = FPEM_ECCm; 20363 20364 if (NULL == mem || NULL == pipe || NULL == iratio) { 20365 return SOC_E_PARAM; 20366 } 20367 20368 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 20369 if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) { 20370 out_mem = EXACT_MATCH_ECCm; 20371 } 20372 #endif 20373 20374 switch (*mem) { 20375 case L3_ENTRY_IPV4_UNICASTm: 20376 case L3_ENTRY_ONLYm: 20377 out_mem = L3_ENTRY_ONLY_ECCm; 20378 break; 20379 case L3_ENTRY_IPV4_MULTICASTm: 20380 case L3_ENTRY_IPV6_UNICASTm: 20381 out_mem = L3_ENTRY_ONLY_ECCm; 20382 out_iratio = 2; 20383 break; 20384 case L3_ENTRY_IPV6_MULTICASTm: 20385 out_mem = L3_ENTRY_ONLY_ECCm; 20386 out_iratio = 4; 20387 break; 20388 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 20389 case L3_ENTRY_SINGLEm: 20390 out_mem = L3_ENTRY_ECCm; 20391 break; 20392 case L3_ENTRY_DOUBLEm: 20393 out_mem = L3_ENTRY_ECCm; 20394 out_iratio = 2; 20395 break; 20396 case L3_ENTRY_QUADm: 20397 out_mem = L3_ENTRY_ECCm; 20398 out_iratio = 4; 20399 break; 20400 case L3_TUNNEL_SINGLEm: 20401 out_mem = L3_TUNNEL_ECCm; 20402 break; 20403 case L3_TUNNEL_DOUBLEm: 20404 out_mem = L3_TUNNEL_ECCm; 20405 out_iratio = 2; 20406 break; 20407 case L3_TUNNEL_QUADm: 20408 out_mem = L3_TUNNEL_ECCm; 20409 out_iratio = 4; 20410 break; 20411 #endif 20412 case L2Xm: 20413 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 20414 if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) { 20415 out_mem = L2_ENTRY_ECCm; 20416 } else 20417 #endif 20418 { 20419 out_mem = L2_ENTRY_ONLY_ECCm; 20420 } 20421 break; 20422 case VLAN_MACm: 20423 case VLAN_XLATEm: 20424 out_mem = VLAN_XLATE_ECCm; 20425 break; 20426 case EGR_VLAN_XLATEm: 20427 out_mem = EGR_VLAN_XLATE_ECCm; 20428 break; 20429 case MPLS_ENTRYm: 20430 #if defined(BCM_TOMAHAWK3_SUPPORT) 20431 case MPLS_ENTRY_SINGLEm: 20432 #endif 20433 out_mem = MPLS_ENTRY_ECCm; 20434 #if defined(BCM_APACHE_SUPPORT) 20435 if (SOC_IS_APACHE(unit)) { 20436 /* No ECC view for MPLS_ENTRY */ 20437 out_mem = MPLS_ENTRYm; 20438 } 20439 #endif 20440 break; 20441 case EXACT_MATCH_2m: 20442 out_iratio = 2; 20443 break; 20444 case EXACT_MATCH_2_PIPE0m: 20445 out_iratio = 2; 20446 out_pipe = 0; 20447 break; 20448 case EXACT_MATCH_2_PIPE1m: 20449 out_iratio = 2; 20450 out_pipe = 1; 20451 break; 20452 case EXACT_MATCH_2_PIPE2m: 20453 out_iratio = 2; 20454 out_pipe = 2; 20455 break; 20456 case EXACT_MATCH_2_PIPE3m: 20457 out_iratio = 2; 20458 out_pipe = 3; 20459 break; 20460 case EXACT_MATCH_4m: 20461 out_iratio = 4; 20462 break; 20463 case EXACT_MATCH_4_PIPE0m: 20464 out_iratio = 4; 20465 out_pipe = 0; 20466 break; 20467 case EXACT_MATCH_4_PIPE1m: 20468 out_iratio = 4; 20469 out_pipe = 1; 20470 break; 20471 case EXACT_MATCH_4_PIPE2m: 20472 out_iratio = 4; 20473 out_pipe = 2; 20474 break; 20475 case EXACT_MATCH_4_PIPE3m: 20476 out_iratio = 4; 20477 out_pipe = 3; 20478 break; 20479 case ING_DNAT_ADDRESS_TYPEm: 20480 out_mem = ING_DNAT_ADDRESS_TYPE_ECCm; 20481 break; 20482 case ING_VP_VLAN_MEMBERSHIPm: 20483 out_mem = ING_VP_VLAN_MEMBERSHIP_ECCm; 20484 break; 20485 case EGR_VP_VLAN_MEMBERSHIPm: 20486 out_mem = EGR_VP_VLAN_MEMBERSHIP_ECCm; 20487 break; 20488 case SUBPORT_ID_TO_SGPP_MAPm: 20489 out_mem = SUBPORT_ID_TO_SGPP_MAP_ECCm; 20490 break; 20491 default: 20492 out_mem = *mem; 20493 break; 20494 } 20495 *mem = out_mem; 20496 *pipe = out_pipe; 20497 *iratio = out_iratio; 20498 20499 return SOC_E_NONE; 20500 } 20501 #endif /* BCM_TOMAHAWK_SUPPORT */ 20502 20503 #if defined(BCM_GREYHOUND2_SUPPORT) 20504 /* 20505 * Function: 20506 * soc_mem_gh2_l2_sw_lookup 20507 * Purpose: 20508 * Use software method to lookup a L2 entry for GH2-B0 20509 * Parameters: 20510 * unit - StrataSwitch unit # 20511 * mem - L2 memory table 20512 * copyno - Which copy to search (if multiple copies) 20513 * banks - For dual hashing, which halves are selected (inverted) 20514 * key - entry to look up 20515 * result - entry to receive entire found entry 20516 * index_ptr - (OUT) If found, receives table index where found 20517 * Returns: 20518 * SOC_E_INTERNAL if retries exceeded or other internal error 20519 * SOC_E_NOT_FOUND if the entry is not found. 20520 * SOC_E_NONE (0) on success (entry found): 20521 * Notes: 20522 * Uses software lookup without using an LOOKUP message over the 20523 * S-Channel. 20524 */ 20525 STATIC int 20526 soc_mem_gh2_l2_sw_lookup( 20527 int unit, 20528 soc_mem_t mem, 20529 int copyno, 20530 int32 banks, 20531 void *key, 20532 void *result, 20533 int *index_ptr) 20534 { 20535 int rv; 20536 l2x_entry_t l2ent; 20537 bcm_vlan_t new_vid, old_vid; 20538 bcm_mac_t new_mac, old_mac; 20539 int cf_hit; 20540 int bank, min_bank, max_bank; 20541 int bucket, slot, index; 20542 int entries_per_row, entries_per_bucket; 20543 int bucket_offset; 20544 uint32 valid = 0, fval = 0; 20545 int index_valid; 20546 20547 if (mem != L2Xm) { 20548 return SOC_E_INTERNAL; 20549 } 20550 20551 if (index_ptr) { 20552 *index_ptr = -1; 20553 } 20554 20555 if (banks == SOC_MEM_HASH_BANK0_ONLY) { 20556 min_bank = max_bank = 0; 20557 } else if (banks == SOC_MEM_HASH_BANK1_ONLY) { 20558 min_bank = max_bank = 1; 20559 } else { 20560 min_bank = 0; 20561 max_bank = 1; 20562 } 20563 20564 cf_hit = -1; 20565 20566 entries_per_row = SOC_L2X_BUCKET_SIZE; 20567 entries_per_bucket = entries_per_row / 2; 20568 20569 MEM_LOCK(unit, mem); 20570 for (bank = min_bank; bank <= max_bank; bank++) { 20571 bucket_offset = bank * entries_per_bucket; 20572 bucket = soc_tr_l2x_bank_entry_hash(unit, bank, (uint32 *)key); 20573 for (slot = 0; slot < entries_per_bucket; slot++) { 20574 index = (bucket * entries_per_row) + bucket_offset + slot; 20575 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &l2ent); 20576 if (SOC_FAILURE(rv)) { 20577 MEM_UNLOCK(unit, mem); 20578 return rv; 20579 } 20580 20581 valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf); 20582 if (!valid) { 20583 continue; 20584 } 20585 20586 fval = soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf); 20587 if (fval != GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) { 20588 continue; 20589 } 20590 20591 /* Get existing L2 entry */ 20592 soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, old_mac); 20593 old_vid = soc_L2Xm_field32_get(unit, &l2ent, VLAN_IDf); 20594 20595 /* Get lookup L2 entry */ 20596 soc_L2Xm_mac_addr_get(unit, (l2x_entry_t *)key, 20597 MAC_ADDRf, new_mac); 20598 new_vid = soc_L2Xm_field32_get(unit, (l2x_entry_t *)key, 20599 VLAN_IDf); 20600 20601 if ((sal_memcmp(old_mac, new_mac, sizeof(bcm_mac_t)) == 0) && 20602 (new_vid == old_vid)) { 20603 /* Found entry */ 20604 cf_hit = index; 20605 break; 20606 } 20607 } 20608 20609 if (cf_hit != -1) { 20610 break; 20611 } 20612 } 20613 20614 if (cf_hit >= 0) { 20615 index = cf_hit; /* Found entry index */ 20616 if (result != NULL) { 20617 sal_memcpy(result, &l2ent, sizeof(l2x_entry_t)); 20618 } 20619 } else { 20620 /* Entry not found */ 20621 LOG_INFO(BSL_LS_SOC_SOCMEM, 20622 (BSL_META_U(unit, 20623 "Lookup table[%s]: Not found\n"), 20624 SOC_MEM_NAME(unit, mem))); 20625 MEM_UNLOCK(unit, mem); 20626 return SOC_E_NOT_FOUND; 20627 } 20628 20629 if (index_ptr != NULL) { 20630 *index_ptr = index; 20631 } 20632 20633 index_valid = (index >= 0 && 20634 index <= soc_mem_index_max(unit, mem)); 20635 if (!index_valid) { 20636 LOG_ERROR(BSL_LS_SOC_SOCMEM, 20637 (BSL_META_U(unit, 20638 "soc_mem_generic_lookup: " 20639 "invalid index %d for memory %s\n"), 20640 index, SOC_MEM_NAME(unit, mem))); 20641 rv = SOC_E_INTERNAL; 20642 } 20643 20644 LOG_INFO(BSL_LS_SOC_SOCMEM, 20645 (BSL_META_U(unit, 20646 "Lookup table[%s]: bank=%d (index=%d)\n"), 20647 SOC_MEM_NAME(unit, mem), bank, index)); 20648 20649 MEM_UNLOCK(unit, mem); 20650 return rv; 20651 20652 } 20653 20654 /* 20655 * Function: 20656 * soc_mem_gh2_l2_sw_insert 20657 * Purpose: 20658 * Use software method to insert a L2 entry for GH2-B0 20659 * Parameters: 20660 * unit - StrataSwitch unit # 20661 * mem - L2 memory table 20662 * copyno - Which copy to search (if multiple copies) 20663 * banks - For dual hashing, which halves are selected (inverted) 20664 * entry - entry to insert 20665 * old_entry - old entry if existing entry was replaced 20666 * index_ptr - (OUT) If entry found gets the location of the entry. 20667 * If not found, and table is sorted, gets the 20668 * location of the insertion point. 20669 * CAN NO LONGER BE NULL. 20670 * Returns: 20671 * SOC_E_NONE - success 20672 * SOC_E_EXISTS - existing entry was replaced 20673 * SOC_E_FULL - full 20674 * Notes: 20675 * Uses software insertion without using an INSERT message over the 20676 * S-Channel. 20677 */ 20678 STATIC int 20679 soc_mem_gh2_l2_sw_insert( 20680 int unit, 20681 soc_mem_t mem, 20682 int copyno, 20683 int32 banks, 20684 void *entry, 20685 void *old_entry, 20686 int *index_ptr) 20687 { 20688 int rv; 20689 l2x_entry_t l2ent; 20690 bcm_vlan_t new_vid, old_vid; 20691 bcm_mac_t new_mac, old_mac; 20692 int cf_hit, cf_unhit; 20693 int bank, min_bank, max_bank; 20694 int bucket, slot, index; 20695 int entries_per_row, entries_per_bucket; 20696 int bucket_offset; 20697 uint32 valid = 0, fval = 0; 20698 int entry_dw = 0, index_valid; 20699 uint8 *vmap; 20700 uint32 *cache; 20701 20702 if (mem != L2Xm) { 20703 return SOC_E_INTERNAL; 20704 } 20705 20706 entry_dw = soc_mem_entry_words(unit, mem); 20707 20708 if (index_ptr) { 20709 *index_ptr = -1; 20710 } 20711 20712 if (banks == SOC_MEM_HASH_BANK0_ONLY) { 20713 min_bank = max_bank = 0; 20714 } else if (banks == SOC_MEM_HASH_BANK1_ONLY) { 20715 min_bank = max_bank = 1; 20716 } else { 20717 min_bank = 0; 20718 max_bank = 1; 20719 } 20720 20721 cf_hit = cf_unhit = -1; 20722 20723 entries_per_row = SOC_L2X_BUCKET_SIZE; 20724 entries_per_bucket = entries_per_row / 2; 20725 20726 MEM_LOCK(unit, mem); 20727 for (bank = min_bank; bank <= max_bank; bank++) { 20728 bucket_offset = bank * entries_per_bucket; 20729 bucket = soc_tr_l2x_bank_entry_hash(unit, bank, (uint32 *)entry); 20730 for (slot = 0; slot < entries_per_bucket; slot++) { 20731 index = (bucket * entries_per_row) + bucket_offset + slot; 20732 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &l2ent); 20733 if (SOC_FAILURE(rv)) { 20734 MEM_UNLOCK(unit, mem); 20735 return rv; 20736 } 20737 20738 valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf); 20739 if (!valid) { 20740 /* Found invalid entry - stop the search victim found */ 20741 cf_unhit = index; 20742 break; 20743 } 20744 20745 fval = soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf); 20746 if (fval != GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) { 20747 continue; 20748 } 20749 20750 /* Get existing L2 entry */ 20751 soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, old_mac); 20752 old_vid = soc_L2Xm_field32_get(unit, &l2ent, VLAN_IDf); 20753 20754 /* Get new insert L2 entry */ 20755 soc_L2Xm_mac_addr_get(unit, (l2x_entry_t *)entry, 20756 MAC_ADDRf, new_mac); 20757 new_vid = soc_L2Xm_field32_get(unit, (l2x_entry_t *)entry, 20758 VLAN_IDf); 20759 20760 if ((sal_memcmp(old_mac, new_mac, sizeof(bcm_mac_t)) == 0) && 20761 (new_vid == old_vid)) { 20762 /* Found existing entry */ 20763 cf_hit = index; 20764 break; 20765 } 20766 } 20767 20768 if ((cf_unhit != -1) || (cf_hit != -1)) { 20769 break; 20770 } 20771 } 20772 20773 if (cf_unhit >= 0) { 20774 index = cf_unhit; /* take first hit invalid entry */ 20775 } else if (cf_hit >= 0) { 20776 index = cf_hit; /* or first hit with the same entry */ 20777 } else { 20778 /* no slot to insert */ 20779 LOG_INFO(BSL_LS_SOC_SOCMEM, 20780 (BSL_META_U(unit, 20781 "Insert table[%s]: hash bucket full\n"), 20782 SOC_MEM_NAME(unit, mem))); 20783 MEM_UNLOCK(unit, mem); 20784 return SOC_E_FULL; 20785 } 20786 20787 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry); 20788 if (SOC_FAILURE(rv)) { 20789 MEM_UNLOCK(unit, mem); 20790 return rv; 20791 } 20792 20793 if (index_ptr != NULL) { 20794 *index_ptr = index; 20795 } 20796 20797 if (cf_hit >= 0) { 20798 if (old_entry != NULL) { 20799 sal_memcpy(old_entry, &l2ent, sizeof(l2x_entry_t)); 20800 } 20801 rv = SOC_E_EXISTS; 20802 } 20803 20804 SOP_MEM_STATE(unit, mem).count[copyno]++; 20805 20806 /* Update cache if active */ 20807 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 20808 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 20809 index_valid = (index >= 0 && 20810 index <= soc_mem_index_max(unit, mem)); 20811 if (!index_valid) { 20812 LOG_ERROR(BSL_LS_SOC_SOCMEM, 20813 (BSL_META_U(unit, 20814 "soc_mem_generic_insert: " 20815 "invalid index %d for memory %s\n"), 20816 index, SOC_MEM_NAME(unit, mem))); 20817 rv = SOC_E_INTERNAL; 20818 } else if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 20819 /* If an invalid or non-static entry is being written then clear the cache */ 20820 if ((soc_L2Xm_field32_get(unit, entry, VALIDf)) && 20821 (soc_L2Xm_field32_get(unit, entry, STATIC_BITf))) { 20822 sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4); 20823 CACHE_VMAP_SET(vmap, index); 20824 } else { 20825 CACHE_VMAP_CLR(vmap, index); 20826 } 20827 } 20828 20829 MEM_UNLOCK(unit, mem); 20830 return rv; 20831 20832 } 20833 20834 /* 20835 * Function: 20836 * soc_mem_gh2_l2_sw_delete 20837 * Purpose: 20838 * Use software method to delete a L2 entry for GH2-B0 20839 * Parameters: 20840 * unit - StrataSwitch unit # 20841 * mem - L2 memory table 20842 * copyno - Which copy to search (if multiple copies) 20843 * banks - For dual hashing, which halves are selected (inverted) 20844 * entry - entry to delete 20845 * old_entry - old entry if existing entry was found 20846 * index_ptr - (OUT) If entry found gets the location of the entry. 20847 * Returns: 20848 * SOC_E_NONE - success 20849 * SOC_E_NOT_FOUND - fail 20850 * Notes: 20851 * Uses software deletion without using an DELETE message over the 20852 * S-Channel. 20853 */ 20854 STATIC int 20855 soc_mem_gh2_l2_sw_delete( 20856 int unit, 20857 soc_mem_t mem, 20858 int copyno, 20859 int32 banks, 20860 void *entry, 20861 void *old_entry, 20862 int *index_ptr) 20863 { 20864 int rv; 20865 l2x_entry_t l2ent, null_l2ent; 20866 bcm_vlan_t new_vid, old_vid; 20867 bcm_mac_t new_mac, old_mac; 20868 int cf_hit; 20869 int bank, min_bank, max_bank; 20870 int bucket, slot, index; 20871 int entries_per_row, entries_per_bucket; 20872 int bucket_offset; 20873 uint32 valid = 0, fval = 0; 20874 int index_valid; 20875 uint8 *vmap; 20876 uint32 *cache; 20877 20878 if (mem != L2Xm) { 20879 return SOC_E_INTERNAL; 20880 } 20881 20882 if (index_ptr) { 20883 *index_ptr = -1; 20884 } 20885 20886 if (banks == SOC_MEM_HASH_BANK0_ONLY) { 20887 min_bank = max_bank = 0; 20888 } else if (banks == SOC_MEM_HASH_BANK1_ONLY) { 20889 min_bank = max_bank = 1; 20890 } else { 20891 min_bank = 0; 20892 max_bank = 1; 20893 } 20894 20895 cf_hit = -1; 20896 20897 entries_per_row = SOC_L2X_BUCKET_SIZE; 20898 entries_per_bucket = entries_per_row / 2; 20899 20900 MEM_LOCK(unit, mem); 20901 for (bank = min_bank; bank <= max_bank; bank++) { 20902 bucket_offset = bank * entries_per_bucket; 20903 bucket = soc_tr_l2x_bank_entry_hash(unit, bank, (uint32 *)entry); 20904 for (slot = 0; slot < entries_per_bucket; slot++) { 20905 index = (bucket * entries_per_row) + bucket_offset + slot; 20906 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &l2ent); 20907 if (SOC_FAILURE(rv)) { 20908 MEM_UNLOCK(unit, mem); 20909 return rv; 20910 } 20911 20912 valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf); 20913 if (!valid) { 20914 continue; 20915 } 20916 20917 fval = soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf); 20918 if (fval != GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) { 20919 continue; 20920 } 20921 20922 /* Get existing L2 entry */ 20923 soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, old_mac); 20924 old_vid = soc_L2Xm_field32_get(unit, &l2ent, VLAN_IDf); 20925 20926 /* Get deleted L2 entry */ 20927 soc_L2Xm_mac_addr_get(unit, (l2x_entry_t *)entry, 20928 MAC_ADDRf, new_mac); 20929 new_vid = soc_L2Xm_field32_get(unit, (l2x_entry_t *)entry, 20930 VLAN_IDf); 20931 20932 if ((sal_memcmp(old_mac, new_mac, sizeof(bcm_mac_t)) == 0) && 20933 (new_vid == old_vid)) { 20934 /* Found entry */ 20935 cf_hit = index; 20936 break; 20937 } 20938 } 20939 20940 if (cf_hit != -1) { 20941 break; 20942 } 20943 } 20944 20945 if (cf_hit >= 0) { 20946 index = cf_hit; /* Found entry index */ 20947 } else { 20948 /* Entry not found */ 20949 LOG_INFO(BSL_LS_SOC_SOCMEM, 20950 (BSL_META_U(unit, 20951 "Delete table[%s]: Not found\n"), 20952 SOC_MEM_NAME(unit, mem))); 20953 MEM_UNLOCK(unit, mem); 20954 return SOC_E_NOT_FOUND; 20955 } 20956 20957 sal_memcpy(&null_l2ent, soc_mem_entry_null(unit, mem), 20958 sizeof(l2x_entry_t)); 20959 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, (uint32 *)&null_l2ent); 20960 if (SOC_FAILURE(rv)) { 20961 MEM_UNLOCK(unit, mem); 20962 return rv; 20963 } 20964 20965 if (index_ptr != NULL) { 20966 *index_ptr = index; 20967 } 20968 20969 if (cf_hit >= 0) { 20970 if (old_entry != NULL) { 20971 sal_memcpy(old_entry, &l2ent, sizeof(l2x_entry_t)); 20972 } 20973 rv = SOC_E_NONE; 20974 } 20975 20976 SOP_MEM_STATE(unit, mem).count[copyno]--; 20977 20978 if (!SOC_WARM_BOOT(unit)) { 20979 /* Update cache if active */ 20980 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 20981 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 20982 index_valid = (index >= 0 && 20983 index <= soc_mem_index_max(unit, mem)); 20984 if (!index_valid) { 20985 LOG_ERROR(BSL_LS_SOC_SOCMEM, 20986 (BSL_META_U(unit, 20987 "soc_mem_generic_delete: " 20988 "invalid index %d for memory %s\n"), 20989 index, SOC_MEM_NAME(unit, mem))); 20990 MEM_UNLOCK(unit, mem); 20991 return SOC_E_INTERNAL; 20992 } 20993 20994 if (index_valid && cache != NULL && CACHE_VMAP_TST(vmap, index) && 20995 !SOC_MEM_TEST_SKIP_CACHE(unit)) { 20996 CACHE_VMAP_CLR(vmap, index); 20997 } 20998 } 20999 21000 MEM_UNLOCK(unit, mem); 21001 return rv; 21002 21003 } 21004 #endif /* BCM_GREYHOUND2_SUPPORT */ 21005 21006 /* 21007 * Function: 21008 * soc_mem_generic_insert 21009 * Purpose: 21010 * Insert an entry 21011 * Parameters: 21012 * unit - StrataSwitch unit # 21013 * banks - For dual hashing, which halves are selected (inverted) 21014 * Note: used to create a bitmap for ISM mems. (All banks: -1) 21015 * entry - entry to insert 21016 * old_entry - old entry if existing entry was replaced 21017 * Returns: 21018 * SOC_E_NONE - success 21019 * SOC_E_EXISTS - existing entry was replaced 21020 * SOC_E_FULL - full 21021 * SOC_E_BUSY - modfifo full 21022 * Notes: 21023 * Uses hardware insertion; sends an INSERT message over the 21024 * S-Channel. 21025 */ 21026 21027 int 21028 soc_mem_generic_insert(int unit, soc_mem_t mem, int copyno, int32 banks, 21029 void *entry, void *old_entry, int *index_ptr) 21030 { 21031 schan_msg_t schan_msg; 21032 #ifdef BCM_ESW_SUPPORT 21033 schan_msg_t schan_msg_cpy; 21034 #endif /* BCM_ESW_SUPPORT */ 21035 int rv, index_valid; 21036 int entry_dw = 0; 21037 uint8 at, *vmap; 21038 int type, err_info, index, allow_intr=0; 21039 uint32 *data, *cache; 21040 int src_blk, dst_blk, acc_type, data_byte_len; 21041 int opcode, nack; 21042 uint32 bank_ignore_mask; 21043 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 21044 int rv1 = SOC_E_NONE; 21045 #endif 21046 21047 #ifdef BCM_ESW_SUPPORT 21048 uint8 insert_retry_attempt = 0; 21049 #endif 21050 #ifdef BCM_TRX_SUPPORT 21051 uint8 insert_retry = 0; 21052 #endif 21053 21054 #ifdef BCM_TRIDENT2PLUS_SUPPORT 21055 uint8 insert_full_retry_attempt = 0; 21056 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 21057 21058 #if defined(BCM_TRIUMPH3_SUPPORT) 21059 int ins_disable = FALSE, try_one_time = 1; 21060 uint32 l2_insert = 0; 21061 #endif 21062 21063 #if defined(BCM_HURRICANE3_SUPPORT) 21064 uint32 overflow_index = 0; 21065 #endif /* BCM_HURRICANE3_SUPPORT */ 21066 #if defined(BCM_GREYHOUND2_SUPPORT) 21067 uint32 key_type = 0; 21068 #endif /* BCM_GREYHOUND2_SUPPORT */ 21069 21070 #ifdef BCM_TOMAHAWK3_SUPPORT 21071 int j; 21072 uint16 dev_id; 21073 uint8 rev_id; 21074 schan_msg_t schan_msg_dupl; 21075 #endif 21076 21077 _SOC_MEM_REPLACE_MEM(unit, mem); 21078 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 21079 assert(SOC_MEM_IS_VALID(unit, mem)); 21080 assert(soc_attached(unit)); 21081 #ifdef BCM_TOMAHAWK3_SUPPORT 21082 soc_cm_get_id(unit, &dev_id, &rev_id); 21083 #endif 21084 21085 if (copyno == MEM_BLOCK_ANY) { 21086 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 21087 } 21088 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 21089 LOG_WARN(BSL_LS_SOC_SOCMEM, 21090 (BSL_META_U(unit, 21091 "soc_mem_generic_insert: invalid block %d for memory %s\n"), 21092 copyno, SOC_MEM_NAME(unit, mem))); 21093 return SOC_E_PARAM; 21094 } 21095 21096 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 21097 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 21098 "Insert table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem), 21099 banks)); 21100 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 21101 soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON); 21102 } 21103 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 21104 "\n"))); 21105 } 21106 21107 entry_dw = soc_mem_entry_words(unit, mem); 21108 21109 21110 #if defined(BCM_TRIDENT2_SUPPORT) 21111 if (soc_feature(unit, soc_feature_shared_hash_ins) && 21112 !SOC_IS_TOMAHAWKX(unit) && !SOC_IS_TRIDENT3X(unit) && 21113 (mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm)) { 21114 int ok = 0, index, bix; 21115 int num_banks, bank_ids[7]; 21116 int bank_indexes[7] = {-1, -1, -1, -1, -1, -1, -1}; 21117 21118 /* Retreive applicable bank map and first try replace on each */ 21119 21120 { 21121 SOC_IF_ERROR_RETURN 21122 (soc_trident2_hash_bank_count_get(unit, mem, &num_banks)); 21123 } 21124 21125 if (banks != SOC_MEM_HASH_BANK_ALL) { 21126 num_banks = 1; 21127 } 21128 MEM_LOCK(unit, mem); 21129 for (bix = 0; bix < num_banks; bix++) { 21130 int32 bid; 21131 21132 { 21133 rv1 = (soc_trident2_hash_bank_number_get(unit, mem, bix, 21134 &bank_ids[bix])); 21135 } 21136 if (SOC_FAILURE(rv1)) { 21137 MEM_UNLOCK(unit, mem); 21138 return rv1; 21139 } 21140 bid = 1 << bank_ids[bix]; 21141 if (banks != SOC_MEM_HASH_BANK_ALL) { 21142 bid = banks; 21143 } 21144 rv1 = soc_mem_generic_lookup(unit, mem, copyno, bid, 21145 entry, NULL, &index); 21146 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 21147 (BSL_META_U(unit, 21148 "Sh-Ins-Lukp: bank[%d] " 21149 "rv[%d] index[%d]\n"), 21150 bid, rv1, index)); 21151 if (SOC_FAILURE(rv1)) { 21152 if (rv1 == SOC_E_NOT_FOUND) { 21153 /* Entry not found. Save index and move on to the next bank */ 21154 bank_indexes[bix] = index; 21155 continue; 21156 } else { 21157 MEM_UNLOCK(unit, mem); 21158 return rv1; 21159 } 21160 } 21161 /* Replace entry */ 21162 if (old_entry) { 21163 rv1 = soc_mem_read(unit, mem, copyno, index, old_entry); 21164 if (SOC_FAILURE(rv1)) { 21165 MEM_UNLOCK(unit, mem); 21166 return rv1; 21167 } 21168 } 21169 rv1 = soc_mem_write(unit, mem, copyno, index, entry); 21170 if (SOC_FAILURE(rv1)) { 21171 MEM_UNLOCK(unit, mem); 21172 return rv1; 21173 } 21174 if (index_ptr) { 21175 *index_ptr = index; 21176 } 21177 ok = 1; 21178 /* rv = SOC_E_EXISTS; Overwritten later. Coverity complains */ 21179 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 21180 (BSL_META_U(unit, 21181 "Sh-Ins-Lukp: " 21182 "replace at index:%d\n"), index)); 21183 break; 21184 } 21185 if (!ok) { 21186 /* If replace did not happen then try a fresh insert */ 21187 for (bix = 0; bix < num_banks; bix++) { 21188 uint32 bkt[SOC_MAX_MEM_WORDS]; 21189 21190 index = bank_indexes[bix]; 21191 if (index < 0) { 21192 continue; 21193 } 21194 rv1 = soc_mem_read(unit, L3_ENTRY_IPV6_MULTICASTm, copyno, 21195 index, bkt); 21196 if (SOC_FAILURE(rv1)) { 21197 MEM_UNLOCK(unit, mem); 21198 return rv1; 21199 } else { 21200 uint32 v0, v1; 21201 21202 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt, 21203 VALID_0f, &v0); 21204 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt, 21205 VALID_1f, &v1); 21206 if ((v0 == 0) && (v1 == 0)) { 21207 index *= 2; 21208 rv1 = soc_mem_write(unit, mem, copyno, index, entry); 21209 if (SOC_FAILURE(rv1)) { 21210 MEM_UNLOCK(unit, mem); 21211 return rv1; 21212 } 21213 if (index_ptr) { 21214 *index_ptr = index; 21215 } 21216 ok = 1; rv = SOC_E_NONE; 21217 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 21218 (BSL_META_U(unit, 21219 "Sh-Ins-Lukp: " 21220 "insert at index:%d\n"), index)); 21221 break; 21222 } else { 21223 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt, 21224 VALID_2f, &v0); 21225 soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt, 21226 VALID_3f, &v1); 21227 if ((v0 == 0) && (v1 == 0)) { 21228 index = index*2 + 1; 21229 rv1 = soc_mem_write(unit, mem, copyno, index, entry); 21230 if (SOC_FAILURE(rv1)) { 21231 MEM_UNLOCK(unit, mem); 21232 return rv1; 21233 } 21234 if (index_ptr) { 21235 *index_ptr = index; 21236 } 21237 ok = 1; rv = SOC_E_NONE; 21238 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 21239 (BSL_META_U(unit, 21240 "Sh-Ins-Lukp: " 21241 "insert at index:%d\n"), index)); 21242 break; 21243 } 21244 } 21245 } 21246 } 21247 } 21248 if (!ok) { 21249 MEM_UNLOCK(unit, mem); 21250 return SOC_E_FULL; 21251 } 21252 21253 SOP_MEM_STATE(unit, mem).count[copyno]++; 21254 21255 /* Update cache if active */ 21256 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 21257 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 21258 index_valid = (index >= 0 && 21259 index <= soc_mem_index_max(unit, mem)); 21260 if (!index_valid) { 21261 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21262 (BSL_META_U(unit, 21263 "soc_mem_generic_insert: " 21264 "invalid index %d for memory %s\n"), 21265 index, SOC_MEM_NAME(unit, mem))); 21266 rv = SOC_E_INTERNAL; 21267 } else if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 21268 sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4); 21269 CACHE_VMAP_SET(vmap, index); 21270 } 21271 MEM_UNLOCK(unit, mem); 21272 return SOC_E_NONE; 21273 } 21274 #endif /* BCM_TRIDENT2_SUPPORT */ 21275 21276 #if defined(BCM_GREYHOUND2_SUPPORT) 21277 if (soc_feature(unit, soc_feature_vxlan_lite_riot) && (mem == L2Xm)) { 21278 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 21279 /* Use SW to insert a L2 entry when key_type is VFI_MULTICAST */ 21280 if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) { 21281 return soc_mem_gh2_l2_sw_insert(unit, mem, copyno, banks, 21282 entry, old_entry, index_ptr); 21283 } 21284 } 21285 #endif /* BCM_GREYHOUND2_SUPPORT */ 21286 21287 MEM_LOCK(unit, mem); 21288 #if defined(BCM_TRIUMPH3_SUPPORT) 21289 if (soc_feature(unit, soc_feature_esm_correction) && 21290 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21291 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21292 SOC_ESM_LOCK(unit); 21293 } 21294 #endif 21295 schan_msg_clear(&schan_msg); 21296 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 21297 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 21298 dst_blk = SOC_BLOCK2SCH(unit, copyno); 21299 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 21300 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 21301 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 21302 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 21303 (mem == L3_ENTRY_IPV6_MULTICASTm) 21304 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 21305 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 21306 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 21307 #endif 21308 #if defined(BCM_TOMAHAWK3_SUPPORT) 21309 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 21310 || (mem == L3_TUNNEL_QUADm) 21311 #endif 21312 #if defined(BCM_TRIDENT3_SUPPORT) 21313 || (mem == VLAN_XLATE_1_SINGLEm) 21314 || (mem == VLAN_XLATE_1_DOUBLEm) 21315 || (mem == EGR_VLAN_XLATE_1_SINGLEm) 21316 || (mem == EGR_VLAN_XLATE_1_DOUBLEm) 21317 || (mem == VLAN_XLATE_2_SINGLEm) 21318 || (mem == VLAN_XLATE_2_DOUBLEm) 21319 || (mem == EGR_VLAN_XLATE_2_SINGLEm) 21320 || (mem == EGR_VLAN_XLATE_2_DOUBLEm) 21321 #endif 21322 #if defined(BCM_TOMAHAWK_SUPPORT) 21323 || _SOC_MEM_CHK_FPEM_MEM(mem) 21324 #endif 21325 ))) { 21326 /* don't set bank id in cos */ 21327 bank_ignore_mask = 0; 21328 } else { 21329 bank_ignore_mask = banks & 0x3; 21330 } 21331 data_byte_len = entry_dw * 4; 21332 21333 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 21334 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 21335 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 21336 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 21337 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 21338 (mem == L3_ENTRY_IPV6_MULTICASTm) 21339 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 21340 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 21341 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 21342 #endif 21343 #if defined(BCM_TOMAHAWK3_SUPPORT) 21344 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 21345 || (mem == L3_TUNNEL_QUADm) 21346 #endif 21347 #if defined(BCM_TRIDENT3_SUPPORT) 21348 || (mem == VLAN_XLATE_1_SINGLEm) 21349 || (mem == VLAN_XLATE_1_DOUBLEm) 21350 || (mem == EGR_VLAN_XLATE_1_SINGLEm) 21351 || (mem == EGR_VLAN_XLATE_1_DOUBLEm) 21352 || (mem == VLAN_XLATE_2_SINGLEm) 21353 || (mem == VLAN_XLATE_2_DOUBLEm) 21354 || (mem == EGR_VLAN_XLATE_2_SINGLEm) 21355 || (mem == EGR_VLAN_XLATE_2_DOUBLEm) 21356 || (mem == MPLS_ENTRYm) 21357 #endif 21358 #if defined(BCM_TOMAHAWK_SUPPORT) 21359 || _SOC_MEM_CHK_FPEM_MEM(mem) 21360 #endif 21361 ))) { 21362 /* set bank ignore mask in lower 20 bits */ 21363 if (banks && banks != SOC_MEM_HASH_BANK_ALL) { 21364 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 21365 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED); 21366 } else { 21367 #ifdef BCM_TRIUMPH3_SUPPORT 21368 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks); 21369 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM); 21370 #endif /* BCM_TRIUMPH3_SUPPORT */ 21371 } 21372 } 21373 } 21374 #ifdef BCM_TOMAHAWK3_SUPPORT 21375 if (acc_type == 16 && (dev_id == BCM56983_DEVICE_ID)) { 21376 acc_type = 0; 21377 } else if ((acc_type == 14 || acc_type == 9) && (dev_id == BCM56983_DEVICE_ID)) { 21378 sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg)); 21379 21380 21381 /* 21382 * Execute S-Channel "table insert" command packet consisting of 21383 * (header word + address word + entry_dw), and read back 21384 * (header word + response word + entry_dw) data words. 21385 */ 21386 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 21387 LOG_WARN(BSL_LS_SOC_SOCMEM, 21388 (BSL_META_U(unit, 21389 "soc_mem_generic_insert: assert will fail for memory %s\n"), 21390 SOC_MEM_NAME(unit, mem))); 21391 } 21392 for (j = 0; j < 4 ; j++) { 21393 switch(j) { 21394 case 0 : acc_type = 0; 21395 break; 21396 case 1 : acc_type = 1; 21397 break; 21398 case 2 : acc_type = 6; 21399 break; 21400 case 3 : acc_type = 7; 21401 break; 21402 } 21403 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg)); 21404 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG, 21405 dst_blk, src_blk, acc_type, data_byte_len, 0, 21406 bank_ignore_mask); 21407 21408 /* Fill in packet data */ 21409 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 21410 21411 21412 #ifdef BCM_ESW_SUPPORT 21413 if (soc_feature(unit, soc_feature_shared_hash_mem) || 21414 soc_feature(unit, soc_feature_dual_hash) || 21415 soc_feature(unit, soc_feature_ism_memory)) { 21416 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg)); 21417 } 21418 #endif /* BCM_ESW_SUPPORT */ 21419 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 21420 21421 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 21422 NULL, NULL, &nack); 21423 if (opcode != TABLE_INSERT_DONE_MSG) { 21424 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21425 (BSL_META_U(unit, 21426 "soc_mem_generic_insert: " 21427 "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n"))); 21428 soc_schan_dump(unit, &schan_msg, 1); 21429 #if defined(BCM_TRIUMPH3_SUPPORT) 21430 if (soc_feature(unit, soc_feature_esm_correction) && 21431 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21432 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21433 SOC_ESM_UNLOCK(unit); 21434 } 21435 #endif 21436 #if defined(BCM_TRIUMPH3_SUPPORT) 21437 if (ins_disable) { 21438 _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert); 21439 ins_disable = FALSE; 21440 } 21441 #endif 21442 MEM_UNLOCK(unit, mem); 21443 return SOC_E_INTERNAL; 21444 } 21445 21446 21447 } 21448 goto resume; 21449 } else if (acc_type == 15 && (dev_id == BCM56983_DEVICE_ID)) { 21450 sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg)); 21451 /* 21452 * Execute S-Channel "table insert" command packet consisting of 21453 * (header word + address word + entry_dw), and read back 21454 * (header word + response word + entry_dw) data words. 21455 */ 21456 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 21457 LOG_WARN(BSL_LS_SOC_SOCMEM, 21458 (BSL_META_U(unit, 21459 "soc_mem_generic_insert: assert will fail for memory %s\n"), 21460 SOC_MEM_NAME(unit, mem))); 21461 } 21462 21463 for (j = 0; j < 2 ; j++) { 21464 switch(j) { 21465 case 0 : acc_type = 0; 21466 break; 21467 case 1 : acc_type = 6; 21468 break; 21469 } 21470 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg)); 21471 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG, 21472 dst_blk, src_blk, acc_type, data_byte_len, 0, 21473 bank_ignore_mask); 21474 21475 /* Fill in packet data */ 21476 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 21477 21478 #ifdef BCM_ESW_SUPPORT 21479 if (soc_feature(unit, soc_feature_shared_hash_mem) || 21480 soc_feature(unit, soc_feature_dual_hash) || 21481 soc_feature(unit, soc_feature_ism_memory)) { 21482 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg)); 21483 } 21484 #endif /* BCM_ESW_SUPPORT */ 21485 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 21486 21487 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 21488 NULL, NULL, &nack); 21489 if (opcode != TABLE_INSERT_DONE_MSG) { 21490 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21491 (BSL_META_U(unit, 21492 "soc_mem_generic_insert: " 21493 "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n"))); 21494 soc_schan_dump(unit, &schan_msg, 1); 21495 #if defined(BCM_TRIUMPH3_SUPPORT) 21496 if (soc_feature(unit, soc_feature_esm_correction) && 21497 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21498 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21499 SOC_ESM_UNLOCK(unit); 21500 } 21501 #endif 21502 #if defined(BCM_TRIUMPH3_SUPPORT) 21503 if (ins_disable) { 21504 _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert); 21505 ins_disable = FALSE; 21506 } 21507 #endif 21508 MEM_UNLOCK(unit, mem); 21509 return SOC_E_INTERNAL; 21510 } 21511 21512 21513 } 21514 goto resume; 21515 } 21516 #endif 21517 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG, 21518 dst_blk, src_blk, acc_type, data_byte_len, 0, 21519 bank_ignore_mask); 21520 21521 /* Fill in packet data */ 21522 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 21523 21524 if (SOC_IS_SAND(unit)) { 21525 allow_intr = 1; 21526 } 21527 21528 /* 21529 * Execute S-Channel "table insert" command packet consisting of 21530 * (header word + address word + entry_dw), and read back 21531 * (header word + response word + entry_dw) data words. 21532 */ 21533 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 21534 LOG_WARN(BSL_LS_SOC_SOCMEM, 21535 (BSL_META_U(unit, 21536 "soc_mem_generic_insert: assert will fail for memory %s\n"), 21537 SOC_MEM_NAME(unit, mem))); 21538 } 21539 #ifdef BCM_ESW_SUPPORT 21540 if (soc_feature(unit, soc_feature_shared_hash_mem) || 21541 soc_feature(unit, soc_feature_dual_hash) || 21542 soc_feature(unit, soc_feature_ism_memory)) { 21543 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg)); 21544 } 21545 _retry_op: 21546 #endif /* BCM_ESW_SUPPORT */ 21547 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 21548 21549 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 21550 NULL, NULL, &nack); 21551 if (opcode != TABLE_INSERT_DONE_MSG) { 21552 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21553 (BSL_META_U(unit, 21554 "soc_mem_generic_insert: " 21555 "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n"))); 21556 soc_schan_dump(unit, &schan_msg, 1); 21557 #if defined(BCM_TRIUMPH3_SUPPORT) 21558 if (soc_feature(unit, soc_feature_esm_correction) && 21559 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21560 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21561 SOC_ESM_UNLOCK(unit); 21562 } 21563 #endif 21564 #if defined(BCM_TRIUMPH3_SUPPORT) 21565 if (ins_disable) { 21566 _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert); 21567 ins_disable = FALSE; 21568 } 21569 #endif 21570 MEM_UNLOCK(unit, mem); 21571 return SOC_E_INTERNAL; 21572 } 21573 21574 #ifdef BCM_TOMAHAWK3_SUPPORT 21575 resume: 21576 #endif 21577 if (soc_feature(unit, soc_feature_new_sbus_format) && 21578 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 21579 type = schan_msg.genresp_v2.response.type; 21580 err_info = schan_msg.genresp_v2.response.err_info; 21581 index = schan_msg.genresp_v2.response.index; 21582 data = schan_msg.genresp_v2.data; 21583 } else { 21584 type = schan_msg.genresp.response.type; 21585 err_info = schan_msg.genresp.response.err_info; 21586 index = schan_msg.genresp.response.index; 21587 data = schan_msg.genresp.data; 21588 } 21589 21590 #if defined(BCM_TRIUMPH3_SUPPORT) 21591 if (ins_disable) { 21592 _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert); 21593 ins_disable = FALSE; 21594 if (type == SCHAN_GEN_RESP_TYPE_INSERTED) { 21595 if (SOC_IS_TRIUMPH3(unit)) { 21596 soc_l2_entry_callback(unit, 0, mem, NULL, entry); 21597 } 21598 } 21599 } 21600 #endif 21601 21602 if ((nack != 0) || (rv == SOC_E_FAIL)) { 21603 if (index_ptr) { 21604 *index_ptr = -1; 21605 } 21606 #if defined(BCM_TRIUMPH3_SUPPORT) 21607 if ((SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT(unit) || 21608 SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) && 21609 ((type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL) || 21610 (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) { 21611 /*This is a Software Workaround for L2_MOD_FIFO. Sometimes an entry may be 21612 unable to be inserted into L2 table when L2_MOD_FIFO is too busy. In this situation 21613 the L2_INSERT field in L2_MOD_FIFO_ENABLE will be disabled and retry the insert 21614 operation. After the insertion the L2_INSERT field will be enabled.*/ 21615 if (SOC_IS_TRIUMPH3(unit) && (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL)) { 21616 l2_insert = _soc_l2mode_fifo_enable_insert_field_get(unit); 21617 _soc_l2mode_fifo_enable_insert_field_set(unit, 0); 21618 ins_disable = TRUE; 21619 if (l2_insert && try_one_time) { 21620 sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg)); 21621 LOG_INFO(BSL_LS_SOC_SOCMEM, 21622 (BSL_META_U(unit, 21623 "L2_MOD_FIFO may be full," 21624 "error type [%d], will insert again!\n"), 21625 type)); 21626 try_one_time--; 21627 goto _retry_op; 21628 } else { 21629 _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert); 21630 } 21631 } else if ((SOC_IS_TRIDENT(unit) && 21632 (type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL)) || 21633 ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) && 21634 (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) { 21635 LOG_INFO(BSL_LS_SOC_SOCMEM, 21636 (BSL_META_U(unit, 21637 "L2_MOD_FIFO is full, error type [%d]"), 21638 type)); 21639 rv = SOC_E_FULL; 21640 MEM_UNLOCK(unit, mem); 21641 return rv; 21642 } 21643 } 21644 #endif 21645 #if defined(BCM_ISM_SUPPORT) 21646 if ((type == SCHAN_GEN_RESP_MAC_LIMIT_THRESHOLD) || 21647 (type == SCHAN_GEN_RESP_MAC_LIMIT_DELETE) || 21648 (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL)) { 21649 LOG_INFO(BSL_LS_SOC_SOCMEM, 21650 (BSL_META_U(unit, 21651 "Insert table[%s]: hash bucket full\n"), 21652 SOC_MEM_NAME(unit, mem))); 21653 21654 rv = SOC_E_FULL; 21655 } else { 21656 #endif 21657 #ifdef BCM_TRIDENT2PLUS_SUPPORT 21658 if (soc_feature(unit, soc_feature_td2p_a0_sw_war) && 21659 ((mem == EGR_VLAN_XLATEm) || (mem == VLAN_XLATEm)) && 21660 (type == SCHAN_GEN_RESP_TYPE_FULL)) { 21661 if (insert_full_retry_attempt < HASH_MEM_OP_RETRY_COUNT) { 21662 insert_full_retry_attempt++; 21663 sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg)); 21664 goto _retry_op; 21665 } 21666 } 21667 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 21668 if ((type == SCHAN_GEN_RESP_TYPE_FULL) || 21669 (type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL) || 21670 (type == SCHAN_GEN_RESP_TYPE_MAC_LIMIT_THRE) || 21671 (type == SCHAN_GEN_RESP_TYPE_MAC_LIMIT_DEL)) { 21672 LOG_INFO(BSL_LS_SOC_SOCMEM, 21673 (BSL_META_U(unit, 21674 "Insert table[%s]: hash bucket full\n"), 21675 SOC_MEM_NAME(unit, mem))); 21676 rv = SOC_E_FULL; 21677 } else if (type == SCHAN_GEN_RESP_TYPE_ERROR) { 21678 #ifdef BCM_ESW_SUPPORT 21679 LOG_VERBOSE(BSL_LS_SOC_SER,(BSL_META_U(unit, 21680 " soc_mem_generic_insert: rv=%d, nack=%d, type=%d, index=%d\n"), 21681 rv, nack, type, index)); 21682 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 21683 int i, rv1 = SOC_E_NONE, index1 = index, ir1 = 1, 21684 pipe1 = SOC_PIPE_ANY; 21685 soc_mem_t mem1 = mem; 21686 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 21687 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit)) { 21688 (void)_soc_inline_ser_mem_remap(unit, &mem1, &pipe1, 21689 &ir1); 21690 index1 = (index / ir1) * ir1; /* base_index for entry */ 21691 } 21692 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_APACHE_SUPPORT */ 21693 for (i = 0; i < ir1; i++) { 21694 rv1 = soc_ser_sram_correction(unit, pipe1, 21695 schan_msg.gencmd.header.v2.dst_blk, 21696 schan_msg.gencmd.address, mem1, 21697 copyno, index1 + i, NULL); 21698 if (SOC_FAILURE(rv1)) { 21699 break; 21700 } 21701 } 21702 if (rv1 == SOC_E_NONE) { 21703 if (insert_retry_attempt < HASH_MEM_OP_RETRY_COUNT) { 21704 insert_retry_attempt++; 21705 sal_memcpy(&schan_msg, &schan_msg_cpy, 21706 sizeof(schan_msg)); 21707 goto _retry_op; 21708 } 21709 } 21710 } 21711 #endif /* BCM_ESW_SUPPORT */ 21712 if (err_info == SCHAN_GEN_RESP_ERROR_BUSY) { 21713 LOG_INFO(BSL_LS_SOC_SOCMEM, 21714 (BSL_META_U(unit, 21715 "Insert table[%s]: Modfifo full\n"), 21716 SOC_MEM_NAME(unit, mem))); 21717 rv = SOC_E_BUSY; 21718 } else if (err_info == SCHAN_GEN_RESP_ERROR_PARITY) { 21719 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21720 (BSL_META_U(unit, 21721 "Insert table[%s]: Parity Error Index %d\n"), 21722 SOC_MEM_NAME(unit, mem), index)); 21723 rv = SOC_E_INTERNAL; 21724 } 21725 #if defined(BCM_TRX_SUPPORT) 21726 /* Hash table response with SCHAN_GEN_RESP_TYPE_ERROR */ 21727 if (SOC_IS_TRX(unit) && (soc_mem_is_hashed(unit, mem))) { 21728 /* Try to recover */ 21729 rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg, 21730 banks, entry); 21731 if (rv == SOC_E_NONE) { 21732 if (insert_retry < HASH_MEM_OP_RETRY_COUNT) { 21733 insert_retry++; 21734 sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg)); 21735 LOG_WARN(BSL_LS_SOC_SOCMEM, 21736 (BSL_META_U(unit, 21737 "unit %d: Retry Hash insert operation..\n"), 21738 unit)); 21739 goto _retry_op; 21740 } 21741 21742 } else { 21743 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21744 (BSL_META_U(unit, 21745 "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"), 21746 unit, SOC_MEM_NAME(unit, mem), rv)); 21747 } 21748 } 21749 #endif 21750 } else { 21751 #if defined(BCM_TRIDENT2_SUPPORT) 21752 if (SOC_IS_TD2_TT2(unit) && soc_mem_is_hashed(unit, mem) && 21753 (type == SCHAN_GEN_RESP_TYPE_INSERTED || 21754 type == SCHAN_GEN_RESP_TYPE_REPLACED)) { 21755 rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg, 21756 banks, entry); 21757 if (rv == SOC_E_NONE) { 21758 if (insert_retry_attempt < HASH_MEM_OP_RETRY_COUNT) { 21759 insert_retry_attempt++; 21760 sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg)); 21761 LOG_WARN(BSL_LS_SOC_SOCMEM, 21762 (BSL_META_U(unit, 21763 "unit %d: Retry Hash insert operation..\n"), 21764 unit)); 21765 goto _retry_op; 21766 } 21767 } else { 21768 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21769 (BSL_META_U(unit, 21770 "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"), 21771 unit, SOC_MEM_NAME(unit, mem), rv)); 21772 } 21773 } 21774 #endif 21775 rv = SOC_E_FAIL; 21776 } 21777 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(BCM_ISM_SUPPORT) 21778 } 21779 #endif 21780 } else { 21781 #ifdef BCM_TRIUMPH_SUPPORT 21782 if (soc_feature(unit, soc_feature_etu_support) && 21783 mem == EXT_L2_ENTRY_2m) { 21784 soc_mem_t ext_mem; 21785 int ext_index; 21786 21787 rv1 = soc_tcam_raw_index_to_mem_index(unit, index, 21788 &ext_mem, &ext_index); 21789 if (SOC_FAILURE(rv1)) { 21790 #if defined(BCM_TRIUMPH3_SUPPORT) 21791 if (soc_feature(unit, soc_feature_esm_correction) && 21792 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21793 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21794 SOC_ESM_UNLOCK(unit); 21795 } 21796 #endif 21797 MEM_UNLOCK(unit, mem); 21798 return rv1; 21799 } 21800 if (mem != ext_mem) { 21801 #if defined(BCM_TRIUMPH3_SUPPORT) 21802 if (soc_feature(unit, soc_feature_esm_correction) && 21803 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21804 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21805 SOC_ESM_UNLOCK(unit); 21806 } 21807 #endif 21808 MEM_UNLOCK(unit, mem); 21809 return SOC_E_INTERNAL; 21810 } 21811 index = ext_index; 21812 } 21813 #endif /* BCM_TRIUMPH_SUPPORT */ 21814 if (index_ptr != NULL) { 21815 *index_ptr = index; 21816 } 21817 if (type == SCHAN_GEN_RESP_TYPE_REPLACED) { 21818 if (old_entry != NULL) { 21819 /* coverity[overrun-buffer-arg] */ 21820 sal_memcpy(old_entry, data, entry_dw * sizeof(uint32)); 21821 } 21822 rv = SOC_E_EXISTS; 21823 } 21824 SOP_MEM_STATE(unit, mem).count[copyno]++; 21825 #if defined(BCM_TRIUMPH_SUPPORT) 21826 if (mem == EXT_L2_ENTRYm) { 21827 rv1 = soc_triumph_ext_l2_entry_update(unit, index, entry); 21828 if (SOC_FAILURE(rv1)) { 21829 #if defined(BCM_TRIUMPH3_SUPPORT) 21830 if (soc_feature(unit, soc_feature_esm_correction) && 21831 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21832 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21833 SOC_ESM_UNLOCK(unit); 21834 } 21835 #endif 21836 MEM_UNLOCK(unit, mem); 21837 return rv1; 21838 } 21839 } 21840 #endif /* BCM_TRIUMPH_SUPPORT */ 21841 #if defined(BCM_TRIUMPH3_SUPPORT) 21842 if (mem == EXT_L2_ENTRY_1m || mem == EXT_L2_ENTRY_2m) { 21843 rv1 = soc_triumph3_ext_l2_entry_update(unit, mem, index, entry); 21844 if (SOC_FAILURE(rv1)) { 21845 #if defined(BCM_TRIUMPH3_SUPPORT) 21846 if (soc_feature(unit, soc_feature_esm_correction) && 21847 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21848 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21849 SOC_ESM_UNLOCK(unit); 21850 } 21851 #endif 21852 MEM_UNLOCK(unit, mem); 21853 return rv1; 21854 } 21855 } 21856 #endif /* BCM_TRIUMPH3_SUPPORT */ 21857 /* Update cache if active */ 21858 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 21859 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 21860 index_valid = (index >= 0 && 21861 index <= soc_mem_index_max(unit, mem)); 21862 if (!index_valid) { 21863 #if defined(BCM_HURRICANE3_SUPPORT) 21864 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 21865 (mem == L2Xm) && 21866 (index & SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit))) { 21867 overflow_index = 21868 (index & ~SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit)); 21869 /* Check whether the entry is located at L2_OVERFLOW_ENTRY */ 21870 if ((overflow_index) <= 21871 soc_mem_index_max(unit, L2_ENTRY_OVERFLOWm)) { 21872 rv = SOC_E_NONE; 21873 /* update cache */ 21874 cache = SOC_MEM_STATE(unit, 21875 L2_ENTRY_OVERFLOWm).cache[copyno]; 21876 vmap = SOC_MEM_STATE(unit, 21877 L2_ENTRY_OVERFLOWm).vmap[copyno]; 21878 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 21879 /* 21880 * If an invalid or non-static entry 21881 * is being written then clear the cache 21882 */ 21883 if (soc_mem_field32_get(unit, mem, entry, VALIDf) && 21884 soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) { 21885 sal_memcpy(cache + overflow_index * entry_dw, 21886 entry, entry_dw * 4); 21887 CACHE_VMAP_SET(vmap, overflow_index); 21888 } else { 21889 CACHE_VMAP_CLR(vmap, overflow_index); 21890 } 21891 } 21892 } else { 21893 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21894 (BSL_META_U(unit, "soc_mem_generic_insert: " 21895 "invalid index %d for memory " 21896 "L2_ENTRY_OVERFLOW\n"), 21897 overflow_index)); 21898 rv = SOC_E_INTERNAL; 21899 } 21900 } else 21901 #endif /* BCM_HURRICANE3_SUPPORT */ 21902 { 21903 LOG_ERROR(BSL_LS_SOC_SOCMEM, 21904 (BSL_META_U(unit, 21905 "soc_mem_generic_insert: " 21906 "invalid index %d for memory %s\n"), 21907 index, SOC_MEM_NAME(unit, mem))); 21908 rv = SOC_E_INTERNAL; 21909 } 21910 } else if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 21911 if (_SOC_MEM_CHK_L2_MEM(mem)) { 21912 soc_field_t fld_vld = VALIDf; 21913 if (soc_feature(unit, soc_feature_base_valid)) { 21914 fld_vld = BASE_VALIDf; 21915 } 21916 /* If an invalid or non-static entry is being written then clear the cache */ 21917 if (((mem == L2_ENTRY_2m && 21918 soc_L2_ENTRY_2m_field32_get(unit, entry, VALID_0f) && 21919 soc_L2_ENTRY_2m_field32_get(unit, entry, VALID_1f)) || 21920 ((mem == L2Xm || mem == L2_ENTRY_1m) && 21921 soc_mem_field32_get(unit, mem, entry, fld_vld))) && 21922 (((mem == L2Xm || mem == L2_ENTRY_1m) && 21923 soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) || 21924 (mem == L2_ENTRY_2m && 21925 (soc_mem_field32_get(unit, mem, entry, STATIC_BIT_0f) && 21926 soc_mem_field32_get(unit, mem, entry, STATIC_BIT_1f))))) { 21927 sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4); 21928 CACHE_VMAP_SET(vmap, index); 21929 if (mem == L2_ENTRY_1m) { 21930 vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno]; 21931 CACHE_VMAP_CLR(vmap, index/2); 21932 } else if (mem == L2_ENTRY_2m) { 21933 vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno]; 21934 CACHE_VMAP_CLR(vmap, index*2); 21935 CACHE_VMAP_CLR(vmap, index*2 + 1); 21936 } 21937 } else { 21938 CACHE_VMAP_CLR(vmap, index); 21939 } 21940 } else { 21941 sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4); 21942 CACHE_VMAP_SET(vmap, index); 21943 } 21944 } 21945 } 21946 #if defined(BCM_TRIUMPH3_SUPPORT) 21947 if (soc_feature(unit, soc_feature_esm_correction) && 21948 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 21949 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 21950 SOC_ESM_UNLOCK(unit); 21951 } 21952 #endif 21953 MEM_UNLOCK(unit, mem); 21954 21955 return rv; 21956 } 21957 21958 /* 21959 * Function: 21960 * soc_mem_generic_delete 21961 * Purpose: 21962 * Delete an entry 21963 * Parameters: 21964 * unit - StrataSwitch unit # 21965 * banks - For dual hashing, which halves are selected (inverted) 21966 * Note: used to create a bitmap for ISM mems. (All banks: -1) 21967 * entry - entry to delete 21968 * old_entry - old entry if entry was found and deleted 21969 * Returns: 21970 * SOC_E_NONE - success 21971 * SOC_E_NOT_FOUND - full 21972 * SOC_E_BUSY - modfifo full 21973 * Notes: 21974 * Uses hardware deletion; sends an DELETE message over the 21975 * S-Channel. 21976 */ 21977 21978 int 21979 soc_mem_generic_delete(int unit, soc_mem_t mem, int copyno, int32 banks, 21980 void *entry, void *old_entry, int *index_ptr) 21981 { 21982 schan_msg_t schan_msg; 21983 #ifdef BCM_ESW_SUPPORT 21984 schan_msg_t schan_msg_cpy; 21985 #endif /* BCM_ESW_SUPPORT */ 21986 int rv, entry_dw, index_valid; 21987 uint8 at, *vmap; 21988 int type, err_info, index, allow_intr=0; 21989 uint32 *data, *cache; 21990 void *null_entry; 21991 int src_blk, dst_blk, acc_type, data_byte_len; 21992 int opcode, nack; 21993 uint32 bank_ignore_mask; 21994 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 21995 int rv1 = SOC_E_NONE; 21996 #endif 21997 #if defined(BCM_TRX_SUPPORT) 21998 #if defined(BCM_TRIDENT2_SUPPORT) 21999 uint8 delete_retry_attempt = 0; 22000 #endif 22001 uint8 delete_retry = 0; 22002 #endif 22003 #if defined(BCM_TRIUMPH3_SUPPORT) 22004 int del_disable = FALSE, try_one_time = 1; 22005 uint32 l2_delete = 0; 22006 #endif 22007 22008 #if defined(BCM_HURRICANE3_SUPPORT) 22009 uint32 overflow_index = 0; 22010 #endif /* BCM_HURRICANE3_SUPPORT */ 22011 #if defined(BCM_GREYHOUND2_SUPPORT) 22012 uint32 key_type = 0; 22013 #endif /* BCM_GREYHOUND2_SUPPORT */ 22014 22015 #ifdef BCM_TOMAHAWK3_SUPPORT 22016 int j = 0; 22017 uint16 dev_id; 22018 uint8 rev_id; 22019 schan_msg_t schan_msg_dupl; 22020 soc_cm_get_id(unit, &dev_id, &rev_id); 22021 #endif 22022 _SOC_MEM_REPLACE_MEM(unit, mem); 22023 SOC_MEM_ALIAS_TO_ORIG(unit,mem); 22024 null_entry = soc_mem_entry_null(unit, mem); 22025 22026 assert(SOC_MEM_IS_VALID(unit, mem)); 22027 assert(soc_attached(unit)); 22028 22029 if (copyno == MEM_BLOCK_ANY) { 22030 /* coverity[overrun-local : FALSE] */ 22031 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 22032 } 22033 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 22034 LOG_WARN(BSL_LS_SOC_SOCMEM, 22035 (BSL_META_U(unit, 22036 "soc_mem_generic_delete: invalid block %d for memory %s\n"), 22037 copyno, SOC_MEM_NAME(unit, mem))); 22038 return SOC_E_PARAM; 22039 } 22040 22041 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 22042 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 22043 "Delete table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem), 22044 banks)); 22045 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 22046 soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON); 22047 } 22048 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, 22049 "\n"))); 22050 } 22051 22052 #if defined(BCM_GREYHOUND2_SUPPORT) 22053 if (soc_feature(unit, soc_feature_vxlan_lite_riot) && (mem == L2Xm)) { 22054 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 22055 /* Use SW to delete a L2 entry when key_type is VFI_MULTICAST */ 22056 if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) { 22057 return soc_mem_gh2_l2_sw_delete(unit, mem, copyno, banks, 22058 entry, old_entry, index_ptr); 22059 } 22060 } 22061 #endif /* BCM_GREYHOUND2_SUPPORT */ 22062 22063 entry_dw = soc_mem_entry_words(unit, mem); 22064 22065 MEM_LOCK(unit, mem); 22066 #if defined(BCM_TRIUMPH3_SUPPORT) 22067 if (soc_feature(unit, soc_feature_esm_correction) && 22068 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22069 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22070 SOC_ESM_LOCK(unit); 22071 } 22072 #endif 22073 schan_msg_clear(&schan_msg); 22074 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 22075 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 22076 dst_blk = SOC_BLOCK2SCH(unit, copyno); 22077 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 22078 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 22079 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 22080 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 22081 (mem == L3_ENTRY_IPV6_MULTICASTm) 22082 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 22083 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 22084 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 22085 #endif 22086 #if defined(BCM_TOMAHAWK3_SUPPORT) 22087 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 22088 || (mem == L3_TUNNEL_QUADm) 22089 #endif 22090 #if defined(BCM_TRIDENT3_SUPPORT) 22091 || (mem == VLAN_XLATE_1_SINGLEm) 22092 || (mem == VLAN_XLATE_1_DOUBLEm) 22093 || (mem == EGR_VLAN_XLATE_1_SINGLEm) 22094 || (mem == EGR_VLAN_XLATE_1_DOUBLEm) 22095 || (mem == VLAN_XLATE_2_SINGLEm) 22096 || (mem == VLAN_XLATE_2_DOUBLEm) 22097 || (mem == EGR_VLAN_XLATE_2_SINGLEm) 22098 || (mem == EGR_VLAN_XLATE_2_DOUBLEm) 22099 #endif 22100 #if defined(BCM_TOMAHAWK_SUPPORT) 22101 || _SOC_MEM_CHK_FPEM_MEM(mem) 22102 #endif 22103 ))) { 22104 /* don't set bank id in cos */ 22105 bank_ignore_mask = 0; 22106 } else { 22107 bank_ignore_mask = banks & 0x3; 22108 } 22109 data_byte_len = entry_dw * 4; 22110 22111 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 22112 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 22113 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 22114 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 22115 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 22116 (mem == L3_ENTRY_IPV6_MULTICASTm) 22117 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 22118 || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) 22119 || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm) 22120 #endif 22121 #if defined(BCM_TOMAHAWK3_SUPPORT) 22122 || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm) 22123 || (mem == L3_TUNNEL_QUADm) 22124 #endif 22125 #if defined(BCM_TRIDENT3_SUPPORT) 22126 || (mem == VLAN_XLATE_1_SINGLEm) 22127 || (mem == VLAN_XLATE_1_DOUBLEm) 22128 || (mem == EGR_VLAN_XLATE_1_SINGLEm) 22129 || (mem == EGR_VLAN_XLATE_1_DOUBLEm) 22130 || (mem == VLAN_XLATE_2_SINGLEm) 22131 || (mem == VLAN_XLATE_2_DOUBLEm) 22132 || (mem == EGR_VLAN_XLATE_2_SINGLEm) 22133 || (mem == EGR_VLAN_XLATE_2_DOUBLEm) 22134 || (mem == MPLS_ENTRYm) 22135 #endif 22136 #if defined(BCM_TOMAHAWK_SUPPORT) 22137 || _SOC_MEM_CHK_FPEM_MEM(mem) 22138 #endif 22139 ))) { 22140 /* set bank ignore mask in lower 20 bits */ 22141 if (banks && banks != SOC_MEM_HASH_BANK_ALL) { 22142 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 22143 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED); 22144 } else { 22145 #ifdef BCM_TRIUMPH3_SUPPORT 22146 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks); 22147 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM); 22148 #endif /* BCM_TRIUMPH3_SUPPORT */ 22149 } 22150 } 22151 } 22152 #ifdef BCM_TOMAHAWK3_SUPPORT 22153 /* For 56983 Lower die SKU, we are converting data split and unique into 4 unique 22154 delete commands */ 22155 if ((acc_type == 14 || acc_type == 9) && (dev_id == BCM56983_DEVICE_ID)) { 22156 sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg)); 22157 for (j = 0; j < 4; j++) { 22158 switch(j) { 22159 case 0 : acc_type = 0; 22160 break; 22161 case 1 : acc_type = 1; 22162 break; 22163 case 2 : acc_type = 6; 22164 break; 22165 case 3 : acc_type = 7; 22166 break; 22167 } 22168 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg)); 22169 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG, 22170 dst_blk, src_blk, acc_type, data_byte_len, 0, 22171 bank_ignore_mask); 22172 /* Fill in packet data */ 22173 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 22174 #ifdef BCM_ESW_SUPPORT 22175 if (soc_feature(unit, soc_feature_shared_hash_mem) || 22176 soc_feature(unit, soc_feature_dual_hash) || 22177 soc_feature(unit, soc_feature_ism_memory)) { 22178 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg)); 22179 } 22180 #endif 22181 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 22182 NULL, NULL, &nack); 22183 if (opcode != TABLE_DELETE_DONE_MSG) { 22184 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22185 (BSL_META_U(unit, 22186 "soc_mem_generic_delete: " 22187 "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n"))); 22188 soc_schan_dump(unit, &schan_msg, 1); 22189 #if defined(BCM_TRIUMPH3_SUPPORT) 22190 if (soc_feature(unit, soc_feature_esm_correction) && 22191 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22192 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22193 SOC_ESM_UNLOCK(unit); 22194 } 22195 #endif 22196 #if defined(BCM_TRIUMPH3_SUPPORT) 22197 if (del_disable) { 22198 _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete); 22199 del_disable = FALSE; 22200 } 22201 #endif 22202 MEM_UNLOCK(unit, mem); 22203 return SOC_E_INTERNAL; 22204 } 22205 } 22206 } else if (acc_type == 15 && (dev_id == BCM56983_DEVICE_ID)) { 22207 sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg)); 22208 for (j = 0; j < 2; j++) { 22209 switch(j) { 22210 case 0 : acc_type = 0; 22211 break; 22212 case 1 : acc_type = 6; 22213 break; 22214 } 22215 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg)); 22216 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG, 22217 dst_blk, src_blk, acc_type, data_byte_len, 0, 22218 bank_ignore_mask); 22219 /* Fill in packet data */ 22220 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 22221 #ifdef BCM_ESW_SUPPORT 22222 if (soc_feature(unit, soc_feature_shared_hash_mem) || 22223 soc_feature(unit, soc_feature_dual_hash) || 22224 soc_feature(unit, soc_feature_ism_memory)) { 22225 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg)); 22226 } 22227 #endif 22228 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 22229 NULL, NULL, &nack); 22230 if (opcode != TABLE_DELETE_DONE_MSG) { 22231 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22232 (BSL_META_U(unit, 22233 "soc_mem_generic_delete: " 22234 "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n"))); 22235 soc_schan_dump(unit, &schan_msg, 1); 22236 #if defined(BCM_TRIUMPH3_SUPPORT) 22237 if (soc_feature(unit, soc_feature_esm_correction) && 22238 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22239 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22240 SOC_ESM_UNLOCK(unit); 22241 } 22242 #endif 22243 #if defined(BCM_TRIUMPH3_SUPPORT) 22244 if (del_disable) { 22245 _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete); 22246 del_disable = FALSE; 22247 } 22248 #endif 22249 MEM_UNLOCK(unit, mem); 22250 return SOC_E_INTERNAL; 22251 } 22252 } 22253 } else 22254 #endif 22255 { 22256 #ifdef BCM_TOMAHAWK3_SUPPORT 22257 if (acc_type == 16 && (dev_id == BCM56983_DEVICE_ID)) { 22258 acc_type = 0; 22259 } 22260 #endif 22261 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG, 22262 dst_blk, src_blk, acc_type, data_byte_len, 0, 22263 bank_ignore_mask); 22264 22265 /* Fill in packet data */ 22266 sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4); 22267 22268 if (SOC_IS_SAND(unit)) { 22269 allow_intr = 1; 22270 } 22271 22272 /* 22273 * Execute S-Channel "table delete" command packet consisting of 22274 * (header word + address word + entry_dw), and read back 22275 * (header word + response word + entry_dw) data words. 22276 */ 22277 #ifdef BCM_ESW_SUPPORT 22278 if (soc_feature(unit, soc_feature_shared_hash_mem) || 22279 soc_feature(unit, soc_feature_dual_hash) || 22280 soc_feature(unit, soc_feature_ism_memory)) { 22281 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg)); 22282 } 22283 #endif 22284 #if defined(BCM_TRX_SUPPORT) 22285 _retry_op_delete: 22286 #endif 22287 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr); 22288 22289 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 22290 NULL, NULL, &nack); 22291 if (opcode != TABLE_DELETE_DONE_MSG) { 22292 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22293 (BSL_META_U(unit, 22294 "soc_mem_generic_delete: " 22295 "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n"))); 22296 soc_schan_dump(unit, &schan_msg, 1); 22297 #if defined(BCM_TRIUMPH3_SUPPORT) 22298 if (soc_feature(unit, soc_feature_esm_correction) && 22299 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22300 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22301 SOC_ESM_UNLOCK(unit); 22302 } 22303 #endif 22304 #if defined(BCM_TRIUMPH3_SUPPORT) 22305 if (del_disable) { 22306 _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete); 22307 del_disable = FALSE; 22308 } 22309 #endif 22310 MEM_UNLOCK(unit, mem); 22311 return SOC_E_INTERNAL; 22312 } 22313 22314 } 22315 if (soc_feature(unit, soc_feature_new_sbus_format) && 22316 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 22317 type = schan_msg.genresp_v2.response.type; 22318 err_info = schan_msg.genresp_v2.response.err_info; 22319 index = schan_msg.genresp_v2.response.index; 22320 data = schan_msg.genresp_v2.data; 22321 } else { 22322 type = schan_msg.genresp.response.type; 22323 err_info = schan_msg.genresp.response.err_info; 22324 index = schan_msg.genresp.response.index; 22325 data = schan_msg.genresp.data; 22326 } 22327 #if defined(BCM_TRIUMPH3_SUPPORT) 22328 if (del_disable) { 22329 _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete); 22330 del_disable = FALSE; 22331 if (type == SCHAN_GEN_RESP_TYPE_DELETED) { 22332 if (SOC_IS_TRIUMPH3(unit)) { 22333 soc_l2_entry_callback(unit, 0, mem, entry, NULL); 22334 } 22335 } 22336 } 22337 #endif 22338 22339 if ((nack != 0) || (rv == SOC_E_FAIL)) { 22340 if (index_ptr) { 22341 *index_ptr = -1; 22342 } 22343 if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { 22344 LOG_INFO(BSL_LS_SOC_SOCMEM, 22345 (BSL_META_U(unit, 22346 "Delete table[%s]: Not found\n"), 22347 SOC_MEM_NAME(unit, mem))); 22348 rv = SOC_E_NOT_FOUND; 22349 } else if (type == SCHAN_GEN_RESP_TYPE_ERROR) { 22350 LOG_VERBOSE(BSL_LS_SOC_SER,(BSL_META_U(unit, 22351 ">>>>> soc_mem_generic_delete: rv=%d, nack=%d, type=%d, index=%d\n"), 22352 rv, nack, type, index)); 22353 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 22354 if (soc_feature(unit, soc_feature_shared_hash_mem) && 22355 (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit))) { 22356 int i, rv1 = SOC_E_NONE, index1 = index, ir1 = 1, 22357 pipe1 = SOC_PIPE_ANY; 22358 soc_mem_t mem1 = mem; 22359 22360 (void)_soc_inline_ser_mem_remap(unit, &mem1, &pipe1, &ir1); 22361 index1 = (index / ir1) * ir1; /* base_index for entry */ 22362 22363 for (i = 0; i < ir1; i++) { 22364 rv1 = soc_ser_sram_correction(unit, pipe1, 22365 schan_msg.gencmd.header.v2.dst_blk, 22366 schan_msg.gencmd.address, mem1, 22367 copyno, index1 + i, NULL); 22368 if (SOC_FAILURE(rv1)) { 22369 break; 22370 } 22371 } 22372 if (rv1 == SOC_E_NONE) { 22373 if (delete_retry_attempt < HASH_MEM_OP_RETRY_COUNT) { 22374 delete_retry_attempt++; 22375 sal_memcpy(&schan_msg, &schan_msg_cpy, 22376 sizeof(schan_msg)); 22377 goto _retry_op_delete; 22378 } 22379 } 22380 } 22381 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_APACHE_SUPPORT */ 22382 if (err_info == SCHAN_GEN_RESP_ERROR_BUSY) { 22383 LOG_INFO(BSL_LS_SOC_SOCMEM, 22384 (BSL_META_U(unit, 22385 "Delete table[%s]: Modfifo full\n"), 22386 SOC_MEM_NAME(unit, mem))); 22387 rv = SOC_E_BUSY; 22388 } else if (err_info == SCHAN_GEN_RESP_ERROR_PARITY) { 22389 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22390 (BSL_META_U(unit, 22391 "Delete table[%s]: Parity Error Index %d\n"), 22392 SOC_MEM_NAME(unit, mem), index)); 22393 rv = SOC_E_INTERNAL; 22394 } 22395 /* For Trident2, type is SCHAN_GEN_RESP_TYPE_ERROR, err_info is 0 */ 22396 #if defined(BCM_TRX_SUPPORT) 22397 if (SOC_IS_TRX(unit) && (soc_mem_is_hashed(unit, mem))) { 22398 /* Try to recover */ 22399 rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg, 22400 banks, entry); 22401 if (rv == SOC_E_NONE) { 22402 if (delete_retry < HASH_MEM_OP_RETRY_COUNT) { 22403 delete_retry++; 22404 if (soc_mem_generic_lookup(unit, mem, copyno, banks, 22405 entry, NULL, index_ptr) == 22406 SOC_E_NOT_FOUND) { 22407 rv = SOC_E_NONE; 22408 } else { 22409 sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg)); 22410 LOG_WARN(BSL_LS_SOC_SOCMEM, 22411 (BSL_META_U(unit, 22412 "unit %d: Retry Hash delete operation..\n"), 22413 unit)); 22414 goto _retry_op_delete; 22415 } 22416 } 22417 } else { 22418 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22419 (BSL_META_U(unit, 22420 "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"), 22421 unit, SOC_MEM_NAME(unit, mem), rv)); 22422 } 22423 } 22424 #endif 22425 } else { 22426 22427 rv = SOC_E_FAIL; 22428 #if defined(BCM_TRIDENT2_SUPPORT) 22429 if (SOC_IS_TD2_TT2(unit) && soc_mem_is_hashed(unit, mem) && 22430 (type == SCHAN_GEN_RESP_TYPE_DELETED)) { 22431 rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg, 22432 banks, entry); 22433 if (rv == SOC_E_NONE) { 22434 if (delete_retry_attempt < HASH_MEM_OP_RETRY_COUNT) { 22435 delete_retry_attempt++; 22436 if (soc_mem_generic_lookup(unit, mem, copyno, banks, 22437 entry, NULL, index_ptr) == 22438 SOC_E_NOT_FOUND) { 22439 rv = SOC_E_NONE; 22440 } else { 22441 sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg)); 22442 LOG_WARN(BSL_LS_SOC_SOCMEM, 22443 (BSL_META_U(unit, 22444 "unit %d: Retry Hash delete operation..\n"), 22445 unit)); 22446 goto _retry_op_delete; 22447 } 22448 } 22449 } else { 22450 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22451 (BSL_META_U(unit, 22452 "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"), 22453 unit, SOC_MEM_NAME(unit, mem), rv)); 22454 } 22455 } 22456 #endif 22457 #if defined(BCM_TRIUMPH3_SUPPORT) 22458 if ((SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT(unit) || 22459 SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) && 22460 ((type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL) || 22461 (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) { 22462 /*This is a Software Workaround for L2_MOD_FIFO. Sometimes an entry may be 22463 unable to be deleted when L2_MOD_FIFO is too busy. In this situation 22464 the L2_DELETE field in L2_MOD_FIFO_ENABLE will be disabled and retry the delete 22465 operation. After the deletion the L2_DELETE field will be enabled.*/ 22466 if ((SOC_IS_TRIUMPH3(unit)) && 22467 (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL)) { 22468 if (soc_mem_generic_lookup(unit, mem, copyno, banks, 22469 entry, NULL, index_ptr) == 22470 SOC_E_NOT_FOUND) { 22471 rv = SOC_E_NONE; 22472 } else { 22473 l2_delete = _soc_l2mode_fifo_enable_delete_field_get(unit); 22474 _soc_l2mode_fifo_enable_delete_field_set(unit, 0); 22475 del_disable = TRUE; 22476 sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg)); 22477 if (l2_delete && try_one_time) { 22478 LOG_INFO(BSL_LS_SOC_SOCMEM, 22479 (BSL_META_U(unit, 22480 "L2_MOD_FIFO may be full," 22481 "error type [%d]," 22482 "will delete again!\n"), 22483 type)); 22484 try_one_time--; 22485 goto _retry_op_delete; 22486 } else { 22487 _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete); 22488 } 22489 } 22490 } else if ((SOC_IS_TRIDENT(unit) && 22491 (type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL)) || 22492 ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) && 22493 (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) { 22494 LOG_INFO(BSL_LS_SOC_SOCMEM, 22495 (BSL_META_U(unit, 22496 "L2_MOD_FIFO is full, error type [%d]"), 22497 type)); 22498 rv = SOC_E_FULL; 22499 MEM_UNLOCK(unit, mem); 22500 return rv; 22501 } 22502 } 22503 #endif 22504 } 22505 } else { 22506 if (old_entry != NULL) { 22507 sal_memcpy(old_entry, data, entry_dw * sizeof(uint32)); 22508 } 22509 #ifdef BCM_TRIUMPH_SUPPORT 22510 if (soc_feature(unit, soc_feature_etu_support) && 22511 mem == EXT_L2_ENTRY_2m) { 22512 soc_mem_t ext_mem; 22513 int ext_index; 22514 22515 rv1 = soc_tcam_raw_index_to_mem_index(unit, index, 22516 &ext_mem, &ext_index); 22517 if (SOC_FAILURE(rv1)) { 22518 #if defined(BCM_TRIUMPH3_SUPPORT) 22519 if (soc_feature(unit, soc_feature_esm_correction) && 22520 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22521 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22522 SOC_ESM_UNLOCK(unit); 22523 } 22524 #endif 22525 MEM_UNLOCK(unit, mem); 22526 return rv1; 22527 } 22528 if (mem != ext_mem) { 22529 #if defined(BCM_TRIUMPH3_SUPPORT) 22530 if (soc_feature(unit, soc_feature_esm_correction) && 22531 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22532 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22533 SOC_ESM_UNLOCK(unit); 22534 } 22535 #endif 22536 MEM_UNLOCK(unit, mem); 22537 return SOC_E_INTERNAL; 22538 } 22539 index = ext_index; 22540 } 22541 #endif /* BCM_TRIUMPH_SUPPORT */ 22542 if (index_ptr != NULL) { 22543 *index_ptr = index; 22544 } 22545 SOP_MEM_STATE(unit, mem).count[copyno]--; 22546 #if defined(BCM_TRIUMPH_SUPPORT) 22547 if (mem == EXT_L2_ENTRYm) { 22548 rv1 = soc_triumph_ext_l2_entry_update(unit, index, NULL); 22549 if (SOC_FAILURE(rv1)) { 22550 #if defined(BCM_TRIUMPH3_SUPPORT) 22551 if (soc_feature(unit, soc_feature_esm_correction) && 22552 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22553 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22554 SOC_ESM_UNLOCK(unit); 22555 } 22556 #endif 22557 MEM_UNLOCK(unit, mem); 22558 return rv1; 22559 } 22560 } 22561 #endif /* BCM_TRIUMPH_SUPPORT */ 22562 #if defined(BCM_TRIUMPH3_SUPPORT) 22563 if (mem == EXT_L2_ENTRY_1m || mem == EXT_L2_ENTRY_2m) { 22564 rv1 = soc_triumph3_ext_l2_entry_update(unit, mem, index, NULL); 22565 if (SOC_FAILURE(rv1)) { 22566 #if defined(BCM_TRIUMPH3_SUPPORT) 22567 if (soc_feature(unit, soc_feature_esm_correction) && 22568 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22569 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22570 SOC_ESM_UNLOCK(unit); 22571 } 22572 #endif 22573 MEM_UNLOCK(unit, mem); 22574 return rv1; 22575 } 22576 } 22577 #endif /* BCM_TRIUMPH3_SUPPORT */ 22578 if (!SOC_WARM_BOOT(unit)) { 22579 /* Update cache if active */ 22580 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 22581 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 22582 index_valid = (index >= 0 && 22583 index <= soc_mem_index_max(unit, mem)); 22584 if (!index_valid) { 22585 #if defined(BCM_HURRICANE3_SUPPORT) 22586 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 22587 (mem == L2Xm) && 22588 (index & SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit))) { 22589 overflow_index = 22590 (index & ~SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit)); 22591 /* Check whether the entry is located at L2_OVERFLOW_ENTRY */ 22592 if ((overflow_index) <= 22593 soc_mem_index_max(unit, L2_ENTRY_OVERFLOWm)) { 22594 /* update cache */ 22595 cache = 22596 SOC_MEM_STATE(unit, 22597 L2_ENTRY_OVERFLOWm).cache[copyno]; 22598 vmap = 22599 SOC_MEM_STATE(unit, 22600 L2_ENTRY_OVERFLOWm).vmap[copyno]; 22601 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit) && 22602 CACHE_VMAP_TST(vmap, overflow_index)) { 22603 CACHE_VMAP_CLR(vmap, index); 22604 } 22605 MEM_UNLOCK(unit, mem); 22606 return rv; 22607 } else { 22608 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22609 (BSL_META_U(unit, 22610 "soc_mem_generic_delete: " 22611 "invalid index %d for memory " 22612 "L2_ENTRY_OVERFLOW\n"), 22613 overflow_index)); 22614 } 22615 } else 22616 #endif /* BCM_HURRICANE3_SUPPORT */ 22617 { 22618 LOG_ERROR(BSL_LS_SOC_SOCMEM, 22619 (BSL_META_U(unit, 22620 "soc_mem_generic_delete: " 22621 "invalid index %d for memory %s\n"), 22622 index, SOC_MEM_NAME(unit, mem))); 22623 } 22624 #if defined(BCM_TRIUMPH3_SUPPORT) 22625 if (soc_feature(unit, soc_feature_esm_correction) && 22626 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22627 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22628 SOC_ESM_UNLOCK(unit); 22629 } 22630 #endif 22631 MEM_UNLOCK(unit, mem); 22632 return SOC_E_INTERNAL; 22633 } 22634 if (index_valid && cache != NULL && CACHE_VMAP_TST(vmap, index) 22635 && !SOC_MEM_TEST_SKIP_CACHE(unit)) { 22636 if (_SOC_MEM_CHK_L2_MEM(mem)) { 22637 CACHE_VMAP_CLR(vmap, index); 22638 if (mem == L2_ENTRY_1m) { 22639 vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno]; 22640 CACHE_VMAP_CLR(vmap, index/2); 22641 } else if (mem == L2_ENTRY_2m) { 22642 vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno]; 22643 CACHE_VMAP_CLR(vmap, index*2); 22644 CACHE_VMAP_CLR(vmap, index*2 + 1); 22645 } 22646 } else { 22647 sal_memcpy(cache + index * entry_dw, null_entry, entry_dw * 4); 22648 CACHE_VMAP_CLR(vmap, index); 22649 } 22650 } 22651 } 22652 } 22653 #if defined(BCM_TRIUMPH3_SUPPORT) 22654 if (soc_feature(unit, soc_feature_esm_correction) && 22655 ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 22656 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) { 22657 SOC_ESM_UNLOCK(unit); 22658 } 22659 #endif 22660 MEM_UNLOCK(unit, mem); 22661 return rv; 22662 } 22663 22664 /* 22665 * Function: 22666 * soc_mem_search 22667 * Purpose: 22668 * Search a memory for a key. 22669 * Parameters: 22670 * mem Memory to search 22671 * copyno Which copy to search (if multiple copies) 22672 * index_ptr OUT: 22673 * If entry found gets the location of the entry. 22674 * If not found, and table is sorted, gets the 22675 * location of the insertion point. 22676 * CAN NO LONGER BE NULL. 22677 * key_data IN: Data to search for 22678 * entry_data, OUT: Data if found 22679 * CAN NO LONGER BE NULL. Must be big enough 22680 * to handle the appropriate data. 22681 * lowest_match IN: For sorted tables only. 22682 * If there are duplicate entries in the 22683 * table, and lowest_match is 1, then the 22684 * matching entry at the lowest index is 22685 * returned. If lowest_match is 0, then any 22686 * of the matching entries may be picked at 22687 * random, which can be faster. 22688 * Returns: 22689 * SOC_E_NOT_FOUND 22690 * Entry not found: in this case, if 22691 * table is sorted, then index_ptr gets the 22692 * location in which the entry should be 22693 * inserted. 22694 * SOC_E_NONE Entry is found: index_ptr gets location 22695 * SOC_E_XXX If internal error occurs 22696 * Notes: 22697 * A binary search is performed for a matching table entry. 22698 * The appropriate field(s) of entry_data are used for the key. 22699 * All other fields in entry_data are ignored. 22700 * 22701 * If found, the index is stored in index_ptr, and if entry_data is 22702 * non-NULL, the contents of the found entry are written into it, 22703 * and 1 is returned. 22704 * If not found, the index of a correct insertion point for the 22705 * entry is stored in index_ptr and 0 is returned (unless this 22706 * is a hashed table). 22707 * If a table read error occurs, SOC_E_XXX is returned. 22708 * 22709 * For the ARL table, all entries are searched. On revision GSL and 22710 * higher, a hardware lookup feature is used. For earlier 22711 * revisions, a software search is used, which is not 22712 * recommended since the ARL table may be under constant 22713 * update by the hardware. For hardware lookup, the index_ptr 22714 * is written with -1. 22715 * For non-ARL sorted tables, only the entries known to contain data 22716 * are searched: 22717 * (index_min <= search_index < index_min + memInfo.count). 22718 */ 22719 22720 int 22721 soc_mem_search(int unit, 22722 soc_mem_t mem, 22723 int copyno, 22724 int *index_ptr, 22725 void *key_data, 22726 void *entry_data, 22727 int lowest_match) 22728 { 22729 int rv = 0; 22730 #ifdef BCM_TRIDENT3_SUPPORT 22731 soc_mem_t phy_mem; 22732 #endif 22733 22734 COMPILER_REFERENCE(rv); 22735 22736 #ifdef BCM_TRIDENT3_SUPPORT 22737 if (soc_feature(unit, soc_feature_flex_flow)) { 22738 if (SOC_MEM_IS_VIEW(unit, mem)) { 22739 rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem); 22740 if (rv != SOC_E_NONE) { 22741 return rv; 22742 } 22743 mem = phy_mem; 22744 } 22745 } 22746 #endif 22747 22748 assert(soc_mem_is_sorted(unit, mem) || 22749 soc_mem_is_hashed(unit, mem) || 22750 soc_mem_is_cam(unit, mem) || 22751 soc_mem_is_cmd(unit, mem)); 22752 assert(entry_data); 22753 assert(index_ptr); 22754 22755 if (copyno == MEM_BLOCK_ANY) { 22756 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 22757 } 22758 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 22759 22760 #ifdef BCM_TRX_SUPPORT 22761 if (soc_feature(unit, soc_feature_generic_table_ops)) { 22762 int32 banks = 0; 22763 _SOC_MEM_REPLACE_MEM(unit, mem); 22764 switch (mem) { 22765 case L2Xm: 22766 case L3_ENTRY_IPV4_UNICASTm: 22767 case L3_ENTRY_IPV4_MULTICASTm: 22768 case L3_ENTRY_IPV6_UNICASTm: 22769 case L3_ENTRY_IPV6_MULTICASTm: 22770 case EXACT_MATCH_2m: 22771 case EXACT_MATCH_2_PIPE0m: 22772 case EXACT_MATCH_2_PIPE1m: 22773 case EXACT_MATCH_2_PIPE2m: 22774 case EXACT_MATCH_2_PIPE3m: 22775 case EXACT_MATCH_4m: 22776 case EXACT_MATCH_4_PIPE0m: 22777 case EXACT_MATCH_4_PIPE1m: 22778 case EXACT_MATCH_4_PIPE2m: 22779 case EXACT_MATCH_4_PIPE3m: 22780 #ifdef BCM_ISM_SUPPORT 22781 case L2_ENTRY_1m: 22782 case L2_ENTRY_2m: 22783 case L3_ENTRY_1m: 22784 case L3_ENTRY_2m: 22785 case L3_ENTRY_4m: 22786 case VLAN_XLATE_EXTDm: 22787 case MPLS_ENTRY_EXTDm: 22788 #endif /* BCM_ISM_SUPPORT */ 22789 case EGR_VLAN_XLATEm: 22790 case VLAN_XLATEm: 22791 case MPLS_ENTRYm: 22792 /* passthru */ 22793 /* coverity[fallthrough: FALSE] */ 22794 #ifdef BCM_TRIUMPH3_SUPPORT 22795 case AXP_WRX_WCDm: 22796 case AXP_WRX_SVP_ASSIGNMENTm: 22797 case EXT_L2_ENTRY_1m: 22798 case EXT_L2_ENTRY_2m: 22799 case FT_SESSIONm: 22800 case FT_SESSION_IPV6m: 22801 #endif /* BCM_TRIUMPH3_SUPPORT */ 22802 case VLAN_MACm: 22803 #ifdef BCM_TRIDENT2_SUPPORT 22804 case ING_VP_VLAN_MEMBERSHIPm: 22805 case EGR_VP_VLAN_MEMBERSHIPm: 22806 case ING_DNAT_ADDRESS_TYPEm: 22807 case L2_ENDPOINT_IDm: 22808 case ENDPOINT_QUEUE_MAPm: 22809 #endif /* BCM_TRIDENT2_SUPPORT */ 22810 #ifdef BCM_KATANA2_SUPPORT 22811 case EGR_MP_GROUPm: 22812 #endif 22813 #ifdef BCM_SABER2_SUPPORT 22814 case MP_GROUPm: 22815 #endif 22816 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 22817 case L3_ENTRY_SINGLEm: 22818 case L3_ENTRY_DOUBLEm: 22819 case L3_ENTRY_QUADm: 22820 case MPLS_ENTRY_SINGLEm: 22821 case VLAN_XLATE_1_SINGLEm: 22822 case VLAN_XLATE_1_DOUBLEm: 22823 case VLAN_XLATE_2_SINGLEm: 22824 case VLAN_XLATE_2_DOUBLEm: 22825 case EGR_VLAN_XLATE_1_SINGLEm: 22826 case EGR_VLAN_XLATE_1_DOUBLEm: 22827 case EGR_VLAN_XLATE_2_SINGLEm: 22828 case EGR_VLAN_XLATE_2_DOUBLEm: 22829 case SUBPORT_ID_TO_SGPP_MAPm: 22830 #endif 22831 #if defined(BCM_TOMAHAWK3_SUPPORT) 22832 case L3_TUNNEL_SINGLEm: 22833 case L3_TUNNEL_DOUBLEm: 22834 case L3_TUNNEL_QUADm: 22835 #endif 22836 #ifdef BCM_HELIX5_SUPPORT 22837 case FT_KEY_SINGLEm: 22838 case FT_KEY_DOUBLEm: 22839 #endif 22840 case EXT_L2_ENTRYm: 22841 if (soc_feature(unit, soc_feature_ism_memory) && 22842 soc_mem_is_mview(unit, mem)) { 22843 banks = -1; 22844 } 22845 return soc_mem_generic_lookup(unit, mem, copyno, banks, 22846 key_data, entry_data, index_ptr); 22847 default: 22848 break; 22849 } 22850 } 22851 #endif /* BCM_TRX_SUPPORT */ 22852 22853 #ifdef BCM_FIREBOLT_SUPPORT 22854 if (SOC_IS_FBX(unit)) { 22855 switch (mem) { 22856 case L2Xm: 22857 return soc_fb_l2x_lookup(unit, key_data, 22858 entry_data, index_ptr); 22859 #if defined(INCLUDE_L3) 22860 case L3_DEFIPm: 22861 case L3_DEFIP_LEVEL1m: 22862 return soc_fb_lpm_match(unit, key_data, entry_data, index_ptr); 22863 case L3_ENTRY_IPV4_UNICASTm: 22864 case L3_ENTRY_IPV4_MULTICASTm: 22865 case L3_ENTRY_IPV6_UNICASTm: 22866 case L3_ENTRY_IPV6_MULTICASTm: 22867 return soc_fb_l3x_lookup(unit, key_data, entry_data, index_ptr); 22868 #endif /* INCLUDE_L3 */ 22869 case VLAN_MACm: 22870 return soc_fb_vlanmac_entry_lkup(unit, key_data, entry_data, index_ptr); 22871 default: 22872 break; 22873 } 22874 } 22875 #endif /* BCM_FIREBOLT_SUPPORT */ 22876 22877 return _soc_mem_search(unit, mem, copyno, index_ptr, key_data, 22878 entry_data, lowest_match); 22879 } 22880 22881 22882 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \ 22883 || defined(BCM_RAVEN_SUPPORT) || defined(BCM_HAWKEYE_SUPPORT) 22884 22885 /* 22886 * Function: 22887 * soc_mem_bank_insert 22888 * Purpose: 22889 * Do a single insert to a banked hash table with bank selection 22890 */ 22891 int 22892 soc_mem_bank_insert(int unit, 22893 soc_mem_t mem, 22894 int32 banks, 22895 int copyno, 22896 void *entry_data, 22897 void *old_entry_data) 22898 { 22899 if (SOC_CONTROL(unit)->soc_mem_watch) { 22900 if (SOC_CONTROL(unit)->prev_mem != mem) { 22901 LOG_CLI((BSL_META_U(unit, "%d:%s MEM: %s\n"), 22902 unit, BSL_FUNC, SOC_MEM_NAME(unit, mem))); 22903 SOC_CONTROL(unit)->prev_mem = mem; 22904 } 22905 } 22906 if (soc_feature(unit, soc_feature_generic_table_ops)) { 22907 return soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 22908 banks, entry_data, old_entry_data, 0); 22909 } 22910 22911 switch (mem) { 22912 case L2Xm: 22913 return soc_fb_l2x_bank_insert(unit, banks, 22914 (l2x_entry_t *)entry_data); 22915 #if defined(INCLUDE_L3) 22916 case L3_ENTRY_IPV4_UNICASTm: 22917 case L3_ENTRY_IPV4_MULTICASTm: 22918 case L3_ENTRY_IPV6_UNICASTm: 22919 case L3_ENTRY_IPV6_MULTICASTm: 22920 return soc_fb_l3x_bank_insert(unit, banks, 22921 (l3_entry_ipv6_multicast_entry_t *)entry_data); 22922 #endif 22923 #if defined(BCM_RAVEN_SUPPORT) 22924 case VLAN_MACm: 22925 if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 22926 return soc_fb_vlanmac_entry_bank_ins(unit, banks, 22927 (vlan_mac_entry_t *)entry_data); 22928 } else { 22929 return SOC_E_UNAVAIL; 22930 } 22931 #endif 22932 default: 22933 break; 22934 } 22935 22936 return SOC_E_UNAVAIL; 22937 } 22938 22939 int soc_fb_vlanmac_entry_bank_delete(int unit, 22940 int32 banks, 22941 vlan_mac_entry_t *entry_data) 22942 { 22943 return soc_fb_vlanmac_entry_del(unit, (vlan_mac_entry_t *)entry_data); 22944 } 22945 22946 /* 22947 * Function: 22948 * soc_mem_bank_delete 22949 * Purpose: 22950 * Do a single delete to a banked hash table with bank selection 22951 * Parameters: 22952 * unit - StrataSwitch unit # 22953 * mem - Memory in which the entry has to be deleted. 22954 * banks - For dual hashing, which halves are selected (inverted) 22955 * copyno - Specific copy of table/memory or all if -1. 22956 * entry_data - entry to be deleted. 22957 * old_entry_data (OUT) - If found, receives table index where 22958 * entry was deleted. 22959 * Returns: 22960 * SOC_E_INTERNAL if retries exceeded or other internal error 22961 * SOC_E_NOT_FOUND if the entry is not found. 22962 * SOC_E_NONE (0) on success (entry found): 22963 */ 22964 int 22965 soc_mem_bank_delete(int unit, 22966 soc_mem_t mem, 22967 int32 banks, 22968 int copyno, 22969 void *entry_data, 22970 void *old_entry_data) 22971 { 22972 if (soc_feature(unit, soc_feature_generic_table_ops)) { 22973 return soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 22974 banks, entry_data, old_entry_data, 0); 22975 } 22976 22977 switch (mem) { 22978 case L2Xm: 22979 return soc_fb_l2x_bank_delete(unit, banks, 22980 (l2x_entry_t *)entry_data); 22981 #if defined(INCLUDE_L3) 22982 case L3_ENTRY_IPV4_UNICASTm: 22983 case L3_ENTRY_IPV4_MULTICASTm: 22984 case L3_ENTRY_IPV6_UNICASTm: 22985 case L3_ENTRY_IPV6_MULTICASTm: 22986 return soc_fb_l3x_bank_delete(unit, banks, 22987 (l3_entry_ipv6_multicast_entry_t *)entry_data); 22988 #endif 22989 #if defined(BCM_RAVEN_SUPPORT) 22990 case VLAN_MACm: 22991 if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 22992 return soc_fb_vlanmac_entry_bank_delete(unit, banks, 22993 (vlan_mac_entry_t *)entry_data); 22994 } else { 22995 return SOC_E_UNAVAIL; 22996 } 22997 #endif 22998 default: 22999 break; 23000 } 23001 23002 return SOC_E_UNAVAIL; 23003 } 23004 23005 23006 /* 23007 * Function: 23008 * soc_mem_bank_search 23009 * Purpose: 23010 * Search a banked hash table with bank selection 23011 */ 23012 int 23013 soc_mem_bank_search(int unit, 23014 soc_mem_t mem, 23015 uint8 banks, 23016 int copyno, 23017 int *index_ptr, 23018 void *key_data, 23019 void *entry_data) 23020 { 23021 switch (mem) { 23022 case L2Xm: 23023 return soc_fb_l2x_bank_lookup(unit, banks, (l2x_entry_t *)key_data, 23024 (l2x_entry_t *)entry_data, index_ptr); 23025 #if defined(INCLUDE_L3) 23026 case L3_ENTRY_IPV4_UNICASTm: 23027 case L3_ENTRY_IPV4_MULTICASTm: 23028 case L3_ENTRY_IPV6_UNICASTm: 23029 case L3_ENTRY_IPV6_MULTICASTm: 23030 return soc_fb_l3x_bank_lookup(unit, banks, 23031 (l3_entry_ipv6_multicast_entry_t *)key_data, 23032 (l3_entry_ipv6_multicast_entry_t *)entry_data, 23033 index_ptr); 23034 #endif 23035 default: 23036 break; 23037 } 23038 23039 return SOC_E_UNAVAIL; 23040 } 23041 23042 /* 23043 * Function: 23044 * _soc_mem_dual_hash_get 23045 * Purpose: 23046 * Calcualte hash for dual hashed memories 23047 */ 23048 23049 STATIC int 23050 _soc_mem_dual_hash_get(int unit, soc_mem_t mem, int hash_sel, int bank, 23051 void *entry_data) 23052 { 23053 switch (mem) { 23054 case L2Xm: 23055 #if defined(BCM_TRX_SUPPORT) 23056 if (SOC_IS_TRX(unit)) { 23057 return soc_tr_l2x_entry_hash(unit, hash_sel, entry_data); 23058 } else 23059 #endif 23060 { 23061 return soc_fb_l2x_entry_hash(unit, hash_sel, entry_data); 23062 } 23063 #if defined(INCLUDE_L3) 23064 case L3_ENTRY_IPV4_UNICASTm: 23065 case L3_ENTRY_IPV4_MULTICASTm: 23066 case L3_ENTRY_IPV6_UNICASTm: 23067 case L3_ENTRY_IPV6_MULTICASTm: 23068 return soc_fb_l3x_entry_hash(unit, hash_sel, entry_data); 23069 #endif /* INCLUDE_L3 */ 23070 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 23071 case VLAN_MACm: 23072 #if defined(BCM_TRIDENT2_SUPPORT) 23073 if (SOC_IS_TD2_TT2(unit)) { 23074 return soc_td2_vlan_xlate_entry_hash(unit, hash_sel, bank, entry_data); 23075 } else 23076 #endif 23077 if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 23078 return soc_fb_vlan_mac_entry_hash(unit, hash_sel, entry_data); 23079 } else { 23080 return -1; 23081 } 23082 #endif 23083 23084 #if defined(BCM_TRX_SUPPORT) 23085 case VLAN_XLATEm: 23086 #if defined(BCM_TRIDENT2_SUPPORT) 23087 if (SOC_IS_TD2_TT2(unit)) { 23088 #ifdef BCM_APACHE_SUPPORT 23089 if (SOC_IS_APACHE(unit)) { 23090 return soc_ap_vlan_xlate_entry_hash(unit, hash_sel, bank, 23091 entry_data); 23092 } else 23093 #endif /* BCM_APACHE_SUPPORT */ 23094 #ifdef BCM_TOMAHAWK_SUPPORT 23095 if (SOC_IS_TOMAHAWKX(unit)) { 23096 return soc_th_vlan_xlate_entry_hash(unit, hash_sel, bank, 23097 entry_data); 23098 } else 23099 #endif /* BCM_TOMAHAWK_SUPPORT */ 23100 { 23101 return soc_td2_vlan_xlate_entry_hash(unit, hash_sel, bank, 23102 entry_data); 23103 } 23104 } else 23105 #endif /* BCM_TRIDENT2_SUPPORT */ 23106 if (SOC_IS_TRX(unit)) { 23107 return soc_tr_vlan_xlate_entry_hash(unit, hash_sel, entry_data); 23108 } 23109 return -1; 23110 23111 case MPLS_ENTRYm: 23112 #if defined(BCM_TRIDENT2_SUPPORT) 23113 if (SOC_IS_TD2_TT2(unit)) { 23114 #ifdef BCM_APACHE_SUPPORT 23115 if (SOC_IS_APACHE(unit)) { 23116 return soc_ap_mpls_entry_hash(unit, hash_sel, bank, 23117 entry_data); 23118 } else 23119 #endif /* BCM_APACHE_SUPPORT */ 23120 #ifdef BCM_TOMAHAWK_SUPPORT 23121 if (SOC_IS_TOMAHAWKX(unit)) { 23122 #ifdef BCM_TOMAHAWK3_SUPPORT 23123 if (SOC_IS_TOMAHAWK3(unit)) { 23124 return soc_tomahawk3_mpls_bank_entry_hash(unit, bank, 23125 entry_data); 23126 } else 23127 #endif /* BCM_TOMAHAWK3_SUPPORT */ 23128 { 23129 return soc_th_mpls_entry_hash(unit, hash_sel, bank, 23130 entry_data); 23131 } 23132 } else 23133 #endif /* BCM_TOMAHAWK_SUPPORT */ 23134 { 23135 return soc_td2_mpls_entry_hash(unit, hash_sel, bank, entry_data); 23136 } 23137 } else 23138 #endif /* BCM_TRIDENT2_SUPPORT */ 23139 if (SOC_IS_TR_VL(unit)) { 23140 return soc_tr_mpls_entry_hash(unit, hash_sel, entry_data); 23141 } 23142 return -1; 23143 23144 case EGR_VLAN_XLATEm: 23145 #if defined(BCM_TRIDENT2_SUPPORT) 23146 if (SOC_IS_TD2_TT2(unit)) { 23147 #ifdef BCM_APACHE_SUPPORT 23148 if (SOC_IS_APACHE(unit)) { 23149 return soc_ap_egr_vlan_xlate_entry_hash(unit, hash_sel, 23150 bank, entry_data); 23151 } else 23152 #endif /* BCM_APACHE_SUPPORT */ 23153 #ifdef BCM_TOMAHAWK_SUPPORT 23154 if (SOC_IS_TOMAHAWKX(unit)) { 23155 return soc_th_egr_vlan_xlate_entry_hash(unit, hash_sel, 23156 bank, entry_data); 23157 } else 23158 #endif /* BCM_TOMAHAWK_SUPPORT */ 23159 { 23160 return soc_td2_egr_vlan_xlate_entry_hash(unit, hash_sel, 23161 bank, entry_data); 23162 } 23163 } else 23164 #endif /* BCM_TRIDENT2_SUPPORT */ 23165 if (SOC_IS_TRX(unit)) { 23166 return soc_tr_egr_vlan_xlate_entry_hash(unit, hash_sel, entry_data); 23167 } 23168 return -1; 23169 #endif 23170 23171 #ifdef BCM_TRIUMPH3_SUPPORT 23172 case AXP_WRX_WCDm: 23173 case AXP_WRX_SVP_ASSIGNMENTm: 23174 if (SOC_IS_TRIUMPH3(unit)) { 23175 return soc_tr3_wlan_entry_hash(unit, mem, hash_sel, entry_data); 23176 } 23177 return -1; 23178 case FT_SESSIONm: 23179 case FT_SESSION_IPV6m: 23180 if (SOC_IS_TRIUMPH3(unit)) { 23181 return soc_tr3_ft_session_entry_hash(unit, mem, hash_sel, entry_data); 23182 } 23183 return -1; 23184 #endif /* BCM_TRIUMPH3_SUPPORT */ 23185 23186 #ifdef BCM_TRIDENT2_SUPPORT 23187 case ING_VP_VLAN_MEMBERSHIPm: 23188 if (SOC_IS_TD2_TT2(unit)) { 23189 #ifdef BCM_HELIX5_SUPPORT 23190 if (SOC_IS_HELIX5(unit)) { 23191 return soc_hx5_ing_vp_vlan_member_bank_entry_hash(unit, bank, 23192 entry_data); 23193 } else 23194 #endif /* BCM_HELIX5_SUPPORT */ 23195 #ifdef BCM_TRIDENT3_SUPPORT 23196 if (SOC_IS_TRIDENT3X(unit)) { 23197 return soc_td3_ing_vp_vlan_member_bank_entry_hash(unit, bank, 23198 entry_data); 23199 } else 23200 #endif /* BCM_TRIDENT3_SUPPORT */ 23201 { 23202 return soc_td2_ing_vp_vlan_member_entry_hash(unit, hash_sel, bank, 23203 entry_data); 23204 } 23205 } 23206 return -1; 23207 case EGR_VP_VLAN_MEMBERSHIPm: 23208 if (SOC_IS_TD2_TT2(unit)) { 23209 #ifdef BCM_HELIX5_SUPPORT 23210 if (SOC_IS_HELIX5(unit)) { 23211 return soc_hx5_egr_vp_vlan_member_bank_entry_hash(unit, bank, 23212 entry_data); 23213 } else 23214 #endif /* BCM_HELIX5_SUPPORT */ 23215 #ifdef BCM_TRIDENT3_SUPPORT 23216 if (SOC_IS_TRIDENT3X(unit)) { 23217 return soc_td3_egr_vp_vlan_member_bank_entry_hash(unit, bank, 23218 entry_data); 23219 } else 23220 #endif /* BCM_TRIDENT3_SUPPORT */ 23221 { 23222 return soc_td2_egr_vp_vlan_member_entry_hash(unit, hash_sel, bank, 23223 entry_data); 23224 } 23225 } 23226 return -1; 23227 case ING_DNAT_ADDRESS_TYPEm: 23228 if (SOC_IS_TD2_TT2(unit)) { 23229 #ifdef BCM_TRIDENT3_SUPPORT 23230 if (SOC_IS_TRIDENT3X(unit)) { 23231 return soc_td3_ing_dnat_address_type_bank_entry_hash(unit, bank, 23232 entry_data); 23233 } else 23234 #endif /* BCM_TRIDENT3_SUPPORT */ 23235 { 23236 return soc_td2_ing_dnat_address_type_entry_hash(unit, hash_sel, bank, 23237 entry_data); 23238 } 23239 } 23240 return -1; 23241 case L2_ENDPOINT_IDm: 23242 if (SOC_IS_TD2_TT2(unit)) { 23243 #ifdef BCM_APACHE_SUPPORT 23244 if (SOC_IS_APACHE(unit)) { 23245 return soc_ap_l2_endpoint_id_entry_hash(unit, hash_sel, bank, 23246 entry_data); 23247 } else 23248 #endif /* BCM_APACHE_SUPPORT */ 23249 { 23250 return soc_td2_l2_endpoint_id_entry_hash(unit, hash_sel, bank, 23251 entry_data); 23252 } 23253 } 23254 return -1; 23255 case ENDPOINT_QUEUE_MAPm: 23256 if (SOC_IS_TD2_TT2(unit)) { 23257 #ifdef BCM_APACHE_SUPPORT 23258 if (SOC_IS_APACHE(unit)) { 23259 return soc_ap_endpoint_queue_map_entry_hash(unit, hash_sel, 23260 bank, entry_data); 23261 } else 23262 #endif /* BCM_APACHE_SUPPORT */ 23263 { 23264 return soc_td2_endpoint_queue_map_entry_hash(unit, hash_sel, 23265 bank, entry_data); 23266 } 23267 } 23268 return -1; 23269 #endif /* BCM_TRIDENT2_SUPPORT */ 23270 case SUBPORT_ID_TO_SGPP_MAPm: 23271 #ifdef BCM_TRIDENT3_SUPPORT 23272 if (SOC_IS_TRIDENT3X(unit)) { 23273 return soc_td3_subport_id_to_sgpp_map_bank_entry_hash(unit, bank, 23274 entry_data); 23275 } 23276 #endif /* BCM_TRIDENT3_SUPPORT */ 23277 return -1; 23278 23279 default: 23280 return -1; 23281 } 23282 } 23283 23284 /* 23285 * Function: 23286 * _soc_mem_dual_hash_move 23287 * Purpose: 23288 * Recursive move routine for dual hash auto-move inserts 23289 * Assumes feature already checked, mem locks taken. 23290 */ 23291 23292 STATIC int 23293 _soc_mem_dual_hash_move(int unit, soc_mem_t mem, /* Assumes memory locked */ 23294 uint8 banks, int copyno, void *entry_data, 23295 dual_hash_info_t *hash_info, 23296 SHR_BITDCL *bucket_trace, int recurse_depth, 23297 int recurse_in ) 23298 { 23299 int hash_base, cur_index = -1, base_index, bucket_index; 23300 int dest_hash_base, dest_bucket_index = -1; 23301 int half_bucket, hw_war = 0, trace_size = 0; 23302 SHR_BITDCL *trace; /* Buckets involved in recursion. */ 23303 int rv = SOC_E_NONE, bix, i, found = FALSE; 23304 uint8 this_bank_bit, this_bank_only, that_bank_only, this_hash, that_hash; 23305 uint32 move_entry[SOC_MAX_MEM_WORDS]; 23306 int recurse = recurse_in; 23307 23308 if (recurse_depth < 0) { 23309 return SOC_E_FULL; 23310 } 23311 if (((SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) || 23312 SOC_IS_SCORPION(unit) || SOC_IS_ENDURO(unit)) && 23313 (mem == EGR_VLAN_XLATEm)) || 23314 soc_feature(unit, soc_feature_hr2_dual_hash)) { 23315 /* Handle h/w limitation for this memory */ 23316 hw_war = TRUE; 23317 } 23318 /* Stack variables initialization & memory allocations.*/ 23319 half_bucket = hash_info->bucket_size / 2; 23320 23321 /* Keep back trace of all buckets affected by recursion. */ 23322 if (NULL == bucket_trace) { 23323 trace_size = 23324 SHR_BITALLOCSIZE(soc_mem_index_count(unit, hash_info->base_mem)/ 23325 half_bucket); 23326 trace = sal_alloc(trace_size, "Dual hash"); 23327 if (NULL == trace) { 23328 return (SOC_E_MEMORY); 23329 } 23330 recurse = 0; 23331 } else { 23332 trace = bucket_trace; 23333 recurse++; 23334 } 23335 23336 /* Iterate over banks. */ 23337 for (bix = 0; bix < 2; bix++) { 23338 this_bank_bit = 23339 (bix == 0) ? SOC_MEM_HASH_BANK0_BIT : SOC_MEM_HASH_BANK1_BIT; 23340 this_bank_only = 23341 (bix == 0) ? SOC_MEM_HASH_BANK0_ONLY : SOC_MEM_HASH_BANK1_ONLY; 23342 that_bank_only = 23343 (bix == 0) ? SOC_MEM_HASH_BANK1_ONLY : SOC_MEM_HASH_BANK0_ONLY; 23344 this_hash = (bix == 0) ? hash_info->hash_sel0 : hash_info->hash_sel1; 23345 that_hash = (bix == 0) ? hash_info->hash_sel1 : hash_info->hash_sel0; 23346 23347 if (banks & this_bank_bit) { 23348 /* Not this bank */ 23349 continue; 23350 } 23351 hash_base = _soc_mem_dual_hash_get(unit, mem, this_hash, bix, 23352 entry_data); 23353 if (hash_base == -1) { 23354 rv = SOC_E_INTERNAL; 23355 break; 23356 } 23357 23358 /* Bucket half is based on bank id. */ 23359 bucket_index = hash_base * hash_info->bucket_size + bix * half_bucket; 23360 23361 /* Recursion trace initialization. */ 23362 if (NULL == bucket_trace) { 23363 sal_memset(trace, 0, trace_size); 23364 } 23365 SHR_BITSET(trace, bucket_index/half_bucket); 23366 23367 /* Iterate over entries in the half-bucket.. */ 23368 for (i = 0; i < (hash_info->bucket_size / 2); i++) { 23369 cur_index = base_index = bucket_index + i; 23370 /* Read bucket entry. */ 23371 rv = soc_mem_read(unit, hash_info->base_mem, copyno, 23372 base_index, move_entry); 23373 if (SOC_FAILURE(rv)) { 23374 rv = SOC_E_MEMORY; 23375 break; 23376 } 23377 /* Is this an exception mem OR 23378 Are we already in recursion or will we be in recursion */ 23379 if (hw_war || recurse || recurse_depth) { 23380 /* Calculate destination entry hash value. */ 23381 dest_hash_base = _soc_mem_dual_hash_get(unit, mem, that_hash, 23382 !bix, move_entry); 23383 if (dest_hash_base == -1) { 23384 rv = SOC_E_INTERNAL; 23385 break; 23386 } 23387 dest_bucket_index = 23388 dest_hash_base * hash_info->bucket_size + (!bix) * half_bucket; 23389 23390 /* Make sure we are not touching buckets in bucket trace. */ 23391 if(SHR_BITGET(trace, dest_bucket_index/half_bucket)) { 23392 continue; 23393 } 23394 } 23395 23396 /* Attempt to insert it into the other bank. */ 23397 if (hw_war) { 23398 int e, notfound = TRUE; 23399 uint32 tmp_entry[SOC_MAX_MEM_WORDS]; 23400 23401 for (e = 0; e < (hash_info->bucket_size / 2); e++) { 23402 rv = soc_mem_read(unit, mem, copyno, 23403 dest_bucket_index + e, tmp_entry); 23404 if (SOC_FAILURE(rv)) { 23405 rv = SOC_E_MEMORY; 23406 break; 23407 } 23408 if (soc_mem_field32_get(unit, mem, tmp_entry, VALIDf)) { 23409 continue; 23410 } else { 23411 rv = soc_mem_write(unit, mem, copyno, dest_bucket_index + e, 23412 move_entry); 23413 if (SOC_FAILURE(rv)) { 23414 rv = SOC_E_MEMORY; 23415 break; 23416 } 23417 notfound = FALSE; 23418 break; 23419 } 23420 } 23421 if ((rv != SOC_E_MEMORY) && (notfound == TRUE)) { 23422 rv = SOC_E_FULL; 23423 } 23424 } else { 23425 rv = soc_mem_bank_insert(unit, mem, that_bank_only, 23426 copyno, move_entry, NULL); 23427 } 23428 if (SOC_FAILURE(rv)) { 23429 if (rv != SOC_E_FULL) { 23430 if ((rv == SOC_E_EXISTS) && 23431 bsl_check(bslLayerSoc, bslSourceCommon, 23432 bslSeverityVerbose, unit)) { 23433 soc_mem_entry_dump(unit, mem, move_entry, 23434 BSL_VERBOSE|BSL_LS_SOC_COMMON); 23435 } 23436 break; 23437 } 23438 /* Recursive call - attempt to create a slot 23439 in other bank bucket. */ 23440 rv = _soc_mem_dual_hash_move(unit, mem, that_bank_only, 23441 copyno, move_entry, hash_info, 23442 trace, recurse_depth - 1, 23443 recurse); 23444 if (SOC_FAILURE(rv)) { 23445 if (rv != SOC_E_FULL) { 23446 if ((rv == SOC_E_EXISTS) && 23447 bsl_check(bslLayerSoc, bslSourceCommon, 23448 bslSeverityVerbose, unit)) { 23449 soc_mem_entry_dump(unit, mem, move_entry, 23450 BSL_VERBOSE|BSL_LS_SOC_COMMON); 23451 } 23452 break; 23453 } 23454 continue; 23455 } 23456 } 23457 /* Entry was moved successfully. */ 23458 found = TRUE; 23459 /* Delete old entry from original location */ 23460 if (hw_war) { 23461 /* A entry clear is not needed as the entry is written over later on. 23462 soc_mem_field32_set(unit, mem, &move_entry, VALIDf, 0); 23463 rv = soc_mem_write(unit, mem, copyno, cur_index, move_entry); 23464 */ 23465 /* 23466 * For L2Xm, the related Limit count (System, Port/Trunk and 23467 * VLAN/VFI mac count) will be updated automatically through 23468 * normal L2 insert operation, the Limit count will not be 23469 * updated by calling soc_mem_write(). 23470 */ 23471 if (soc_feature(unit, soc_feature_hr2_dual_hash) && 23472 (mem == L2Xm)) { 23473 /* Clear the move_entry before L2 insert */ 23474 soc_mem_field32_set(unit, mem, &move_entry, VALIDf, 0); 23475 rv = soc_mem_write(unit, mem, copyno, 23476 cur_index, move_entry); 23477 } 23478 } else { 23479 rv = soc_mem_bank_delete(unit, mem, this_bank_only, MEM_BLOCK_ANY, 23480 move_entry, NULL); 23481 } 23482 break; 23483 } /* Bucket iteration loop. */ 23484 23485 if (found || ((rv < 0) && (rv != SOC_E_FULL))) { 23486 break; 23487 } 23488 } /* Bank iteration loop. */ 23489 23490 if ((rv < 0) && (rv != SOC_E_FULL)) { 23491 if (NULL == bucket_trace) sal_free(trace); 23492 return rv; 23493 } 23494 23495 if (!found) { 23496 if (NULL == bucket_trace) sal_free(trace); 23497 return SOC_E_FULL; 23498 } 23499 if (hw_war) { 23500 if (soc_feature(unit, soc_feature_hr2_dual_hash) && 23501 (mem == L2Xm)) { 23502 /* 23503 * For L2Xm, the related Limit count (System, Port/Trunk and 23504 * VLAN/VFI mac count) will be updated automatically through 23505 * normal L2 insert operation, the Limit count will not be 23506 * updated by calling soc_mem_write(). 23507 */ 23508 rv = soc_mem_bank_insert(unit, mem, this_bank_only, copyno, 23509 entry_data, NULL); 23510 } else { 23511 rv = soc_mem_write(unit, mem, copyno, cur_index, entry_data); 23512 } 23513 } else { 23514 rv = soc_mem_bank_insert(unit, mem, this_bank_only,copyno, 23515 entry_data, NULL); 23516 } 23517 if (NULL == bucket_trace) sal_free(trace); 23518 return (rv); 23519 } 23520 23521 /* 23522 * Function: 23523 * _soc_mem_dual_hash_insert 23524 * Purpose: 23525 * Dual hash auto-move inserts 23526 * Assumes feature already checked 23527 */ 23528 23529 int 23530 _soc_mem_dual_hash_insert(int unit, 23531 soc_mem_t mem, /* Assumes memory locked */ 23532 int copyno, 23533 void *entry_data, 23534 void *old_entry_data, 23535 int recurse_depth) 23536 { 23537 int rv = SOC_E_NONE; 23538 dual_hash_info_t hash_info = {0}; 23539 #ifdef BCM_TRIUMPH3_SUPPORT 23540 uint32 regval; 23541 #endif /* BCM_TRIUMPH3_SUPPORT */ 23542 23543 switch (mem) { 23544 case L2Xm: 23545 rv = soc_mem_bank_insert(unit, mem, 0, copyno, 23546 entry_data, old_entry_data); 23547 if (rv != SOC_E_FULL || recurse_depth == 0) { 23548 return rv; 23549 } 23550 SOC_IF_ERROR_RETURN 23551 (soc_fb_l2x_entry_bank_hash_sel_get(unit, 0, 23552 &(hash_info.hash_sel0))); 23553 SOC_IF_ERROR_RETURN 23554 (soc_fb_l2x_entry_bank_hash_sel_get(unit, 1, 23555 &(hash_info.hash_sel1))); 23556 if (hash_info.hash_sel0 == hash_info.hash_sel1) { 23557 /* Can't juggle the entries */ 23558 return SOC_E_FULL; 23559 } 23560 hash_info.bucket_size = SOC_L2X_BUCKET_SIZE; 23561 hash_info.base_mem = mem; 23562 23563 /* Time to shuffle the entries */ 23564 SOC_IF_ERROR_RETURN(soc_l2x_freeze(unit)); 23565 rv = _soc_mem_dual_hash_move(unit, mem, SOC_MEM_HASH_BANK_BOTH, 23566 copyno, entry_data, &hash_info, 23567 NULL, recurse_depth - 1,0); 23568 SOC_IF_ERROR_RETURN(soc_l2x_thaw(unit)); 23569 return rv; 23570 #ifdef BCM_TRX_SUPPORT 23571 case VLAN_XLATEm: 23572 if (!SOC_IS_TRX(unit)) { 23573 break; 23574 } 23575 /* Fall thru for TRX (VLAN_XLATE & VLAN_MAC are a shared table) */ 23576 #endif /* BCM_TRX_SUPPORT */ 23577 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRX_SUPPORT) 23578 case VLAN_MACm: 23579 if (SOC_IS_FIREBOLT2(unit)) { 23580 break; 23581 } 23582 rv = soc_mem_bank_insert(unit, mem, 0, copyno, 23583 entry_data, old_entry_data); 23584 if (rv != SOC_E_FULL || recurse_depth == 0) { 23585 return rv; 23586 } 23587 #ifdef BCM_TRX_SUPPORT 23588 if (mem == VLAN_XLATEm) { 23589 SOC_IF_ERROR_RETURN 23590 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info.hash_sel0)); 23591 SOC_IF_ERROR_RETURN 23592 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info.hash_sel1)); 23593 hash_info.bucket_size = SOC_VLAN_XLATE_BUCKET_SIZE; 23594 } else 23595 #endif /* BCM_TRX_SUPPORT */ 23596 { 23597 SOC_IF_ERROR_RETURN 23598 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &(hash_info.hash_sel0))); 23599 23600 SOC_IF_ERROR_RETURN 23601 (soc_fb_rv_vlanmac_hash_sel_get(unit, 1, &(hash_info.hash_sel1))); 23602 hash_info.bucket_size = SOC_VLAN_MAC_BUCKET_SIZE; 23603 } 23604 if (hash_info.hash_sel0 == hash_info.hash_sel1) { 23605 /* Can't juggle the entries */ 23606 return SOC_E_FULL; 23607 } 23608 hash_info.base_mem = mem; 23609 /* Time to shuffle the entries */ 23610 if (SOC_IS_TRX(unit)) { 23611 soc_mem_lock(unit, VLAN_XLATEm); 23612 } 23613 soc_mem_lock(unit, VLAN_MACm); 23614 rv = _soc_mem_dual_hash_move(unit, mem, SOC_MEM_HASH_BANK_BOTH, 23615 copyno, entry_data, &hash_info, 23616 NULL, recurse_depth - 1,0); 23617 soc_mem_unlock(unit, VLAN_MACm); 23618 if (SOC_IS_TRX(unit)) { 23619 soc_mem_unlock(unit, VLAN_XLATEm); 23620 } 23621 return rv; 23622 #endif /* BCM_RAVEN_SUPPORT || BCM_TRX_SUPPORT */ 23623 #if defined(INCLUDE_L3) 23624 case L3_ENTRY_ONLYm: 23625 case L3_ENTRY_IPV4_UNICASTm: 23626 case L3_ENTRY_IPV4_MULTICASTm: 23627 case L3_ENTRY_IPV6_UNICASTm: 23628 case L3_ENTRY_IPV6_MULTICASTm: 23629 return soc_fb_l3x_insert(unit, entry_data); 23630 #if defined(BCM_TOMAHAWK3_SUPPORT) 23631 case L3_TUNNEL_SINGLEm: 23632 case L3_TUNNEL_DOUBLEm: 23633 case L3_TUNNEL_QUADm: 23634 hash_info.bucket_size = SOC_L3_TUNNEL_BUCKET_SIZE; 23635 break; 23636 #endif /* BCM_TOMAHAWK3_SUPPORT */ 23637 #endif /* INCLUDE_L3 */ 23638 #if defined(BCM_TRX_SUPPORT) 23639 case MPLS_ENTRYm: 23640 hash_info.bucket_size = SOC_MPLS_ENTRY_BUCKET_SIZE; 23641 break; 23642 case EGR_VLAN_XLATEm: 23643 hash_info.bucket_size = SOC_EGR_VLAN_XLATE_BUCKET_SIZE; 23644 break; 23645 case AXP_WRX_WCDm: 23646 case AXP_WRX_SVP_ASSIGNMENTm: 23647 hash_info.bucket_size = SOC_WLAN_BUCKET_SIZE; 23648 break; 23649 #ifdef BCM_TRIUMPH3_SUPPORT 23650 case FT_SESSIONm: 23651 case FT_SESSION_IPV6m: 23652 SOC_IF_ERROR_RETURN(READ_FT_CONFIGr(unit, ®val)); 23653 hash_info.bucket_size = 1 << soc_reg_field_get(unit, 23654 FT_CONFIGr, regval, TABLE_SIZEf); 23655 break; 23656 #endif /* BCM_TRIUMPH3_SUPPORT */ 23657 #ifdef BCM_TRIDENT2_SUPPORT 23658 case ING_VP_VLAN_MEMBERSHIPm: 23659 hash_info.bucket_size = SOC_ING_VP_VLAN_MEMBER_BUCKET_SIZE; 23660 break; 23661 case EGR_VP_VLAN_MEMBERSHIPm: 23662 hash_info.bucket_size = SOC_EGR_VP_VLAN_MEMBER_BUCKET_SIZE; 23663 break; 23664 case ING_DNAT_ADDRESS_TYPEm: 23665 hash_info.bucket_size = SOC_ING_DNAT_ADDRESS_TYPE_BUCKET_SIZE; 23666 break; 23667 case L2_ENDPOINT_IDm: 23668 hash_info.bucket_size = SOC_L2_ENDPOINT_ID_BUCKET_SIZE; 23669 break; 23670 case ENDPOINT_QUEUE_MAPm: 23671 hash_info.bucket_size = SOC_ENDPOINT_QUEUE_MAP_BUCKET_SIZE; 23672 break; 23673 #ifdef BCM_TRIDENT3_SUPPORT 23674 case SUBPORT_ID_TO_SGPP_MAPm: 23675 hash_info.bucket_size = SOC_SUBPORT_ID_TO_SGPP_MAP_BUCKET_SIZE; 23676 break; 23677 #endif /* BCM_TRIDENT3_SUPPORT */ 23678 #endif /* BCM_TRIDENT2_SUPPORT */ 23679 #ifdef BCM_KATANA2_SUPPORT 23680 case EGR_MP_GROUPm: 23681 hash_info.bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE; 23682 break; 23683 #endif 23684 #ifdef BCM_SABER2_SUPPORT 23685 case MP_GROUPm: 23686 hash_info.bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE; 23687 break; 23688 #endif 23689 #endif /* BCM_TRX_SUPPORT */ 23690 default: 23691 return SOC_E_UNAVAIL; 23692 } 23693 23694 #if defined(BCM_TRX_SUPPORT) 23695 /* 23696 * If a block of physical memory is not shared by multiple table and 23697 * it is not modified by hardware, we should be able to use general case 23698 * for dual hash insert 23699 */ 23700 rv = soc_mem_bank_insert(unit, mem, 0, copyno, entry_data, old_entry_data); 23701 23702 if (rv != SOC_E_FULL || recurse_depth == 0) { 23703 return rv; 23704 } 23705 23706 #ifdef BCM_TRIDENT2_SUPPORT 23707 if (SOC_IS_TD2_TT2(unit)) { 23708 if ((!SOC_IS_TRIDENT3X(unit)) && (!SOC_IS_TOMAHAWK3(unit))) { 23709 SOC_IF_ERROR_RETURN 23710 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info.hash_sel0)); 23711 SOC_IF_ERROR_RETURN 23712 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info.hash_sel1)); 23713 } 23714 } else 23715 #endif /* BCM_TRIDENT2_SUPPORT */ 23716 { 23717 SOC_IF_ERROR_RETURN 23718 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info.hash_sel0)); 23719 SOC_IF_ERROR_RETURN 23720 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info.hash_sel1)); 23721 } 23722 if (hash_info.hash_sel0 == hash_info.hash_sel1) { 23723 /* Can't juggle the entries */ 23724 return SOC_E_FULL; 23725 } 23726 #if defined(BCM_TRIUMPH3_SUPPORT) 23727 if (mem == FT_SESSIONm || mem == FT_SESSION_IPV6m) { 23728 /* Can't juggle the entries - FT_SESSION entries don't move */ 23729 return SOC_E_FULL; 23730 } 23731 #endif /* BCM_TRIUMPH3_SUPPORT */ 23732 hash_info.base_mem = mem; 23733 /* Time to shuffle the entries */ 23734 soc_mem_lock(unit, mem); 23735 rv = _soc_mem_dual_hash_move(unit, mem, SOC_MEM_HASH_BANK_BOTH, copyno, 23736 entry_data, &hash_info, NULL, 23737 recurse_depth - 1,0); 23738 soc_mem_unlock(unit, mem); 23739 #endif /* BCM_TRX_SUPPORT */ 23740 23741 return rv; 23742 } 23743 23744 #ifdef BCM_ISM_SUPPORT 23745 /* 23746 * Function: 23747 * _soc_mem_multi_hash_insert 23748 * Purpose: 23749 * N hash auto-move inserts 23750 * Assumes feature already checked 23751 */ 23752 23753 STATIC int 23754 _soc_mem_multi_hash_insert(int unit, soc_mem_t mem, int copyno, 23755 void *entry_data, void *old_entry_data, 23756 int recurse_depth) 23757 { 23758 int rv = SOC_E_NONE; 23759 rv = soc_mem_bank_insert(unit, mem, SOC_MEM_HASH_BANK_ALL, copyno, 23760 entry_data, old_entry_data); 23761 if (rv != SOC_E_FULL) { 23762 return rv; 23763 } 23764 /* Time to shuffle the entries */ 23765 soc_mem_lock(unit, mem); 23766 rv = soc_mem_multi_hash_move(unit, mem, SOC_MEM_HASH_BANK_ALL, copyno, 23767 entry_data, NULL, NULL, recurse_depth-1); 23768 soc_mem_unlock(unit, mem); 23769 return rv; 23770 } 23771 #endif /* BCM_ISM_SUPPORT */ 23772 23773 #ifdef BCM_TRIDENT2_SUPPORT 23774 /*Function declaration */ 23775 23776 #define NUM_ENT 4 23777 #define NUM_ENT_TD3 16 23778 23779 typedef struct _soc_breadth_bucket2_s { 23780 int8 src_bix; 23781 int8 level; 23782 uint8 status; /* l3 only */ 23783 uint8 src_ent; 23784 23785 uint8 width[NUM_ENT]; /* l3 only */ 23786 soc_mem_t mem[NUM_ENT]; /*l3 only */ 23787 uint32 bucket; 23788 uint32 p_bucket; /* l3 only */ 23789 uint32 s_bucket; 23790 int n_bucket; 23791 union { 23792 l2x_entry_t l2[4]; 23793 #ifdef BCM_TRIDENT3_SUPPORT 23794 vlan_xlate_1_single_entry_t vlan[4]; 23795 egr_vlan_xlate_1_single_entry_t egr_vlan[4]; 23796 #endif /* BCM_TRIDENT3_SUPPORT */ 23797 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 23798 l3_entry_only_single_entry_t l3_single[4]; 23799 mpls_entry_single_entry_t mpls[4]; 23800 #endif /* BCM_TRIDENT3_SUPPORT || BCM_TOMAHAWK3_SUPPORT */ 23801 #ifdef BCM_TOMAHAWK3_SUPPORT 23802 mpls_entry_single_entry_t mpls_1[4]; 23803 #endif /* BCM_TOMAHAWK3_SUPPORT */ 23804 l3_entry_only_entry_t l3[4]; 23805 exact_match_2_entry_t em_2[4]; 23806 exact_match_4_entry_t em_4[4]; 23807 } e; 23808 } _soc_breadth_bucket2_t; 23809 23810 typedef struct _soc_breadth_bucket_s { 23811 soc_mem_t src_mem; 23812 uint8 src_bix; 23813 uint8 status; 23814 uint8 src_width; 23815 uint8 src_ent; 23816 uint32 src_bkt_idx; 23817 uint32 bucket; 23818 union { 23819 l2x_entry_t l2[4]; 23820 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 23821 l3_entry_only_single_entry_t l3_single[4]; 23822 l3_entry_quad_entry_t l3_quad[4]; 23823 mpls_entry_single_entry_t mpls[4]; 23824 #endif /* BCM_TRIDENT3_SUPPORT || BCM_TOMAHAWK3_SUPPORT */ 23825 #ifdef BCM_TRIDENT3_SUPPORT 23826 vlan_xlate_1_single_entry_t vlan[4]; 23827 egr_vlan_xlate_1_single_entry_t egr_vlan[4]; 23828 #endif 23829 #ifdef BCM_TOMAHAWK3_SUPPORT 23830 tunnel_quad_entry_t tunnel_quad[4]; 23831 #endif 23832 l3_entry_only_entry_t l3[4]; 23833 exact_match_2_entry_t em_2[4]; 23834 exact_match_4_entry_t em_4[4]; 23835 } e; 23836 } _soc_breadth_bucket_t; 23837 23838 STATIC INLINE int 23839 _soc_mem_shared_hash_init(int unit, soc_mem_t mem, 23840 SHR_BITDCL **trace, 23841 _soc_hash_bank_info_t *bank_info, 23842 int num_levels, 23843 _soc_breadth_bucket_t **buckets, 23844 _soc_breadth_bucket2_t **buckets2); 23845 23846 STATIC int 23847 _soc_mem_shared_hash_incr_per_entry(int unit, soc_mem_t mem, void *old_entry, 23848 void *new_entry) 23849 { 23850 if (mem == L2Xm) { 23851 return 1; 23852 } else { 23853 int oi = 1; 23854 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) { 23855 int key_type; 23856 23857 key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm, 23858 old_entry, KEY_TYPEf); 23859 switch (key_type) { 23860 case TD2_L3_HASH_KEY_TYPE_V4UC: 23861 case TD2_L3_HASH_KEY_TYPE_TRILL: 23862 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 23863 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 23864 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 23865 oi = 1; 23866 break; 23867 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 23868 case TD2_L3_HASH_KEY_TYPE_V4MC: 23869 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 23870 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 23871 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 23872 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 23873 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 23874 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 23875 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 23876 case TD2_L3_HASH_KEY_TYPE_V6UC: 23877 oi = 2; 23878 break; 23879 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 23880 case TD2_L3_HASH_KEY_TYPE_V6MC: 23881 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 23882 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 23883 oi = 4; 23884 break; 23885 default: 23886 oi = 1; 23887 } 23888 key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm, 23889 new_entry, KEY_TYPEf); 23890 switch (key_type) { 23891 case TD2_L3_HASH_KEY_TYPE_V4UC: 23892 case TD2_L3_HASH_KEY_TYPE_TRILL: 23893 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 23894 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 23895 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 23896 return oi; 23897 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 23898 case TD2_L3_HASH_KEY_TYPE_V4MC: 23899 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 23900 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 23901 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 23902 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 23903 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 23904 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 23905 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 23906 case TD2_L3_HASH_KEY_TYPE_V6UC: 23907 return (oi > 2) ? 2 : 1; 23908 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 23909 case TD2_L3_HASH_KEY_TYPE_V6MC: 23910 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 23911 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 23912 return 1; 23913 default: 23914 return (oi > 1) ? oi : 1; 23915 } 23916 } else { 23917 return 1; 23918 } 23919 } 23920 } 23921 23922 /* return values: 23923 * 0: equals, 23924 * 1, 2, 4, wider times, old_entry>new_entry . 23925 * -1, old_entry<new_entry 23926 */ 23927 STATIC int 23928 _soc_mem_shared_hash_entry_wide_cmp(int unit, soc_mem_t mem, void *old_entry, 23929 void *new_entry, soc_mem_t *wider_mem) 23930 { 23931 int oi = 1; 23932 int ni = 1; 23933 23934 *wider_mem = mem; 23935 if (mem == L2Xm) { 23936 return 0; 23937 } 23938 23939 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) { 23940 int key_type, key_type2; 23941 23942 key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm, 23943 old_entry, KEY_TYPEf); 23944 switch (key_type) { 23945 case TD2_L3_HASH_KEY_TYPE_V4UC: 23946 case TD2_L3_HASH_KEY_TYPE_TRILL: 23947 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 23948 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 23949 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 23950 oi = 1; 23951 break; 23952 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 23953 case TD2_L3_HASH_KEY_TYPE_V4MC: 23954 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 23955 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 23956 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 23957 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 23958 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 23959 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 23960 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 23961 case TD2_L3_HASH_KEY_TYPE_V6UC: 23962 oi = 2; 23963 break; 23964 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 23965 case TD2_L3_HASH_KEY_TYPE_V6MC: 23966 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 23967 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 23968 oi = 4; 23969 break; 23970 default: 23971 oi = 1; 23972 } 23973 key_type2 = soc_mem_field32_get(unit, L3_ENTRY_ONLYm, 23974 new_entry, KEY_TYPEf); 23975 switch (key_type2) { 23976 case TD2_L3_HASH_KEY_TYPE_V4UC: 23977 case TD2_L3_HASH_KEY_TYPE_TRILL: 23978 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 23979 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 23980 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 23981 ni = 1; 23982 break; 23983 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 23984 case TD2_L3_HASH_KEY_TYPE_V4MC: 23985 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 23986 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 23987 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 23988 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 23989 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 23990 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 23991 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 23992 case TD2_L3_HASH_KEY_TYPE_V6UC: 23993 ni = 2; 23994 break; 23995 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 23996 case TD2_L3_HASH_KEY_TYPE_V6MC: 23997 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 23998 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 23999 ni = 4; 24000 break; 24001 default: 24002 ni = 1; 24003 } 24004 24005 if (oi == ni) { 24006 return 0; 24007 } else if (oi < ni) { 24008 return -1; 24009 } else { /* (oi > ni) */ 24010 if (oi == 2) { 24011 *wider_mem = L3_ENTRY_IPV4_MULTICASTm; 24012 } else if (oi == 4) { 24013 *wider_mem = L3_ENTRY_IPV6_MULTICASTm; 24014 } 24015 return oi / ni; 24016 } 24017 } 24018 24019 return 0; 24020 } 24021 24022 STATIC int 24023 _soc_mem_shared_hash_narrower_move_allowed(int v0, int v1, int v2, int v3, 24024 soc_mem_t *mem, int *index, int offset) 24025 { 24026 int entry_num = v0 + v1 + v2 + v3; 24027 int double_wide_upper_num = v0 + v1; 24028 int double_wide_lower_num = v2 + v3; 24029 soc_mem_t ori_mem = *mem; 24030 int ori_idx = *index + offset; 24031 int index_offset = 0; 24032 24033 switch (ori_mem) { 24034 case L3_ENTRY_IPV6_MULTICASTm: 24035 if (entry_num == 1) { 24036 index_offset = v0 ? 0 : (v1 ? 1 : (v2 ? 2 : (v3 ? 3 : 0))); 24037 *mem = L3_ENTRY_IPV4_UNICASTm; 24038 *index = ori_idx * 4 + index_offset; 24039 return 1; 24040 } else if (entry_num == 2) { 24041 if (double_wide_upper_num == 2 || double_wide_lower_num == 2) { 24042 index_offset = double_wide_upper_num ? 0 : 1; 24043 /* L3_ENTRY_IPV4_UNICASTm can be treated as V4_MULTICAST */ 24044 *mem = L3_ENTRY_IPV4_MULTICASTm; 24045 *index = ori_idx * 2 + index_offset; 24046 return 1; 24047 } 24048 } 24049 break; 24050 case L3_ENTRY_IPV6_UNICASTm: 24051 case L3_ENTRY_IPV4_MULTICASTm: 24052 if (entry_num == 1) { 24053 index_offset = v0 ? 0 : 1; 24054 *mem = L3_ENTRY_IPV4_UNICASTm; 24055 *index = ori_idx * 2 + index_offset; 24056 return 1; 24057 } 24058 break; 24059 default: 24060 /* no entry narrower than L3_ENTRY_IPV4_UNICASTm */ 24061 return 0; 24062 } 24063 24064 return 0; 24065 } 24066 24067 STATIC int 24068 _soc_mem_shared_hash_move(int unit, soc_mem_t mem, int32 banks, int copyno, 24069 void *entry, SHR_BITDCL *bucket_trace, 24070 int recurse_depth,_soc_hash_bank_info_t *bank_info) 24071 { 24072 SHR_BITDCL *trace = NULL; 24073 _soc_hash_bank_info_t bank_inf = {0}; 24074 uint8 num_ent = 0; 24075 int32 nbix, cbix; 24076 int rv = SOC_E_NONE, cmp_rv, index, ori_index; 24077 uint8 i, bix, found = 0, cb = 0; 24078 uint32 db, dest_bucket; 24079 uint32 bucket, move_entry[SOC_MAX_MEM_WORDS]; 24080 soc_mem_t wider_mem, ori_mem = mem; 24081 int banks_seq_num = 0; 24082 24083 if (recurse_depth < 0) { 24084 return SOC_E_FULL; 24085 } 24086 /* Get the entry number per each bucket */ 24087 num_ent = _soc_mem_shared_hash_entries_per_bkt(unit, mem); 24088 24089 /* Stack variables initialization & memory allocations */ 24090 if (NULL == bucket_trace) { 24091 SOC_IF_ERROR_RETURN( 24092 _soc_mem_shared_hash_init(unit, mem, &trace, &bank_inf, 0, NULL, NULL)); 24093 } else { 24094 trace = bucket_trace; 24095 if (NULL != bank_info) { 24096 sal_memcpy(&bank_inf, bank_info, sizeof(_soc_hash_bank_info_t)); 24097 } else { 24098 rv = SOC_E_INTERNAL; 24099 goto clean_up; 24100 } 24101 } 24102 24103 if (banks != SOC_MEM_HASH_BANK_ALL) { 24104 #ifdef BCM_APACHE_SUPPORT 24105 if (SOC_IS_APACHE(unit)) { 24106 rv = soc_apache_hash_seq_number_get(unit, mem, banks, 24107 &banks_seq_num); 24108 } else 24109 #endif /* BCM_APACHE_SUPPORT */ 24110 #ifdef BCM_TOMAHAWK_SUPPORT 24111 if (SOC_IS_TOMAHAWKX(unit)) { 24112 #ifdef BCM_TOMAHAWK3_SUPPORT 24113 if (SOC_IS_TOMAHAWK3(unit)) { 24114 rv = soc_tomahawk3_hash_seq_number_get(unit, mem, banks, 24115 &banks_seq_num); 24116 } else 24117 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24118 { 24119 rv = soc_tomahawk_hash_seq_number_get(unit, mem, banks, 24120 &banks_seq_num); 24121 } 24122 } else 24123 #endif /* BCM_TOMAHAWK_SUPPORT */ 24124 #ifdef BCM_HELIX5_SUPPORT 24125 if (SOC_IS_HELIX5(unit)) { 24126 rv = soc_hx5_hash_seq_number_get(unit, mem, banks, &banks_seq_num); 24127 } else 24128 #endif /* BCM_HELIX5_SUPPORT */ 24129 #ifdef BCM_TRIDENT3_SUPPORT 24130 if (SOC_IS_TRIDENT3X(unit)) { 24131 rv = soc_td3_hash_seq_number_get(unit, mem, banks, &banks_seq_num); 24132 } else 24133 #endif /* BCM_TRIDENT3_SUPPORT */ 24134 { 24135 rv = soc_trident2_hash_seq_number_get(unit, mem, banks, 24136 &banks_seq_num); 24137 } 24138 if (SOC_FAILURE(rv)) { 24139 goto clean_up; 24140 } 24141 } else { 24142 /* Make sure we will try from the first bank */ 24143 banks_seq_num = -1; 24144 } 24145 24146 /* Iterate over banks. */ 24147 for (bix = 0; bix < bank_inf.num_banks; bix++) { 24148 /* if banks is present, try interate from next bank */ 24149 cbix = banks_seq_num + bix + 1; 24150 cbix = cbix % bank_inf.num_banks; 24151 cb = bank_inf.bank_nums[cbix]; 24152 if (banks == cb) { 24153 /* Not this bank */ 24154 continue; 24155 } 24156 nbix = (cbix + 1) % bank_inf.num_banks; /* next bank index */ 24157 db = bank_inf.bank_nums[nbix]; /* next destination bank */ 24158 #ifdef BCM_APACHE_SUPPORT 24159 if (SOC_IS_APACHE(unit)) { 24160 rv = soc_ap_hash_bucket_get(unit, mem, cb, entry, &bucket); 24161 } else 24162 #endif /* BCM_APACHE_SUPPORT */ 24163 #ifdef BCM_TOMAHAWK_SUPPORT 24164 if (SOC_IS_TOMAHAWKX(unit)) { 24165 #ifdef BCM_TOMAHAWK3_SUPPORT 24166 if (SOC_IS_TOMAHAWK3(unit)) { 24167 rv = soc_tomahawk3_hash_bucket_get(unit, mem, cb, entry, &bucket); 24168 } else 24169 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24170 { 24171 rv = soc_th_hash_bucket_get(unit, mem, cb, entry, &bucket); 24172 } 24173 } else 24174 #endif /* BCM_TOMAHAWK_SUPPORT */ 24175 #ifdef BCM_HELIX5_SUPPORT 24176 if (SOC_IS_HELIX5(unit)) { 24177 rv = soc_hx5_hash_bucket_get(unit, mem, cb, entry, &bucket); 24178 } else 24179 #endif /* BCM_HELIX5_SUPPORT */ 24180 #ifdef BCM_TRIDENT3_SUPPORT 24181 if (SOC_IS_TRIDENT3X(unit)) { 24182 rv = soc_td3_hash_bucket_get(unit, mem, cb, entry, &bucket); 24183 } else 24184 #endif /* BCM_TRIDENT3_SUPPORT */ 24185 { 24186 rv = soc_hash_bucket_get(unit, mem, cb, entry, &bucket); 24187 } 24188 if (SOC_FAILURE(rv)) { 24189 break; 24190 } 24191 SHR_BITSET(trace, (bank_inf.numb * cbix) + bucket); 24192 #ifdef BCM_APACHE_SUPPORT 24193 if (SOC_IS_APACHE(unit)) { 24194 index = soc_ap_hash_index_get(unit, mem, cb, bucket); 24195 } else 24196 #endif /* BCM_APACHE_SUPPORT */ 24197 #ifdef BCM_TOMAHAWK_SUPPORT 24198 if (SOC_IS_TOMAHAWKX(unit)) { 24199 #ifdef BCM_TOMAHAWK3_SUPPORT 24200 if (SOC_IS_TOMAHAWK3(unit)) { 24201 index = soc_tomahawk3_hash_index_get(unit, mem, cb, bucket); 24202 } else 24203 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24204 { 24205 index = soc_th_hash_index_get(unit, mem, cb, bucket); 24206 } 24207 } else 24208 #endif /* BCM_TOMAHAWK_SUPPORT */ 24209 #ifdef BCM_HELIX5_SUPPORT 24210 if (SOC_IS_HELIX5(unit)) { 24211 index = soc_hx5_hash_index_get(unit, mem, cb, bucket); 24212 } else 24213 #endif /* BCM_HELIX5_SUPPORT */ 24214 #ifdef BCM_TRIDENT3_SUPPORT 24215 if (SOC_IS_TRIDENT3X(unit)) { 24216 index = soc_td3_hash_index_get(unit, mem, cb, bucket); 24217 } else 24218 #endif /* BCM_TRIDENT3_SUPPORT */ 24219 { 24220 index = soc_hash_index_get(unit, mem, cb, bucket); 24221 } 24222 ori_index = index; 24223 for (i = 0; i < num_ent;) { 24224 uint32 v0, v1, v2, v3; 24225 soc_field_t fld_vld = VALIDf; 24226 if (mem == L2Xm && 24227 soc_feature(unit, soc_feature_base_valid)) { 24228 fld_vld = BASE_VALIDf; 24229 } 24230 rv = soc_mem_read(unit, mem, copyno, index+i, move_entry); 24231 if (SOC_FAILURE(rv)) { 24232 rv = SOC_E_MEMORY; 24233 break; 24234 } 24235 24236 /* Could be an empty slot here */ 24237 v0 = v1 = v2 = v3 = 0; 24238 switch (mem) { 24239 case L3_ENTRY_IPV6_MULTICASTm: 24240 soc_mem_field_get(unit, mem, move_entry, VALID_3f, &v3); 24241 soc_mem_field_get(unit, mem, move_entry, VALID_2f, &v2); 24242 /* pass through */ 24243 case L3_ENTRY_IPV6_UNICASTm: 24244 case L3_ENTRY_IPV4_MULTICASTm: 24245 soc_mem_field_get(unit, mem, move_entry, VALID_1f, &v1); 24246 soc_mem_field_get(unit, mem, move_entry, VALID_0f, &v0); 24247 break; 24248 case L3_ENTRY_IPV4_UNICASTm: 24249 case L3_ENTRY_ONLYm: 24250 case L2Xm: 24251 soc_mem_field_get(unit, mem, move_entry, fld_vld, &v0); 24252 break; 24253 default: 24254 v0 = v1 = v2 = v3 = 1; 24255 break; 24256 } 24257 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24258 (BSL_META_U(unit, 24259 "Depth %d, 1st read %d index %d from bank %d bucket %d(%d %d %d %d)\n"), 24260 recurse_depth, mem, index+i, cb, bucket, 24261 v0, v1, v2, v3)); 24262 24263 if (!(v0 || v1 || v2 || v3)) { 24264 found = TRUE; 24265 break; 24266 } 24267 24268 cmp_rv = _soc_mem_shared_hash_entry_wide_cmp(unit, mem, move_entry, 24269 entry, &wider_mem); 24270 if (cmp_rv == 0) { 24271 /* Are we already in recursion or will we be in recursion */ 24272 if (recurse_depth) { 24273 /* Calculate destination entry hash value. */ 24274 #ifdef BCM_APACHE_SUPPORT 24275 if (SOC_IS_APACHE(unit)) { 24276 (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry, 24277 &dest_bucket); 24278 } else 24279 #endif /* BCM_APACHE_SUPPORT */ 24280 #ifdef BCM_TOMAHAWK_SUPPORT 24281 if (SOC_IS_TOMAHAWKX(unit)) { 24282 #ifdef BCM_TOMAHAWK3_SUPPORT 24283 if (SOC_IS_TOMAHAWK3(unit)) { 24284 (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry, 24285 &dest_bucket); 24286 } else 24287 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24288 { 24289 (void)soc_th_hash_bucket_get(unit, mem, db, move_entry, 24290 &dest_bucket); 24291 } 24292 } else 24293 #endif /* BCM_TOMAHAWK_SUPPORT */ 24294 #ifdef BCM_HELIX5_SUPPORT 24295 if (SOC_IS_HELIX5(unit)) { 24296 (void)soc_hx5_hash_bucket_get(unit, mem, db, move_entry, 24297 &dest_bucket); 24298 } else 24299 #endif /* BCM_HELIX5_SUPPORT */ 24300 #ifdef BCM_TRIDENT3_SUPPORT 24301 if (SOC_IS_TRIDENT3X(unit)) { 24302 (void)soc_td3_hash_bucket_get(unit, mem, db, move_entry, 24303 &dest_bucket); 24304 } else 24305 #endif /* BCM_TRIDENT3_SUPPORT */ 24306 { 24307 (void)soc_hash_bucket_get(unit, mem, db, move_entry, &dest_bucket); 24308 } 24309 24310 if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) { 24311 /* Try next entry in the same bucket */ 24312 i++; 24313 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24314 (BSL_META_U(unit, 24315 " Skip(1) bank %d bucket %d, go to bank %d index %d\n"), 24316 db, dest_bucket, cb, index+i)); 24317 continue; 24318 } 24319 } 24320 } 24321 24322 if (cmp_rv < 0) { 24323 if (_soc_mem_shared_hash_narrower_move_allowed(v0, v1, v2, v3, 24324 &mem, &index, i)) { 24325 if (SOC_FAILURE(soc_mem_read(unit, mem, copyno, index, 24326 move_entry))) { 24327 rv = SOC_E_MEMORY; 24328 mem = ori_mem; 24329 break; 24330 } 24331 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24332 (BSL_META_U(unit, 24333 "Depth %d, L-2nd read %d index %d from bank %d bucket %d\n"), 24334 recurse_depth, mem, index, cb, bucket)); 24335 /* Are we already in recursion or will we be in recursion */ 24336 if (recurse_depth) { 24337 /* Calculate destination entry hash value. */ 24338 #ifdef BCM_APACHE_SUPPORT 24339 if (SOC_IS_APACHE(unit)) { 24340 (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry, 24341 &dest_bucket); 24342 } else 24343 #endif /* BCM_APACHE_SUPPORT */ 24344 #ifdef BCM_TOMAHAWK_SUPPORT 24345 if (SOC_IS_TOMAHAWKX(unit)) { 24346 #ifdef BCM_TOMAHAWK3_SUPPORT 24347 if (SOC_IS_TOMAHAWK3(unit)) { 24348 (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry, 24349 &dest_bucket); 24350 } else 24351 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24352 { 24353 (void)soc_th_hash_bucket_get(unit, mem, db, move_entry, 24354 &dest_bucket); 24355 } 24356 } else 24357 #endif /* BCM_TOMAHAWK_SUPPORT */ 24358 #ifdef BCM_HELIX5_SUPPORT 24359 if (SOC_IS_HELIX5(unit)) { 24360 (void)soc_hx5_hash_bucket_get(unit, mem, db, 24361 move_entry, &dest_bucket); 24362 } else 24363 #endif /* BCM_HELIX5_SUPPORT */ 24364 #ifdef BCM_TRIDENT3_SUPPORT 24365 if (SOC_IS_TRIDENT3X(unit)) { 24366 (void)soc_td3_hash_bucket_get(unit, mem, db, 24367 move_entry, &dest_bucket); 24368 } else 24369 #endif /* BCM_TRIDENT3_SUPPORT */ 24370 { 24371 (void)soc_hash_bucket_get(unit, mem, db, move_entry, 24372 &dest_bucket); 24373 } 24374 if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) { 24375 /* Try next entry in the same bucket in original 24376 * memory view */ 24377 mem = ori_mem; 24378 index = ori_index; 24379 i++; 24380 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24381 (BSL_META_U(unit, 24382 " Skip(2) bank %d bucket %d, go to mem %d " \ 24383 "bank %d index %d \n"), 24384 db, dest_bucket, mem, i >= num_ent ? db : cb, 24385 i >= num_ent ? -1 : (index+i))); 24386 continue; 24387 } 24388 } 24389 } else { 24390 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24391 (BSL_META_U(unit, 24392 "Depth %d, Existing entry width is narrower, but can't move\n"), 24393 recurse_depth)); 24394 rv = SOC_E_NONE; 24395 break; 24396 } 24397 } 24398 24399 /* wider entry */ 24400 if (cmp_rv > 0) { 24401 mem = wider_mem; 24402 index = (index + i) / cmp_rv; 24403 rv = soc_mem_read(unit, mem, copyno, index, move_entry); 24404 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24405 (BSL_META_U(unit, 24406 "Depth %d, G-2nd read %d index %d from bank %d bucket %d\n"), 24407 recurse_depth, mem, index, cb, bucket)); 24408 if (SOC_FAILURE(rv)) { 24409 rv = SOC_E_MEMORY; 24410 mem = ori_mem; 24411 break; 24412 } 24413 /* Are we already in recursion or will we be in recursion */ 24414 if (recurse_depth) { 24415 /* Calculate destination entry hash value. */ 24416 #ifdef BCM_APACHE_SUPPORT 24417 if (SOC_IS_APACHE(unit)) { 24418 (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry, 24419 &dest_bucket); 24420 } else 24421 #endif /* BCM_APACHE_SUPPORT */ 24422 #ifdef BCM_TOMAHAWK_SUPPORT 24423 if (SOC_IS_TOMAHAWKX(unit)) { 24424 #ifdef BCM_TOMAHAWK3_SUPPORT 24425 if (SOC_IS_TOMAHAWK3(unit)) { 24426 (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry, 24427 &dest_bucket); 24428 } else 24429 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24430 { 24431 (void)soc_th_hash_bucket_get(unit, mem, db, move_entry, 24432 &dest_bucket); 24433 } 24434 } else 24435 #endif /* BCM_TOMAHAWK_SUPPORT */ 24436 #ifdef BCM_HELIX5_SUPPORT 24437 if (SOC_IS_HELIX5(unit)) { 24438 (void)soc_hx5_hash_bucket_get(unit, mem, db, move_entry, 24439 &dest_bucket); 24440 } else 24441 #endif /* BCM_HELIX5_SUPPORT */ 24442 #ifdef BCM_TRIDENT3_SUPPORT 24443 if (SOC_IS_TRIDENT3X(unit)) { 24444 (void)soc_td3_hash_bucket_get(unit, mem, db, move_entry, 24445 &dest_bucket); 24446 } else 24447 #endif /* BCM_TRIDENT3_SUPPORT */ 24448 { 24449 (void)soc_hash_bucket_get(unit, mem, db, move_entry, 24450 &dest_bucket); 24451 } 24452 if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) { 24453 /* Determine bucket offset increment based upon 24454 * existing entry type/size */ 24455 mem = ori_mem; 24456 index = ori_index; 24457 i += _soc_mem_shared_hash_incr_per_entry(unit, mem, 24458 move_entry, entry); 24459 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24460 (BSL_META_U(unit, 24461 " Skip(3) bank %d bucket %d, go to bank %d index %d\n"), 24462 db, dest_bucket, cb, index+i)); 24463 continue; 24464 } 24465 } 24466 } 24467 24468 /* Attempt to insert it into the other bank. */ 24469 rv = soc_mem_bank_insert(unit, mem, (uint32)1<<db, copyno, move_entry, NULL); 24470 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24471 (BSL_META_U(unit, 24472 "Depth %d, trying to insert %d index %d to bank %d\n"), 24473 recurse_depth, mem, index, db)); 24474 if (SOC_FAILURE(rv)) { 24475 if (rv != SOC_E_FULL) { 24476 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24477 (BSL_META_U(unit, 24478 " But failed, rv %s, ori_mem %d\n"), soc_errmsg(rv), ori_mem)); 24479 mem = ori_mem; 24480 break; 24481 } 24482 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24483 (BSL_META_U(unit, 24484 " But bank is full, insert failed, will do recurse\n"))); 24485 /* Recursive call - attempt to create a slot 24486 in another bank's bucket. */ 24487 rv = _soc_mem_shared_hash_move(unit, mem, cb, copyno, 24488 move_entry, trace, 24489 recurse_depth - 1,&bank_inf); 24490 if (SOC_FAILURE(rv)) { 24491 if (rv != SOC_E_FULL) { 24492 break; 24493 } 24494 mem = ori_mem; 24495 index = ori_index; 24496 i += _soc_mem_shared_hash_incr_per_entry(unit, mem, 24497 move_entry, entry); 24498 continue; 24499 } 24500 } 24501 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24502 (BSL_META_U(unit, 24503 " Insert successfully\n"))); 24504 /* Entry was moved successfully. */ 24505 found = TRUE; 24506 /* Delete old entry from original location */ 24507 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24508 (BSL_META_U(unit, 24509 "Depth %d, trying to delete %d index %d from bank %d\n"), 24510 recurse_depth, mem, index, cb)); 24511 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, (uint32)1<<cb, 24512 move_entry, NULL, NULL); 24513 mem = ori_mem; 24514 break; 24515 } /* Bucket iteration loop. */ 24516 if (found || ((rv < 0) && (rv != SOC_E_FULL))) { 24517 break; 24518 } 24519 } /* Bank iteration loop. */ 24520 if ((rv < 0) && (rv != SOC_E_FULL)) { 24521 if (NULL == bucket_trace) { 24522 sal_free(trace); 24523 } 24524 return rv; 24525 } 24526 if (!found) { 24527 if (NULL == bucket_trace) { 24528 sal_free(trace); 24529 } 24530 return SOC_E_FULL; 24531 } 24532 rv = soc_mem_generic_insert(unit, mem, copyno, (uint32)1<<cb, entry, entry, NULL); 24533 if (rv) { 24534 LOG_VERBOSE(BSL_LS_SOC_COMMON, 24535 (BSL_META_U(unit, 24536 "Insert entry: %d\n"), rv)); 24537 } 24538 clean_up: 24539 if (NULL == bucket_trace) { 24540 sal_free(trace); 24541 } 24542 return rv; 24543 } 24544 24545 24546 STATIC INLINE void 24547 _soc_mem_shared_hash_l3_bucket_read(int unit, int ent, int key_type, int *width, 24548 soc_mem_t *mem, void *bkt_entry, void *entry) 24549 { 24550 24551 soc_mem_info_t meminfo; 24552 soc_field_info_t fieldinfo; 24553 /* Exclude HIT bit */ 24554 int entry_bits; 24555 24556 switch (key_type) { 24557 case TD2_L3_HASH_KEY_TYPE_V4UC: 24558 case TD2_L3_HASH_KEY_TYPE_TRILL: 24559 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 24560 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 24561 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 24562 *width = 1; 24563 *mem = L3_ENTRY_IPV4_UNICASTm; 24564 break; 24565 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 24566 case TD2_L3_HASH_KEY_TYPE_V4MC: 24567 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 24568 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 24569 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 24570 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 24571 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 24572 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 24573 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 24574 case TD2_L3_HASH_KEY_TYPE_V6UC: 24575 *width = 2; 24576 *mem = L3_ENTRY_IPV4_MULTICASTm; 24577 break; 24578 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 24579 case TD2_L3_HASH_KEY_TYPE_V6MC: 24580 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 24581 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 24582 default: 24583 *width = 4; 24584 *mem = L3_ENTRY_IPV6_MULTICASTm; 24585 sal_memcpy(entry, bkt_entry, sizeof(l3_entry_ipv6_multicast_entry_t)); 24586 return; 24587 } 24588 entry_bits = (soc_mem_entry_bits(unit, L3_ENTRY_IPV4_UNICASTm) - 1) * (*width); 24589 24590 meminfo.flags = 0; 24591 meminfo.bytes = SOC_MEM_WORDS(unit, L3_ENTRY_IPV6_MULTICASTm) * 4; 24592 fieldinfo.flags = SOCF_LE; 24593 fieldinfo.bp = entry_bits * (ent / *width); 24594 fieldinfo.len = entry_bits; 24595 24596 (void)soc_meminfo_fieldinfo_field_get(bkt_entry, &meminfo, 24597 &fieldinfo, entry); 24598 24599 } 24600 24601 #define SRAM_ENTRIES_PER_BUCKET 2 24602 #define SRAM_ENTRIES_PER_BUCKET_EM_2 2 24603 #define SRAM_ENTRIES_PER_BUCKET_EM_4 4 24604 24605 #define MEM_IS_EXACT_MATCH_2(mem) (EXACT_MATCH_2m == mem || \ 24606 EXACT_MATCH_2_PIPE0m == mem || \ 24607 EXACT_MATCH_2_PIPE1m == mem || \ 24608 EXACT_MATCH_2_PIPE2m == mem || \ 24609 EXACT_MATCH_2_PIPE3m == mem) 24610 #define MEM_IS_EXACT_MATCH_4(mem) (EXACT_MATCH_4m == mem || \ 24611 EXACT_MATCH_4_PIPE0m == mem || \ 24612 EXACT_MATCH_4_PIPE1m == mem || \ 24613 EXACT_MATCH_4_PIPE2m == mem || \ 24614 EXACT_MATCH_4_PIPE3m == mem) 24615 24616 #define MEM_IS_L3_ENTRY_SINGLE(mem) (L3_ENTRY_SINGLEm == mem) 24617 #define MEM_IS_L3_ENTRY_DOUBLE(mem) (L3_ENTRY_DOUBLEm == mem) 24618 #define MEM_IS_L3_ENTRY_QUAD(mem) (L3_ENTRY_QUADm == mem) 24619 24620 #define MEM_IS_VLAN_XLATE(mem) (VLAN_XLATE_1_SINGLEm == mem || \ 24621 VLAN_XLATE_1_DOUBLEm == mem || \ 24622 VLAN_XLATE_2_SINGLEm == mem || \ 24623 VLAN_XLATE_2_DOUBLEm == mem) 24624 24625 #define MEM_IS_EGR_VLAN_XLATE(mem) (EGR_VLAN_XLATE_1_SINGLEm == mem || \ 24626 EGR_VLAN_XLATE_1_DOUBLEm == mem || \ 24627 EGR_VLAN_XLATE_2_SINGLEm == mem || \ 24628 EGR_VLAN_XLATE_2_DOUBLEm == mem) 24629 24630 #define MEM_IS_MPLS(mem) (MPLS_ENTRYm == mem || MPLS_ENTRY_SINGLEm == mem) 24631 24632 #if defined(BCM_TOMAHAWK3_SUPPORT) 24633 #define MEM_IS_L3_TUNNEL_SINGLE(mem) (L3_TUNNEL_SINGLEm == mem) 24634 #define MEM_IS_L3_TUNNEL_DOUBLE(mem) (L3_TUNNEL_DOUBLEm == mem) 24635 #define MEM_IS_L3_TUNNEL_QUAD(mem) (L3_TUNNEL_QUADm == mem) 24636 #endif 24637 24638 24639 #if defined(BCM_TOMAHAWK_SUPPORT) 24640 STATIC INLINE void 24641 _soc_mem_shared_hash_exact_match_bucket_read(int unit, int ent, int key_type, int *width, 24642 soc_mem_t *mem, void *bkt_entry, void *entry, int pipenum) 24643 { 24644 soc_mem_info_t meminfo; 24645 soc_field_info_t fieldinfo; 24646 /* Exclude HIT bit */ 24647 int entry_bits; 24648 int table_entries_per_sram_entry = 0; 24649 switch (key_type) { 24650 case TH_FPEM_HASH_KEY_TYPE_128B: 24651 case TH_FPEM_HASH_KEY_TYPE_160B: 24652 *width = 1; 24653 table_entries_per_sram_entry = 2; 24654 switch (pipenum) { 24655 case 0: 24656 *mem = EXACT_MATCH_2_PIPE0m; 24657 break; 24658 case 1: 24659 *mem = EXACT_MATCH_2_PIPE1m; 24660 break; 24661 case 2: 24662 *mem = EXACT_MATCH_2_PIPE2m; 24663 break; 24664 case 3: 24665 *mem = EXACT_MATCH_2_PIPE3m; 24666 break; 24667 default: 24668 *mem = EXACT_MATCH_2m; 24669 break; 24670 } 24671 break; 24672 case TH_FPEM_HASH_KEY_TYPE_320B: 24673 default: 24674 table_entries_per_sram_entry = 1; 24675 switch (pipenum) { 24676 case 0: 24677 *mem = EXACT_MATCH_4_PIPE0m; 24678 break; 24679 case 1: 24680 *mem = EXACT_MATCH_4_PIPE1m; 24681 break; 24682 case 2: 24683 *mem = EXACT_MATCH_4_PIPE2m; 24684 break; 24685 case 3: 24686 *mem = EXACT_MATCH_4_PIPE3m; 24687 break; 24688 default: 24689 *mem = EXACT_MATCH_4m; 24690 break; 24691 } 24692 *width = 2; 24693 } 24694 entry_bits = (soc_mem_entry_bits(unit, EXACT_MATCH_2m) - 1) * (*width); 24695 24696 meminfo.flags = 0; 24697 meminfo.bytes = SOC_MEM_WORDS(unit, EXACT_MATCH_4m) * 4; 24698 fieldinfo.flags = SOCF_LE; 24699 fieldinfo.bp = entry_bits * ((ent % table_entries_per_sram_entry) / *width); 24700 fieldinfo.len = entry_bits; 24701 24702 (void)soc_meminfo_fieldinfo_field_get((uint32 *)bkt_entry, &meminfo, 24703 &fieldinfo, entry); 24704 } 24705 #endif 24706 24707 24708 #define _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, mem, status)\ 24709 switch(mem) { \ 24710 case L3_ENTRY_IPV6_MULTICASTm: \ 24711 case L3_ENTRY_QUADm: \ 24712 case L3_TUNNEL_QUADm: \ 24713 case EXACT_MATCH_4m: \ 24714 free = (status == 0x0); \ 24715 break; \ 24716 case L3_ENTRY_IPV6_UNICASTm: \ 24717 case L3_ENTRY_IPV4_MULTICASTm: \ 24718 case L3_ENTRY_DOUBLEm: \ 24719 case L3_TUNNEL_DOUBLEm: \ 24720 case EXACT_MATCH_2m: \ 24721 free = (status & 0x3) == 0 || (status >> 2) == 0; \ 24722 break; \ 24723 case MPLS_ENTRYm: \ 24724 case VLAN_XLATE_1_DOUBLEm: \ 24725 case VLAN_XLATE_2_DOUBLEm: \ 24726 case EGR_VLAN_XLATE_1_DOUBLEm: \ 24727 case EGR_VLAN_XLATE_2_DOUBLEm: \ 24728 free = (status & 0x3) == 0; \ 24729 break; \ 24730 case MPLS_ENTRY_SINGLEm: \ 24731 case VLAN_XLATE_1_SINGLEm: \ 24732 case VLAN_XLATE_2_SINGLEm: \ 24733 case EGR_VLAN_XLATE_1_SINGLEm: \ 24734 case EGR_VLAN_XLATE_2_SINGLEm: \ 24735 free = ((status&3) != 0x3); \ 24736 break; \ 24737 case L2Xm: \ 24738 case L3_ENTRY_ONLYm: \ 24739 case L3_ENTRY_IPV4_UNICASTm: \ 24740 case L3_ENTRY_ONLY_SINGLEm: \ 24741 case L3_ENTRY_SINGLEm: \ 24742 case L3_TUNNEL_SINGLEm: \ 24743 default: \ 24744 free = (status != 0xf); \ 24745 break; \ 24746 } 24747 24748 /* 24749 * Function: 24750 * _soc_mem_shared_hash_bucket 24751 * Purpose: 24752 * get the global bucket index 24753 * Parameters: unit - device 24754 * mem (IN) - mem 24755 * bank (IN) - physical bank num 24756 * entry(IN) - entry_data 24757 * 24758 * Returns: 24759 * global bucket index 24760 */ 24761 24762 STATIC INLINE int 24763 _soc_mem_shared_hash_bucket(int unit, int mem, int bank, uint32 *entry) 24764 { 24765 int index; 24766 uint32 bucket; 24767 /* Get the local bucket index in a bank */ 24768 #ifdef BCM_APACHE_SUPPORT 24769 if (SOC_IS_APACHE(unit)) { 24770 (void)soc_ap_hash_bucket_get(unit, mem, bank, entry, &bucket); 24771 } else 24772 #endif /* BCM_APACHE_SUPPORT */ 24773 #ifdef BCM_TOMAHAWK_SUPPORT 24774 if (SOC_IS_TOMAHAWKX(unit)) { 24775 #ifdef BCM_TOMAHAWK3_SUPPORT 24776 if (SOC_IS_TOMAHAWK3(unit)) { 24777 (void)soc_tomahawk3_hash_bucket_get(unit, mem, bank, entry, &bucket); 24778 } else 24779 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24780 { 24781 (void)soc_th_hash_bucket_get(unit, mem, bank, entry, &bucket); 24782 } 24783 } else 24784 #endif /* BCM_TOMAHAWK_SUPPORT */ 24785 #ifdef BCM_HELIX5_SUPPORT 24786 if (SOC_IS_HELIX5(unit)) { 24787 (void)soc_hx5_hash_bucket_get(unit, mem, bank, entry, &bucket); 24788 } else 24789 #endif /* BCM_HELIX5_SUPPORT */ 24790 #ifdef BCM_TRIDENT3_SUPPORT 24791 if (SOC_IS_TRIDENT3X(unit)) { 24792 (void)soc_td3_hash_bucket_get(unit, mem, bank, entry, &bucket); 24793 } else 24794 #endif /* BCM_TRIDENT3_SUPPORT */ 24795 { 24796 (void)soc_hash_bucket_get(unit, mem, bank, entry, &bucket); 24797 } 24798 /* Get global table index for the first entry in the bucket*/ 24799 #ifdef BCM_APACHE_SUPPORT 24800 if (SOC_IS_APACHE(unit)) { 24801 index = soc_ap_hash_index_get(unit, mem, bank, bucket); 24802 } else 24803 #endif /* BCM_APACHE_SUPPORT */ 24804 #ifdef BCM_TOMAHAWK_SUPPORT 24805 if (SOC_IS_TOMAHAWKX(unit)) { 24806 #ifdef BCM_TOMAHAWK3_SUPPORT 24807 if (SOC_IS_TOMAHAWK3(unit)) { 24808 index = soc_tomahawk3_hash_index_get(unit, mem, bank, bucket); 24809 } else 24810 #endif /* BCM_TOMAHAWK3_SUPPORT */ 24811 { 24812 index = soc_th_hash_index_get(unit, mem, bank, bucket); 24813 } 24814 } else 24815 #endif /* BCM_TOMAHAWK_SUPPORT */ 24816 #ifdef BCM_HELIX5_SUPPORT 24817 if (SOC_IS_HELIX5(unit)) { 24818 index = soc_hx5_hash_index_get(unit, mem, bank, bucket); 24819 } else 24820 #endif /* BCM_HELIX5_SUPPORT */ 24821 #ifdef BCM_TRIDENT3_SUPPORT 24822 if (SOC_IS_TRIDENT3X(unit)) { 24823 index = soc_td3_hash_index_get(unit, mem, bank, bucket); 24824 } else 24825 #endif /* BCM_TRIDENT3_SUPPORT */ 24826 { 24827 index = soc_hash_index_get(unit, mem, bank, bucket); 24828 } 24829 24830 return (index / _soc_mem_shared_hash_entries_per_bkt(unit, mem)); 24831 } 24832 24833 STATIC soc_mem_t 24834 _soc_mem_hash_base_mem_get(int unit, soc_mem_t mem) { 24835 switch (mem) { 24836 case L3_ENTRY_SINGLEm: 24837 case L3_ENTRY_ONLY_SINGLEm: 24838 case L3_ENTRY_DOUBLEm: 24839 case L3_ENTRY_ONLY_DOUBLEm: 24840 case L3_ENTRY_QUADm: 24841 case L3_ENTRY_ONLY_QUADm: 24842 return L3_ENTRY_QUADm; 24843 case L3_TUNNEL_SINGLEm: 24844 case L3_TUNNEL_DOUBLEm: 24845 case L3_TUNNEL_QUADm: 24846 return L3_TUNNEL_QUADm; 24847 case L3_ENTRY_IPV4_UNICASTm: 24848 case L3_ENTRY_IPV4_MULTICASTm: 24849 case L3_ENTRY_IPV6_UNICASTm: 24850 case L3_ENTRY_IPV6_MULTICASTm: 24851 return L3_ENTRY_IPV6_MULTICASTm; 24852 case EXACT_MATCH_2m: 24853 case EXACT_MATCH_4m: 24854 case EXACT_MATCH_4_PIPE0m: 24855 case EXACT_MATCH_4_PIPE1m: 24856 case EXACT_MATCH_4_PIPE2m: 24857 case EXACT_MATCH_4_PIPE3m: 24858 case EXACT_MATCH_2_PIPE0m: 24859 case EXACT_MATCH_2_PIPE1m: 24860 case EXACT_MATCH_2_PIPE2m: 24861 case EXACT_MATCH_2_PIPE3m: 24862 if (SOC_IS_TRIDENT3X(unit)) { 24863 if (mem == EXACT_MATCH_2_PIPE0m || mem == EXACT_MATCH_4_PIPE0m) { 24864 return EXACT_MATCH_4_PIPE0m; 24865 } else if (mem == EXACT_MATCH_2_PIPE1m || mem == EXACT_MATCH_4_PIPE1m) { 24866 return EXACT_MATCH_4_PIPE1m; 24867 } 24868 } 24869 return EXACT_MATCH_4m; 24870 case VLAN_XLATE_1_SINGLEm: 24871 case VLAN_XLATE_1_DOUBLEm: 24872 return VLAN_XLATE_1_DOUBLEm; 24873 case VLAN_XLATE_2_SINGLEm: 24874 case VLAN_XLATE_2_DOUBLEm: 24875 return VLAN_XLATE_2_DOUBLEm; 24876 case MPLS_ENTRY_SINGLEm: 24877 return MPLS_ENTRY_SINGLEm; 24878 case MPLS_ENTRYm: 24879 return MPLS_ENTRYm; 24880 case EGR_VLAN_XLATE_1_SINGLEm: 24881 case EGR_VLAN_XLATE_1_DOUBLEm: 24882 return EGR_VLAN_XLATE_1_DOUBLEm; 24883 case EGR_VLAN_XLATE_2_SINGLEm: 24884 case EGR_VLAN_XLATE_2_DOUBLEm: 24885 return EGR_VLAN_XLATE_2_DOUBLEm; 24886 default: 24887 return INVALIDm; 24888 } 24889 } 24890 24891 STATIC int 24892 _soc_mem_hash_mem_width_get(int unit, soc_mem_t mem) { 24893 switch (mem) { 24894 case L3_ENTRY_SINGLEm: 24895 case L3_ENTRY_ONLY_SINGLEm: 24896 case L3_ENTRY_IPV4_UNICASTm: 24897 case VLAN_XLATE_1_SINGLEm: 24898 case VLAN_XLATE_2_SINGLEm: 24899 case MPLS_ENTRY_SINGLEm: 24900 case EGR_VLAN_XLATE_1_SINGLEm: 24901 case EGR_VLAN_XLATE_2_SINGLEm: 24902 return 1; 24903 case EXACT_MATCH_2m: 24904 case EXACT_MATCH_2_PIPE0m: 24905 case EXACT_MATCH_2_PIPE1m: 24906 case EXACT_MATCH_2_PIPE2m: 24907 case EXACT_MATCH_2_PIPE3m: 24908 #ifdef BCM_TOMAHAWK3_SUPPORT 24909 if (SOC_IS_TOMAHAWK3(unit)) { 24910 return 2; 24911 } else 24912 #endif 24913 return (SOC_IS_TRIDENT3X(unit) ? 2 : 1); 24914 case L3_ENTRY_DOUBLEm: 24915 case L3_ENTRY_ONLY_DOUBLEm: 24916 case L3_ENTRY_IPV4_MULTICASTm: 24917 case L3_ENTRY_IPV6_UNICASTm: 24918 case VLAN_XLATE_1_DOUBLEm: 24919 case VLAN_XLATE_2_DOUBLEm: 24920 case MPLS_ENTRYm: 24921 case EGR_VLAN_XLATE_1_DOUBLEm: 24922 case EGR_VLAN_XLATE_2_DOUBLEm: 24923 return 2; 24924 case EXACT_MATCH_4m: 24925 case EXACT_MATCH_4_PIPE0m: 24926 case EXACT_MATCH_4_PIPE1m: 24927 case EXACT_MATCH_4_PIPE2m: 24928 case EXACT_MATCH_4_PIPE3m: 24929 #ifdef BCM_TOMAHAWK3_SUPPORT 24930 if (SOC_IS_TOMAHAWK3(unit)) { 24931 return 4; 24932 } else 24933 #endif 24934 return (SOC_IS_TRIDENT3X(unit) ? 4 : 1); 24935 case L3_ENTRY_QUADm: 24936 case L3_ENTRY_ONLY_QUADm: 24937 case L3_ENTRY_IPV6_MULTICASTm: 24938 return 4; 24939 default: 24940 return -1; 24941 } 24942 24943 } 24944 24945 #define INVALID_BUCKET -1 24946 24947 /* 24948 * this breadth algorithm works as backup as it uses fixed memory which 24949 * will be less than the default one when depth exceeds a threshold 24950 */ 24951 24952 STATIC int 24953 _soc_mem_shared_hash_breadth_l2_move2(int unit, soc_mem_t mem, int copyno, 24954 void *entry, int num_levels) 24955 { 24956 _soc_breadth_bucket2_t *buckets = NULL; 24957 _soc_breadth_bucket2_t *cb, *cbi, *pbi, *pb, *sb; 24958 SHR_BITDCL *bkt_trace = NULL; 24959 _soc_hash_bank_info_t bi = {0}; 24960 int rv; 24961 int job_done = 0; 24962 int bank_num, ibank_num = 0; 24963 int bix, cbix, num_banks; 24964 int free = 0; 24965 int ent, sent, bucket; 24966 int curr_bucket; 24967 void *se, *me; 24968 24969 if (num_levels <= 0) { 24970 return SOC_E_FULL; 24971 } 24972 24973 SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init 24974 (unit, mem, &bkt_trace, &bi, 0, NULL, &buckets)); 24975 24976 /* the last bucket, which is also the head */ 24977 curr_bucket = bi.numb; 24978 pb = &buckets[curr_bucket]; 24979 pb->bucket = curr_bucket; 24980 pb->src_bix = -1; 24981 pb->level = -1; 24982 pb->n_bucket = -1; 24983 24984 do { 24985 /* This bucket's entries have been tried to move */ 24986 cb = &buckets[curr_bucket]; 24987 24988 /* all levels have been tried */ 24989 if (cb->level == num_levels - 1) { 24990 goto done; 24991 } 24992 24993 /* now generate the sub buckets under this bucket 24994 * and try to move the sub buckets' entries 24995 */ 24996 24997 if (curr_bucket == bi.numb) { 24998 num_banks = bi.num_banks; 24999 } else { 25000 num_banks = bi.num_banks - 1; 25001 } 25002 25003 for (ent = 0; ent < NUM_ENT; ent++) { 25004 if (curr_bucket == bi.numb) { 25005 se = entry; 25006 } else { 25007 se = &cb->e.l2[ent]; 25008 } 25009 for (bix = 0; bix < num_banks; bix++) { 25010 cbix = cb->src_bix + bix + 1; 25011 cbix = cbix % bi.num_banks; 25012 25013 bank_num = bi.bank_nums[cbix]; 25014 bucket = _soc_mem_shared_hash_bucket(unit, mem, 25015 bank_num, se); 25016 25017 /* do not visit a bucket twice */ 25018 if (SHR_BITGET(bkt_trace, bucket)) { 25019 continue; 25020 } 25021 25022 sb = &buckets[bucket]; 25023 SHR_BITSET(bkt_trace, bucket); 25024 sb->level = cb->level + 1; 25025 sb->src_ent = ent; 25026 sb->bucket = bucket; 25027 sb->s_bucket = curr_bucket; 25028 sb->src_bix = cbix; 25029 25030 /* connect */ 25031 pb->n_bucket = bucket; 25032 sb->n_bucket = INVALID_BUCKET; 25033 25034 /* loop sub bucket's entries and try move */ 25035 for (sent = 0; sent < NUM_ENT; sent++) { 25036 me = &sb->e.l2[sent]; 25037 rv = soc_mem_read(unit, mem, copyno, (bucket << 2) + sent, me); 25038 if (SOC_FAILURE(rv)) { 25039 goto cleanup; 25040 } 25041 25042 rv = soc_mem_generic_insert(unit, mem, copyno, 25043 bi.banks & ~(1 << bank_num), 25044 me, NULL, NULL); 25045 25046 free = 0; 25047 if (SOC_SUCCESS(rv)) { 25048 25049 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 25050 1 << bank_num, me, NULL, NULL); 25051 if (SOC_FAILURE(rv)) { 25052 goto cleanup; 25053 } 25054 free = 1; 25055 25056 } 25057 25058 /* sb is not freed, try move next entry in sb */ 25059 if (!free) { 25060 continue; 25061 } 25062 25063 /* now sb is freed. 25064 * cb's entry can be moved now. move it and 25065 * more if possible 25066 */ 25067 ibank_num = bank_num; 25068 pbi = sb; 25069 while (pbi->s_bucket != bi.numb) { 25070 cbi = pbi; 25071 pbi = &buckets[pbi->s_bucket]; 25072 me = &pbi->e.l2[cbi->src_ent]; 25073 rv = soc_mem_generic_insert(unit, mem, copyno, 25074 (1 << ibank_num), 25075 me, NULL, NULL); 25076 if (SOC_FAILURE(rv)) { 25077 goto cleanup; 25078 } 25079 25080 ibank_num = bi.bank_nums[pbi->src_bix]; 25081 25082 rv = soc_mem_generic_delete(unit, mem, 25083 MEM_BLOCK_ANY, 25084 (1 << ibank_num), 25085 me, NULL, NULL); 25086 if (SOC_FAILURE(rv)) { 25087 goto cleanup; 25088 } 25089 } 25090 25091 job_done = 1; 25092 goto done; 25093 } /* sub bucket loop and move done. */ 25094 25095 pb = sb; 25096 } 25097 } 25098 curr_bucket = cb->n_bucket; 25099 } while (curr_bucket != INVALID_BUCKET); 25100 25101 done: 25102 if (job_done) { 25103 rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num, 25104 entry, entry, NULL); 25105 } else { 25106 rv = SOC_E_FULL; 25107 } 25108 25109 cleanup: 25110 if (bkt_trace) { 25111 sal_free(bkt_trace); 25112 } 25113 25114 if (buckets) { 25115 sal_free(buckets); 25116 } 25117 25118 if (SOC_FAILURE(rv)) { 25119 LOG_VERBOSE(BSL_LS_SOC_COMMON, 25120 (BSL_META_U(unit, 25121 "Insert entry: %d\n"), rv)); 25122 } 25123 25124 return rv; 25125 } 25126 25127 STATIC int 25128 _soc_mem_shared_hash_breadth_mix_move2(int unit, soc_mem_t mem, int copyno, 25129 void *entry, int num_levels) 25130 { 25131 _soc_breadth_bucket2_t *buckets = NULL; 25132 _soc_breadth_bucket2_t *cb, *nb, *cbi = NULL, *pbi, *pb, *sb, *ib; 25133 SHR_BITDCL *bkt_trace = NULL; 25134 _soc_hash_bank_info_t bi = {0}; 25135 uint32 bkt_entry[NUM_ENT][SOC_MAX_MEM_WORDS]; 25136 uint32 v[NUM_ENT], k[NUM_ENT]; 25137 int rv; 25138 int job_done = 0; 25139 int bank_num, ibank_num = 0; 25140 int bix, cbix, num_banks; 25141 int move_bkt; 25142 int free = 0; 25143 int ent, ent_incr, sent, sent_incr, bucket; 25144 uint8 skip = 0, src_width; 25145 soc_mem_t orig_mem, base_mem, src_mem; 25146 int curr_bucket; 25147 int vld_fld_0 = VALID_0f, vld_fld_1 = VALID_1f; 25148 int vld_fld_2 = VALID_2f, vld_fld_3 = VALID_3f; 25149 int key_type_0 = KEY_TYPE_0f, key_type_1 = KEY_TYPE_1f; 25150 int key_type_2 = KEY_TYPE_2f, key_type_3 = KEY_TYPE_3f; 25151 void *se, *me; 25152 #if defined(BCM_TOMAHAWK_SUPPORT) 25153 int pipenum = -1; 25154 #endif 25155 25156 if (num_levels <= 0) { 25157 return SOC_E_FULL; 25158 } 25159 25160 base_mem = _soc_mem_hash_base_mem_get(unit, mem); 25161 #if defined(BCM_TOMAHAWK_SUPPORT) 25162 if (base_mem == EXACT_MATCH_4m) { 25163 switch (mem) { 25164 case EXACT_MATCH_4_PIPE0m: 25165 case EXACT_MATCH_2_PIPE0m: 25166 base_mem = EXACT_MATCH_4_PIPE0m; 25167 pipenum = 0; 25168 break; 25169 case EXACT_MATCH_4_PIPE1m: 25170 case EXACT_MATCH_2_PIPE1m: 25171 base_mem = EXACT_MATCH_4_PIPE1m; 25172 pipenum = 1; 25173 break; 25174 case EXACT_MATCH_4_PIPE2m: 25175 case EXACT_MATCH_2_PIPE2m: 25176 base_mem = EXACT_MATCH_4_PIPE2m; 25177 pipenum = 2; 25178 break; 25179 case EXACT_MATCH_4_PIPE3m: 25180 case EXACT_MATCH_2_PIPE3m: 25181 base_mem = EXACT_MATCH_4_PIPE3m; 25182 pipenum = 3; 25183 break; 25184 default: 25185 break; 25186 } 25187 } 25188 #endif 25189 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 25190 if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) { 25191 vld_fld_0 = BASE_VALID_0f; 25192 vld_fld_1 = BASE_VALID_1f; 25193 vld_fld_2 = BASE_VALID_2f; 25194 vld_fld_3 = BASE_VALID_3f; 25195 key_type_0 = KEY_TYPEf; 25196 key_type_1 = KEY_TYPEf; 25197 key_type_2 = KEY_TYPEf; 25198 key_type_3 = KEY_TYPEf; 25199 } 25200 #endif 25201 SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init 25202 (unit, base_mem, &bkt_trace, &bi, 0, NULL, &buckets)); 25203 25204 /* the last bucket, which is also the head */ 25205 curr_bucket = bi.numb; 25206 pb = &buckets[curr_bucket]; 25207 pb->bucket = curr_bucket; 25208 pb->status = 0x1; 25209 pb->src_bix = -1; 25210 pb->level = -1; 25211 pb->n_bucket = -1; 25212 pb->mem[0] = mem; 25213 25214 do { 25215 /* This bucket's entries have been tried to move */ 25216 cb = &buckets[curr_bucket]; 25217 25218 /* all levels have been tried */ 25219 if (cb->level == num_levels - 1) { 25220 goto done; 25221 } 25222 25223 /* now generate the sub buckets under this bucket 25224 * and try to move the sub buckets' entries 25225 */ 25226 25227 if (curr_bucket == bi.numb) { 25228 num_banks = bi.num_banks; 25229 } else { 25230 num_banks = bi.num_banks - 1; 25231 } 25232 25233 for (ent = 0; ent < NUM_ENT; ent += ent_incr) { 25234 if (!(cb->status & (1 << ent))) { 25235 ent_incr = 1; 25236 continue; 25237 } 25238 25239 if (curr_bucket == bi.numb) { 25240 se = entry; 25241 ent_incr = NUM_ENT; 25242 } else 25243 #ifdef BCM_TOMAHAWK_SUPPORT 25244 if (MEM_IS_EXACT_MATCH_4(mem)) { 25245 se = &cb->e.em_4[ent]; 25246 ent_incr = cb->width[ent]; 25247 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 25248 se = &cb->e.em_2[ent]; 25249 ent_incr = cb->width[ent]; 25250 } else 25251 #ifdef BCM_TOMAHAWK3_SUPPORT 25252 if (SOC_IS_TOMAHAWK3(unit) && MEM_IS_MPLS(mem)) { 25253 se = &cb->e.mpls_1[ent]; 25254 ent_incr = cb->width[ent]; 25255 } else 25256 #endif /* BCM_TOMAHAWK3_SUPPORT */ 25257 #endif /* BCM_TOMAHAWK_SUPPORT */ 25258 #ifdef BCM_TRIDENT3_SUPPORT 25259 if (MEM_IS_VLAN_XLATE(mem)) { 25260 se = &cb->e.vlan[ent]; 25261 ent_incr = cb->width[ent]; 25262 } else if (MEM_IS_EGR_VLAN_XLATE(mem)) { 25263 se = &cb->e.egr_vlan[ent]; 25264 ent_incr = cb->width[ent]; 25265 } else if (MEM_IS_MPLS(mem)) { 25266 se = &cb->e.mpls[ent]; 25267 ent_incr = cb->width[ent]; 25268 } else if (SOC_IS_TRIDENT3X(unit)) { 25269 se = &cb->e.l3_single[ent]; 25270 ent_incr = cb->width[ent]; 25271 } else 25272 #endif /* BCM_TRIDENT3_SUPPORT */ 25273 { 25274 se = &cb->e.l3[ent]; 25275 ent_incr = cb->width[ent]; 25276 } 25277 25278 src_mem = cb->mem[ent]; 25279 skip = 0; 25280 for (bix = 0; bix < num_banks; bix++) { 25281 cbix = cb->src_bix + bix + 1; 25282 cbix = cbix % bi.num_banks; 25283 25284 bank_num = bi.bank_nums[cbix]; 25285 bucket = _soc_mem_shared_hash_bucket(unit, src_mem, bank_num, se); 25286 25287 /* do not visit a bucket twice */ 25288 if (SHR_BITGET(bkt_trace, bucket)) { 25289 continue; 25290 } 25291 25292 sb = &buckets[bucket]; 25293 SHR_BITSET(bkt_trace, bucket); 25294 sb->level = cb->level + 1; 25295 sb->src_ent = ent; 25296 sb->bucket = bucket; 25297 sb->s_bucket = curr_bucket; 25298 sb->src_bix = cbix; 25299 25300 /* connect */ 25301 pb->n_bucket = bucket; 25302 sb->p_bucket = pb->bucket; 25303 sb->n_bucket = INVALID_BUCKET; 25304 if (MEM_IS_EXACT_MATCH_4(mem) || 25305 (SOC_IS_TRIDENT3X(unit) && MEM_IS_EXACT_MATCH_2(mem))) { 25306 rv = soc_mem_read(unit, base_mem, copyno, 25307 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4, bkt_entry[0]); 25308 if (SOC_FAILURE(rv)) { 25309 goto cleanup; 25310 } 25311 rv = soc_mem_read(unit, base_mem, copyno, 25312 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 1, 25313 bkt_entry[1]); 25314 if (SOC_FAILURE(rv)) { 25315 goto cleanup; 25316 } 25317 rv = soc_mem_read(unit, base_mem, copyno, 25318 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 2, 25319 bkt_entry[2]); 25320 if (SOC_FAILURE(rv)) { 25321 goto cleanup; 25322 } 25323 rv = soc_mem_read(unit, base_mem, copyno, 25324 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 3, 25325 bkt_entry[3]); 25326 if (SOC_FAILURE(rv)) { 25327 goto cleanup; 25328 } 25329 soc_mem_field_get(unit, base_mem, bkt_entry[3], vld_fld_0, &v[3]); 25330 soc_mem_field_get(unit, base_mem, bkt_entry[2], vld_fld_0, &v[2]); 25331 soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_0, &v[1]); 25332 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]); 25333 soc_mem_field_get(unit, base_mem, bkt_entry[3], key_type_0, &k[3]); 25334 soc_mem_field_get(unit, base_mem, bkt_entry[2], key_type_0, &k[2]); 25335 soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_0, &k[1]); 25336 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]); 25337 25338 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 25339 rv = soc_mem_read(unit, base_mem, copyno, 25340 bucket * SRAM_ENTRIES_PER_BUCKET_EM_2, bkt_entry[0]); 25341 if (SOC_FAILURE(rv)) { 25342 goto cleanup; 25343 } 25344 rv = soc_mem_read(unit, base_mem, copyno, 25345 bucket * SRAM_ENTRIES_PER_BUCKET_EM_2 + 1, 25346 bkt_entry[1]); 25347 if (SOC_FAILURE(rv)) { 25348 goto cleanup; 25349 } 25350 soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_2, &v[3]); 25351 soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_0, &v[2]); 25352 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_2, &v[1]); 25353 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]); 25354 soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_2, &k[3]); 25355 soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_0, &k[2]); 25356 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_2, &k[1]); 25357 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]); 25358 25359 } else { 25360 /* loop sub bucket's entries and try move */ 25361 rv = soc_mem_read(unit, base_mem, copyno, bucket, bkt_entry[0]); 25362 if (SOC_FAILURE(rv)) { 25363 goto cleanup; 25364 } 25365 25366 #ifdef BCM_HELIX5_SUPPORT 25367 if (SOC_IS_HELIX5(unit)) { 25368 soc_hx5_hash_mem_status_get(unit, base_mem, bkt_entry[0], v); 25369 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPEf, &k[0]); 25370 k[3] = k[2] = k[1] = k[0]; 25371 } else 25372 #endif /* BCM_HELIX5_SUPPORT */ 25373 #ifdef BCM_TRIDENT3_SUPPORT 25374 if (SOC_IS_TRIDENT3X(unit)) { 25375 soc_td3_hash_mem_status_get(unit, base_mem, bkt_entry[0], v); 25376 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPEf, &k[0]); 25377 k[3] = k[2] = k[1] = k[0]; 25378 } else 25379 #endif /* BCM_TRIDENT3_SUPPORT */ 25380 #ifdef BCM_TOMAHAWK3_SUPPORT 25381 if (SOC_IS_TOMAHAWK3(unit)) { 25382 soc_tomahawk3_hash_mem_status_get(unit, base_mem, bkt_entry[0], v); 25383 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPEf, &k[0]); 25384 k[3] = k[2] = k[1] = k[0]; 25385 } else 25386 #endif /* BCM_TOMAHAWK3_SUPPORT */ 25387 { 25388 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_3, &v[3]); 25389 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_2, &v[2]); 25390 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_1, &v[1]); 25391 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]); 25392 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_3, &k[3]); 25393 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_2, &k[2]); 25394 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_1, &k[1]); 25395 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]); 25396 } 25397 } 25398 25399 sb->status = (v[3]? (1 << 3) : 0) | (v[2]? (1 << 2) : 0) | 25400 (v[1]? (1 << 1) : 0) | (v[0]? 1 : 0); 25401 25402 /* loop sub bucket's entries and try insert */ 25403 for (sent = 0; sent < NUM_ENT; sent += sent_incr) { 25404 if (!v[sent]) { 25405 sent_incr = 1; 25406 continue; 25407 } 25408 #ifdef BCM_TOMAHAWK_SUPPORT 25409 if (MEM_IS_EXACT_MATCH_4(mem)) { 25410 me = &sb->e.em_4[sent]; 25411 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 25412 me = &sb->e.em_2[sent]; 25413 } else 25414 #ifdef BCM_TOMAHAWK3_SUPPORT 25415 if (MEM_IS_MPLS(mem)) { 25416 me = &sb->e.mpls_1[sent]; 25417 } else 25418 #endif /* BCM_TOMAHAWK3_SUPPORT */ 25419 #endif /* BCM_TOMAHAWK_SUPPORT */ 25420 #ifdef BCM_TRIDENT3_SUPPORT 25421 if (MEM_IS_VLAN_XLATE(mem)) { 25422 me = &sb->e.vlan[sent]; 25423 } else if (MEM_IS_EGR_VLAN_XLATE(mem)) { 25424 me = &sb->e.egr_vlan[sent]; 25425 } else if (MEM_IS_MPLS(mem)) { 25426 me = &sb->e.mpls[sent]; 25427 } else if (SOC_IS_TRIDENT3X(unit)) { 25428 me = &sb->e.l3_single[sent]; 25429 } else 25430 #endif /* BCM_TRIDENT3_SUPPORT */ 25431 { 25432 me = &sb->e.l3[sent]; 25433 } 25434 25435 #ifdef BCM_HELIX5_SUPPORT 25436 if (SOC_IS_HELIX5(unit)) { 25437 SOC_IF_ERROR_RETURN(soc_hx5_shared_hash_mem_bucket_read 25438 (unit, sent, k[sent], &sent_incr, 25439 base_mem, &orig_mem, bkt_entry[sent / SRAM_ENTRIES_PER_BUCKET], me)); 25440 } else 25441 #endif /* BCM_HELIX5_SUPPORT */ 25442 #ifdef BCM_TRIDENT3_SUPPORT 25443 if (SOC_IS_TRIDENT3X(unit)) { 25444 if (MEM_IS_EXACT_MATCH_2(mem) || 25445 MEM_IS_EXACT_MATCH_4(mem)) { 25446 SOC_IF_ERROR_RETURN(soc_td3_shared_hash_mem_bucket_read 25447 (unit, sent, k[sent], &sent_incr, base_mem, 25448 &orig_mem, bkt_entry[sent], me)); 25449 } 25450 } else 25451 #endif /* BCM_TRIDENT3_SUPPORT */ 25452 { 25453 #if defined(BCM_TOMAHAWK_SUPPORT) 25454 #if defined(BCM_TOMAHAWK3_SUPPORT) 25455 if (SOC_IS_TOMAHAWK3(unit)) { 25456 if (MEM_IS_EXACT_MATCH_2(mem) || 25457 MEM_IS_EXACT_MATCH_4(mem)) { 25458 SOC_IF_ERROR_RETURN(soc_tomahawk3_shared_hash_mem_bucket_read 25459 (unit, sent, k[sent], &sent_incr, base_mem, 25460 &orig_mem, bkt_entry[sent], me)); 25461 } 25462 } else 25463 #endif /* BCM_TOMAHAWK3_SUPPORT */ 25464 if (MEM_IS_EXACT_MATCH_4(mem)) { 25465 me = &sb->e.em_4[sent]; 25466 _soc_mem_shared_hash_exact_match_bucket_read(unit, sent, k[sent], 25467 &sent_incr, &orig_mem, bkt_entry[sent], me, pipenum); 25468 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 25469 me = &sb->e.em_2[sent]; 25470 _soc_mem_shared_hash_exact_match_bucket_read(unit, sent, k[sent], 25471 &sent_incr, &orig_mem, bkt_entry[sent / SRAM_ENTRIES_PER_BUCKET_EM_2], me, pipenum); 25472 } else 25473 #endif 25474 { 25475 _soc_mem_shared_hash_l3_bucket_read(unit, sent, k[sent], 25476 &sent_incr, &orig_mem, bkt_entry[0], me); 25477 } 25478 } 25479 sb->width[sent] = sent_incr; 25480 sb->mem[sent] = orig_mem; 25481 25482 rv = soc_mem_generic_insert(unit, orig_mem, copyno, 25483 bi.banks & ~(1 << bank_num), 25484 me, NULL, &move_bkt); 25485 25486 free = 0; 25487 if (SOC_SUCCESS(rv)) { 25488 25489 /* modifying a visited a bucket may 25490 * corrupt the structure (entry, status ...) 25491 */ 25492 move_bkt /= _soc_mem_shared_hash_entries_per_bkt(unit, orig_mem); 25493 if (SHR_BITGET(bkt_trace, move_bkt)) { 25494 rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY, 25495 bi.banks & ~(1 << bank_num), 25496 me, NULL, NULL); 25497 25498 if (SOC_FAILURE(rv)) { 25499 goto cleanup; 25500 } 25501 } else { 25502 rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY, 25503 1 << bank_num, me, NULL, NULL); 25504 if (SOC_FAILURE(rv)) { 25505 goto cleanup; 25506 } 25507 sb->status &= ~(((1 << sent_incr) - 1) << sent); 25508 25509 _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, src_mem, sb->status); 25510 } 25511 } 25512 /* sb is not freed, try move next entry in sb */ 25513 if (!free) { 25514 continue; 25515 } 25516 25517 /* now sb is freed. 25518 * cb's entry can be moved now. move it and 25519 * more if possible 25520 */ 25521 ibank_num = bank_num; 25522 pbi = sb; 25523 25524 while (free && pbi->s_bucket != bi.numb) { 25525 cbi = pbi; 25526 pbi = &buckets[pbi->s_bucket]; 25527 #ifdef BCM_TOMAHAWK_SUPPORT 25528 if (MEM_IS_EXACT_MATCH_4(mem)) { 25529 me = &pbi->e.em_4[cbi->src_ent]; 25530 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 25531 me = &pbi->e.em_2[cbi->src_ent]; 25532 } else 25533 #ifdef BCM_TOMAHAWK3_SUPPORT 25534 if (MEM_IS_MPLS(mem)) { 25535 me = &sb->e.mpls_1[cbi->src_ent]; 25536 } else 25537 #endif /* BCM_TOMAHAWK3_SUPPORT */ 25538 #endif /* BCM_TOMAHAWK_SUPPORT */ 25539 #ifdef BCM_TRIDENT3_SUPPORT 25540 if (MEM_IS_VLAN_XLATE(mem)) { 25541 me = &pbi->e.vlan[cbi->src_ent]; 25542 } else if (MEM_IS_EGR_VLAN_XLATE(mem)) { 25543 me = &pbi->e.egr_vlan[cbi->src_ent]; 25544 } else if (MEM_IS_MPLS(mem)) { 25545 me = &pbi->e.mpls[cbi->src_ent]; 25546 } else if (SOC_IS_TRIDENT3X(unit)) { 25547 me = &pbi->e.l3_single[cbi->src_ent]; 25548 } else 25549 #endif /* BCM_TRIDENT3_SUPPORT */ 25550 { 25551 me = &pbi->e.l3[cbi->src_ent]; 25552 } 25553 25554 orig_mem = pbi->mem[cbi->src_ent]; 25555 rv = soc_mem_generic_insert(unit, orig_mem, copyno, 25556 (1 << ibank_num), 25557 me, NULL, NULL); 25558 if (SOC_FAILURE(rv)) { 25559 goto cleanup; 25560 } 25561 25562 ibank_num = bi.bank_nums[pbi->src_bix]; 25563 25564 rv = soc_mem_generic_delete(unit, orig_mem, 25565 MEM_BLOCK_ANY, 25566 (1 << ibank_num), 25567 me, NULL, NULL); 25568 if (SOC_FAILURE(rv)) { 25569 goto cleanup; 25570 } 25571 25572 src_width = _soc_mem_hash_mem_width_get(unit, mem); 25573 pbi->status &= ~(((1 << src_width) - 1) << cbi->src_ent); 25574 25575 _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, 25576 buckets[pbi->s_bucket].mem[pbi->src_ent], pbi->status); 25577 } 25578 25579 if (free) { 25580 job_done = 1; 25581 goto done; 25582 } else { 25583 /* re-connect, because some of sbs which are linked 25584 * just now, may need to be removed from the link. 25585 */ 25586 25587 /* taking care of the sub buckets at next level */ 25588 while (pb->level == sb->level) { 25589 ib = pb; 25590 while (ib->level > cbi->level) { 25591 ib = &buckets[ib->s_bucket]; 25592 } 25593 if (ib->s_bucket != cbi->s_bucket || 25594 ib->src_ent != cbi->src_ent) { 25595 break; 25596 } 25597 /* this could be further optimized to clear 25598 * those skipped sbs and free the bucket. 25599 */ 25600 pb = &buckets[pb->p_bucket]; 25601 } 25602 25603 /* taking care of the current buckets at this level */ 25604 if (pbi == cb) { 25605 /* moved 1 entry. entry of cb is moved, but cb is 25606 * still not freed. continue next entry's sub bucket 25607 */ 25608 skip = 1; 25609 /* assert (cb->level == cbi->level - 1); */ 25610 } else { 25611 25612 /* moved at least 2 entries, now it's time 25613 * to advance current bucket. 25614 */ 25615 25616 /* assert (cb->level >= cbi->level); */ 25617 skip = 2; 25618 25619 nb = &buckets[cb->n_bucket]; 25620 while (nb->level != sb->level) { 25621 ib = nb; 25622 while (ib->level > cbi->level) { 25623 ib = &buckets[ib->s_bucket]; 25624 } 25625 if (ib->s_bucket != cbi->s_bucket || 25626 ib->src_ent != cbi->src_ent) { 25627 break; 25628 } 25629 nb = &buckets[nb->n_bucket]; 25630 } 25631 25632 cb = &buckets[nb->p_bucket]; 25633 } 25634 break; 25635 } 25636 } /* sub bucket loop and move done. */ 25637 if (skip) { 25638 break; 25639 } 25640 pb = sb; 25641 } 25642 if (skip == 2) { 25643 break; 25644 } 25645 } 25646 curr_bucket = cb->n_bucket; 25647 } while (curr_bucket != INVALID_BUCKET); 25648 25649 done: 25650 if (job_done) { 25651 rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num, 25652 entry, entry, NULL); 25653 } else { 25654 rv = SOC_E_FULL; 25655 } 25656 25657 cleanup: 25658 if (bkt_trace) { 25659 sal_free(bkt_trace); 25660 } 25661 25662 if (buckets) { 25663 sal_free(buckets); 25664 } 25665 25666 if (SOC_FAILURE(rv)) { 25667 LOG_VERBOSE(BSL_LS_SOC_COMMON, 25668 (BSL_META_U(unit, 25669 "Insert entry: %d\n"), rv)); 25670 } 25671 25672 return rv; 25673 } 25674 25675 /* 25676 * this breadth algorithm is the default one which is faster and 25677 * consume less memory. 25678 */ 25679 #define MAX_MIX_LEVELS 4 25680 #define MAX_L2_LEVELS 6 25681 25682 STATIC int 25683 _soc_mem_shared_hash_breadth_l2_move(int unit, soc_mem_t mem, int copyno, 25684 void *entry, int num_levels) 25685 { 25686 SHR_BITDCL *bkt_trace = NULL; 25687 _soc_breadth_bucket_t *buckets[MAX_L2_LEVELS + 1] = {0}; 25688 _soc_breadth_bucket_t *cb, *tb, *cbi = NULL, *pbi; 25689 uint32 *se; 25690 int rv; 25691 int level, job_done = 0; 25692 int bank_num, ibank_num = 0; 25693 int bix, cbix; 25694 int bkt_idx; 25695 int nl_bkt_idx, num_cl_bkts; 25696 int ent, bucket; 25697 int i; 25698 _soc_hash_bank_info_t bi = {0}; 25699 25700 if (num_levels <= 0) { 25701 return SOC_E_FULL; 25702 } else if (num_levels > MAX_L2_LEVELS) { 25703 return _soc_mem_shared_hash_breadth_l2_move2(unit, mem, copyno, 25704 entry, num_levels); 25705 } 25706 25707 SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init 25708 (unit, mem, &bkt_trace, &bi, num_levels, &buckets[0], NULL)); 25709 25710 num_cl_bkts = bi.num_banks; 25711 25712 for (level = 0; level < num_levels; level++) { 25713 if (level + 1 < num_levels) { 25714 buckets[level + 1] = buckets[level] + num_cl_bkts; 25715 } else { 25716 buckets[level + 1] = 0; 25717 } 25718 for (bkt_idx = 0; bkt_idx < num_cl_bkts; bkt_idx++) { 25719 cb = &buckets[level][bkt_idx]; 25720 if (level == 0) { 25721 cb->src_bix = bkt_idx; 25722 cb->src_mem = mem; 25723 se = entry; 25724 } else { 25725 se = (uint32 *)&buckets[level - 1][cb->src_bkt_idx].e.l2[cb->src_ent]; 25726 } 25727 25728 if (cb->src_mem == 0) { 25729 continue; 25730 } 25731 25732 bank_num = bi.bank_nums[cb->src_bix]; 25733 bucket = _soc_mem_shared_hash_bucket(unit, cb->src_mem, bank_num, se); 25734 25735 if (SHR_BITGET(bkt_trace, bucket)) { 25736 continue; 25737 } 25738 SHR_BITSET(bkt_trace, bucket); 25739 cb->bucket = bucket; 25740 25741 for (ent = 0; ent < NUM_ENT; ent++) { 25742 /* Read current entry */ 25743 rv = soc_mem_read(unit, mem, copyno, (bucket << 2) + ent, &cb->e.l2[ent]); 25744 if (SOC_FAILURE(rv)) { 25745 goto cleanup; 25746 } 25747 25748 /* Try insert */ 25749 rv = soc_mem_generic_insert(unit, mem, copyno, 25750 bi.banks & ~(1 << bank_num), 25751 &cb->e.l2[ent], NULL, NULL); 25752 25753 if (SOC_SUCCESS(rv)) { 25754 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 25755 (uint32)1<<bank_num, 25756 &cb->e.l2[ent], NULL, NULL); 25757 if (SOC_FAILURE(rv)) { 25758 goto cleanup; 25759 } 25760 break; 25761 } 25762 25763 /* Construct buckets in next level under this entry */ 25764 nl_bkt_idx = bkt_idx * (bi.num_banks - 1) * NUM_ENT + 25765 ent * (bi.num_banks - 1); 25766 25767 for (bix = 0; bix < bi.num_banks && buckets[level + 1]; bix++) { 25768 cbix = cb->src_bix + bix + 1; 25769 cbix = cbix % bi.num_banks; 25770 if (bank_num == bi.bank_nums[cbix]) { 25771 continue; 25772 } 25773 25774 tb = &buckets[level + 1][nl_bkt_idx++]; 25775 tb->src_bkt_idx = bkt_idx; 25776 tb->src_bix = cbix; 25777 tb->src_mem = mem; 25778 tb->src_ent = ent; 25779 } 25780 } 25781 25782 if (ent < NUM_ENT) { 25783 ibank_num = bank_num; 25784 pbi = cb; 25785 for (i = level; i > 0; i--) { 25786 cbi = pbi; 25787 pbi = &buckets[i - 1][cbi->src_bkt_idx]; 25788 25789 rv = soc_mem_bank_insert(unit, cbi->src_mem, 25790 (1 << ibank_num), copyno, 25791 &pbi->e.l2[cbi->src_ent], NULL); 25792 if (SOC_FAILURE(rv)) { 25793 goto cleanup; 25794 } 25795 25796 ibank_num = bi.bank_nums[pbi->src_bix]; 25797 25798 rv = soc_mem_generic_delete(unit, cbi->src_mem, MEM_BLOCK_ANY, 25799 (1 << ibank_num), 25800 &pbi->e.l2[cbi->src_ent], NULL, NULL); 25801 if (SOC_FAILURE(rv)) { 25802 goto cleanup; 25803 } 25804 } 25805 job_done = 1; 25806 goto done; 25807 } 25808 } 25809 num_cl_bkts *= (bi.num_banks - 1) * NUM_ENT; 25810 } 25811 25812 done: 25813 if (job_done) { 25814 rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num, 25815 entry, entry, NULL); 25816 } else { 25817 rv = SOC_E_FULL; 25818 } 25819 25820 cleanup: 25821 if (bkt_trace) { 25822 sal_free(bkt_trace); 25823 } 25824 25825 if (buckets[0]) { 25826 sal_free(buckets[0]); 25827 } 25828 25829 if (SOC_FAILURE(rv)) { 25830 LOG_VERBOSE(BSL_LS_SOC_COMMON, 25831 (BSL_META_U(unit, 25832 "Insert entry: %d\n"), rv)); 25833 } 25834 25835 return rv; 25836 } 25837 25838 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 25839 #define ENTRIES_PER_BKT_TD3 4 25840 typedef struct _soc_breadth_bucket_td3_s { 25841 soc_mem_t src_mem; 25842 uint8 src_bix; 25843 uint8 td3_status[ENTRIES_PER_BKT_TD3]; 25844 uint8 src_width; 25845 uint8 src_ent; 25846 uint32 src_bkt_idx; 25847 uint32 bucket; 25848 union { 25849 l2x_entry_t* l2[NUM_ENT_TD3]; 25850 l3_entry_quad_entry_t* l3_quad[NUM_ENT_TD3]; 25851 exact_match_2_entry_t* em_2[NUM_ENT_TD3]; 25852 exact_match_4_entry_t* em_4[NUM_ENT_TD3]; 25853 vlan_xlate_1_double_entry_t* vlan[NUM_ENT_TD3]; 25854 egr_vlan_xlate_1_double_entry_t* egr_vlan[NUM_ENT_TD3]; 25855 mpls_entry_entry_t* mpls[NUM_ENT_TD3]; 25856 mpls_entry_single_entry_t* mpls_1[NUM_ENT_TD3]; 25857 l3_entry_only_entry_t* l3[NUM_ENT_TD3]; 25858 #ifdef BCM_TOMAHAWK3_SUPPORT 25859 tunnel_quad_entry_t* tunnel_quad[NUM_ENT_TD3]; 25860 #endif 25861 } e; 25862 } _soc_breadth_bucket_td3_t; 25863 25864 static INLINE int 25865 _soc_mem_shared_hash_init_td3(int unit, 25866 int num_banks, 25867 int num_levels, 25868 _soc_breadth_bucket_td3_t **buckets, 25869 int *total_buckets) 25870 { 25871 static int td3_prev_num_levels = 0; 25872 static int td3_prev_tot_bkts = 0; 25873 static int td3_prev_num_banks = 0; 25874 static _soc_breadth_bucket_td3_t *td3_prev_bkt = NULL; 25875 int alloc_size = 0; 25876 int num_cl_buckets; 25877 int level; 25878 25879 if (!buckets) return (SOC_E_INTERNAL); 25880 if ((td3_prev_num_levels == num_levels) && 25881 (td3_prev_num_banks == num_banks)) { 25882 *buckets = td3_prev_bkt; 25883 *total_buckets = td3_prev_tot_bkts; 25884 return (SOC_E_NONE); 25885 } 25886 25887 if (td3_prev_bkt != NULL) { 25888 sal_free(td3_prev_bkt); 25889 } 25890 25891 num_cl_buckets = num_banks; 25892 for (level = 0; level < num_levels; level++) { 25893 alloc_size += num_cl_buckets; 25894 num_cl_buckets *= (num_banks - 1) * NUM_ENT_TD3; 25895 } 25896 *total_buckets = alloc_size; 25897 alloc_size *= sizeof(_soc_breadth_bucket_td3_t); 25898 25899 *buckets = sal_alloc(alloc_size, "Buckets"); 25900 if (*buckets == NULL) { 25901 return SOC_E_MEMORY; 25902 } 25903 sal_memset(*buckets, 0, alloc_size); 25904 25905 td3_prev_bkt = *buckets; 25906 td3_prev_num_levels = num_levels; 25907 td3_prev_num_banks = num_banks; 25908 td3_prev_tot_bkts = *total_buckets; 25909 25910 return SOC_E_NONE; 25911 } 25912 25913 STATIC void* 25914 _soc_mem_hash_entry_buffer_get(int unit, int mem, _soc_breadth_bucket_td3_t *bkt, int ent) 25915 { 25916 void *se; 25917 if ((mem == L2Xm) || 25918 (mem == L2_ENTRY_SINGLEm) || 25919 (mem == L2_ENTRY_ONLY_SINGLEm)) { 25920 if (!bkt->e.l2[ent]) { 25921 bkt->e.l2[ent] = (l2x_entry_t*)sal_alloc(sizeof(l2x_entry_t), "Buckets L2X"); 25922 sal_memset(bkt->e.l2[ent], 0, sizeof(l2x_entry_t)); 25923 } 25924 se = bkt->e.l2[ent]; 25925 } else if (MEM_IS_EXACT_MATCH_2(mem) || MEM_IS_EXACT_MATCH_4(mem)) { 25926 if (!bkt->e.em_4[ent]) { 25927 bkt->e.em_4[ent] = sal_alloc(sizeof(exact_match_4_entry_t), "Buckets EM Quad"); 25928 sal_memset(bkt->e.em_4[ent], 0, sizeof(exact_match_4_entry_t)); 25929 } 25930 se = bkt->e.em_4[ent]; 25931 } else if (MEM_IS_VLAN_XLATE(mem)) { 25932 if (!bkt->e.vlan[ent]) { 25933 bkt->e.vlan[ent] = sal_alloc(sizeof(vlan_xlate_1_double_entry_t), "Buckets L2E"); 25934 sal_memset(bkt->e.vlan[ent], 0, sizeof(vlan_xlate_1_double_entry_t)); 25935 } 25936 se = bkt->e.vlan[ent]; 25937 } else if (MEM_IS_EGR_VLAN_XLATE(mem)) { 25938 if (!bkt->e.egr_vlan[ent]) { 25939 bkt->e.egr_vlan[ent] = sal_alloc(sizeof(egr_vlan_xlate_1_double_entry_t), "Buckets EGR Vlan"); 25940 sal_memset(bkt->e.egr_vlan[ent], 0, sizeof(egr_vlan_xlate_1_double_entry_t)); 25941 } 25942 se = bkt->e.egr_vlan[ent]; 25943 } else if (MEM_IS_MPLS(mem)) { 25944 if (SOC_IS_TOMAHAWK3(unit)) { 25945 if (!bkt->e.mpls_1[ent]) { 25946 bkt->e.mpls_1[ent] = sal_alloc(sizeof(mpls_entry_single_entry_t), "Buckets MPLS Single"); 25947 sal_memset(bkt->e.mpls_1[ent], 0, sizeof(mpls_entry_single_entry_t)); 25948 } 25949 se = bkt->e.mpls_1[ent]; 25950 } else { 25951 if (!bkt->e.mpls[ent]) { 25952 bkt->e.mpls[ent] = sal_alloc(sizeof(mpls_entry_entry_t), "Buckets MPLS"); 25953 sal_memset(bkt->e.mpls[ent], 0, sizeof(mpls_entry_entry_t)); 25954 } 25955 se = bkt->e.mpls[ent]; 25956 } 25957 } else if (MEM_IS_L3_ENTRY_SINGLE(mem) || 25958 MEM_IS_L3_ENTRY_DOUBLE(mem) || 25959 MEM_IS_L3_ENTRY_QUAD(mem)) { 25960 if (!bkt->e.l3_quad[ent]) { 25961 bkt->e.l3_quad[ent] = sal_alloc(sizeof(l3_entry_quad_entry_t), "Buckets L3 QUAD"); 25962 sal_memset(bkt->e.l3_quad[ent], 0, sizeof(l3_entry_quad_entry_t)); 25963 } 25964 se = bkt->e.l3_quad[ent]; 25965 } else 25966 #ifdef BCM_TOMAHAWK3_SUPPORT 25967 if (MEM_IS_L3_TUNNEL_SINGLE(mem) || 25968 MEM_IS_L3_TUNNEL_DOUBLE(mem) || 25969 MEM_IS_L3_TUNNEL_QUAD(mem)) { 25970 if (!bkt->e.tunnel_quad[ent]) { 25971 bkt->e.tunnel_quad[ent] = sal_alloc(sizeof(tunnel_quad_entry_t), "Buckets L3 Tunnel QUAD"); 25972 sal_memset(bkt->e.tunnel_quad[ent], 0, sizeof(tunnel_quad_entry_t)); 25973 } 25974 se = bkt->e.tunnel_quad[ent]; 25975 } else 25976 #endif 25977 { 25978 if (!bkt->e.l3[ent]) { 25979 bkt->e.l3[ent] = sal_alloc(sizeof(l3_entry_only_entry_t), "Buckets L3"); 25980 sal_memset(bkt->e.l3[ent], 0, sizeof(l3_entry_only_entry_t)); 25981 } 25982 se = bkt->e.l3[ent]; 25983 } 25984 return (se); 25985 } 25986 25987 extern int soc_td3_tbl_entries_per_sram_entry_get(int unit, soc_mem_t mem, 25988 int *table_entries_per_sram_entry); 25989 25990 #define MAX_MIX_LEVELS_TD3 6 25991 #define TD3_ENTRIES_PER_BUCKET 4 25992 /*************************************************************************************** 25993 * _soc_mem_shared_hash_td3_breadth_mix_move * 25994 * * 25995 * S/W re-order algorithm to enhance the efficiency of UAT/UFT HASH tables. * 25996 * TD3 - a bucket has 4 entries irrespective of Single Double or Quad wide. * 25997 * * 25998 * TD3 uses similar algorithm as used in TH. In TH - number of entries in a bucket * 25999 * could be 1 quad or 4 single or a mix.., A maximum of 4 entries per bucket. In TD3 * 26000 * there could be a maximum of 16 entries in a quad based bucket. So NUM_ENT_TD3 is 16 * 26001 * * 26002 * If source entry is single wide - 1 quad wide entry represents a bucket. * 26003 * so 1 quad wide entry will be attempted to move to other banks in every level. * 26004 * * 26005 * If source entry is double wide - 2 quad wide entry represents a bucket. * 26006 * so 2 quad wide entries will be attempted to move to other banks in level-1. * 26007 * only 1 quad wide entry will be attempted to move to other banks in all levels. * 26008 * * 26009 * If source entry is quad wide - 4 quad wide entry represents a bucket. * 26010 * so 4 quad wide entries will be attempted to move to other banks in level-1. * 26011 * only 1 quad wide entry will be attempted to move to other banks in all levels. * 26012 */ 26013 sal_mutex_t td3_hash_mutex[SOC_MAX_NUM_DEVICES] = {NULL}; 26014 26015 int 26016 soc_td3_hash_mutex_init (int unit) 26017 { 26018 if (unit >= SOC_MAX_NUM_DEVICES) { 26019 return (SOC_E_INTERNAL); 26020 } 26021 if (td3_hash_mutex[unit] != NULL) { 26022 sal_mutex_destroy(td3_hash_mutex[unit]); 26023 } 26024 td3_hash_mutex[unit] = sal_mutex_create("td3_hash_mutex"); 26025 return (SOC_E_NONE); 26026 } 26027 26028 #define TD3_HASH_LOCK(unit) sal_mutex_take(td3_hash_mutex[unit], sal_mutex_FOREVER); 26029 #define TD3_HASH_UNLOCK(unit) sal_mutex_give(td3_hash_mutex[unit]); 26030 26031 STATIC int 26032 _soc_mem_shared_hash_td3_breadth_mix_move(int unit, soc_mem_t mem, int copyno, 26033 void *entry, int num_levels) 26034 { 26035 SHR_BITDCL *bkt_trace = NULL; 26036 _soc_breadth_bucket_td3_t *buckets[MAX_MIX_LEVELS_TD3 + 1] = {0}; 26037 _soc_breadth_bucket_td3_t *cb, *tb, *cbi = NULL, *pbi; 26038 uint32 bkt_entry[ENTRIES_PER_BKT_TD3][SOC_MAX_MEM_WORDS]; 26039 uint32 v[NUM_ENT_TD3], w[NUM_ENT_TD3]; 26040 void *se, *me; 26041 int rv; 26042 int level, job_done = 0; 26043 int move_bkt; 26044 int bank_num, ibank_num = 0; 26045 int bix, cbix; 26046 int free = 0, moved = 0; 26047 int bkt_idx, bkt_idx1 = 0, bkt_idx2 = 0; 26048 int nl_bkt_idx, num_cl_bkts, total_buckets; 26049 int wide_entry; 26050 uint32 bucket, base_mem_bkt = 0; 26051 int ent, ent_incr, max_entries_per_row = 4; 26052 int num = 0, tbl_entries_per_sram_entry = 0; 26053 int i, j, sok, num_rows_per_bkt, row_idx; 26054 _soc_hash_bank_info_t bi = {0}; 26055 soc_mem_t src_mem, base_mem; 26056 int vld_flds[5] = {BASE_VALID_0f, BASE_VALID_1f, BASE_VALID_2f, BASE_VALID_3f, BASE_VALIDf}; 26057 26058 if (num_levels <= 0) { 26059 return SOC_E_FULL; 26060 } 26061 if (num_levels > MAX_MIX_LEVELS_TD3) { 26062 LOG_VERBOSE(BSL_LS_SOC_COMMON, 26063 (BSL_META_U(unit, 26064 "ERROR: Invalid Level %d (max=%d)\n"), 26065 num_levels, MAX_MIX_LEVELS_TD3)); 26066 return SOC_E_FULL; 26067 } 26068 26069 /* 26070 * UFT provides single, double and quad table entries. 26071 * UAT provides single and double table entries only. 26072 * wide_entry represents quad entry for UFT and double entry for UAT. 26073 */ 26074 #if defined (BCM_TOMAHAWK3_SUPPORT) 26075 if (SOC_IS_TOMAHAWK3(unit)) { 26076 if (MEM_IS_MPLS(mem)) { 26077 max_entries_per_row = 1; 26078 } 26079 } else 26080 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26081 if (MEM_IS_MPLS(mem) || MEM_IS_VLAN_XLATE(mem) || 26082 MEM_IS_EGR_VLAN_XLATE(mem)) { 26083 max_entries_per_row = 2; 26084 } 26085 26086 base_mem = _soc_mem_hash_base_mem_get(unit, mem); 26087 26088 TD3_HASH_LOCK(unit); 26089 SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init 26090 (unit, base_mem, &bkt_trace, &bi, num_levels, NULL, NULL)); 26091 26092 /* 26093 * Based on the number of banks, curb the num_levels, otherwise 26094 * memory usage will be over blown. 26095 * 26096 * For instance number of banks is 10.., then the buckets to be 26097 * allocated for level 1 is 16 * 9 = 144. For level 2 it will be 26098 * 144 * 144. For level 6 it will be 144^6. This is not practical. 26099 * System will run out of memory. So the following rule will be applied. 26100 * 26101 * if num_banks >4 ==> num_levels will be limited to 2. 26102 * if num_banks >= 2 and <= 4 ==> num_levels will be limited to 4. 26103 * else num_levels will be MAX_MIX_LEVELS_TD3. 26104 */ 26105 if (bi.num_banks > 4) { 26106 if (num_levels > 2) { 26107 num_levels = 2; 26108 LOG_VERBOSE(BSL_LS_SOC_COMMON, 26109 (BSL_META_U(unit, 26110 "WARNING: Level is limited to %d \n"), num_levels)); 26111 } 26112 } else if ((bi.num_banks >= 3) && (bi.num_banks <= 4)) { 26113 if (num_levels > 4) { 26114 num_levels = 4; 26115 LOG_VERBOSE(BSL_LS_SOC_COMMON, 26116 (BSL_META_U(unit, 26117 "WARNING: Level is limited to %d \n"), num_levels)); 26118 } 26119 } 26120 26121 rv = _soc_mem_shared_hash_init_td3(unit, 26122 bi.num_banks, num_levels, 26123 &buckets[0], &total_buckets); 26124 if (SOC_FAILURE(rv)) { 26125 if (bkt_trace) { 26126 sal_free(bkt_trace); 26127 } 26128 return (rv); 26129 } 26130 26131 num_cl_bkts = bi.num_banks; 26132 26133 for (level = 0; level < num_levels; level++) { 26134 if (level + 1 < num_levels) { 26135 buckets[level + 1] = buckets[level] + num_cl_bkts; 26136 } else { 26137 buckets[level + 1] = 0; 26138 } 26139 26140 /* 26141 * Loop here for the number of buckets in a given level. 26142 * 26143 * Level 0 : entry can be added to all banks. Bucket has 4 entries. 26144 * Level 0 - entry has (num_of_banks * 4) locations to insert. 26145 * 26146 * Level 1 : Every entry from level 0 has (num_of_banks-1 *4) locations 26147 * to insert. (total num_of_banks*4)*(num_of_banks-1)*4. 26148 * 26149 * Level 2 : Recursive iteration as level 1. Every entry from level 1 has 26150 * (num_of_banks-1)*4 locations in level 2. 26151 * 26152 * num_cl_bkts represents the number of buckets for the given level 26153 * as per the iterative calculation described above. 26154 */ 26155 for (bkt_idx = 0; bkt_idx < num_cl_bkts; bkt_idx++) { 26156 cb = &buckets[level][bkt_idx]; 26157 if (level == 0) { 26158 cb->src_bix = bkt_idx; 26159 cb->src_mem = mem; 26160 cb->src_width = _soc_mem_hash_mem_width_get(unit, cb->src_mem); 26161 se = entry; 26162 } else { 26163 if (cb->src_mem == 0) { 26164 continue; 26165 } 26166 se = _soc_mem_hash_entry_buffer_get(unit, cb->src_mem, 26167 &buckets[level-1][cb->src_bkt_idx], cb->src_ent); 26168 } 26169 26170 /* 26171 * Clear the valid array and entry width array. 26172 * 26173 * UFT: Every quad entry can hold, 26174 * 4 single entries, 2 double entries, 1 quad entry. 26175 * 2 single entries and 1 double entries, 26176 * There could be locations with no valid entry too. 26177 * 26178 * V[4] : represents if there is a valid entry in the 4 base entries(single). 26179 * w[4] : represents the width of the valid entries in the quad wide entry. 26180 * Entry width is 1 for Single entry, 2 for Double and 4 for Quad entry. 26181 * 26182 * For instance a Quad wide Row has | Single | No Entry | DOUBLE ENTRY | 26183 * Valid bits will be represented as V[4] = {1,0,1,1} 26184 * Width bits will be represented as W[4] = {1,0,0,2} 26185 * 26186 * UFT: Every double entry can hold, 26187 * 2 single entries, 1 double entries 26188 * There could be locations with no valid entry too (one single entry). 26189 * 26190 * V : represents if there is a valid entry in the 2 base entries(single). 26191 * w : represents the width of the valid entries in the double wide entry. 26192 * Entry width is 1 for Single entry, 2 for Double entry. 26193 * 26194 * For instance a Double wide Row has | Single | No Entry | 26195 * Valid bits will be represented as V[2] = {1,0} 26196 * Width bits will be represented as W[2] = {1,0} 26197 * 26198 * For instance a Double wide Row has | Double Entry | 26199 * Valid bits will be represented as V[2] = {1,1} 26200 * Width bits will be represented as W[2] = {2,0} 26201 */ 26202 for (i = 0; i < NUM_ENT_TD3; i++) { 26203 w[i]=0; /* entry width */ 26204 v[i]=0; /* entry valid */ 26205 } 26206 26207 bank_num = bi.bank_nums[cb->src_bix]; 26208 bucket = _soc_mem_shared_hash_bucket(unit, cb->src_mem, bank_num, se); 26209 26210 rv = SOC_E_UNAVAIL; 26211 26212 #ifdef BCM_TOMAHAWK3_SUPPORT 26213 if (SOC_IS_TOMAHAWK3(unit)) { 26214 rv = soc_tomahawk3_tbl_entries_per_sram_entry_get(unit, cb->src_mem, 26215 &tbl_entries_per_sram_entry); 26216 } else 26217 #endif 26218 { 26219 #ifdef BCM_TRIDENT3_SUPPORT 26220 rv = soc_td3_tbl_entries_per_sram_entry_get(unit, cb->src_mem, 26221 &tbl_entries_per_sram_entry); 26222 #endif 26223 } 26224 26225 if (SOC_FAILURE(rv)) { 26226 if (bkt_trace) { 26227 sal_free(bkt_trace); 26228 } 26229 return (rv); 26230 } 26231 26232 /* 26233 * In order to identify if the entry is a single, double or Quad, 26234 * a quad wide entry has to be read. So all buckets are read as 26235 * Quad wide entry. 26236 * 26237 * num_rows_per_bkt : represents the number of quad wide entries 26238 * required to represent a bucket. 26239 * 1 for single, 2 for double and 4 for quad. 26240 */ 26241 #if defined(BCM_TOMAHAWK3_SUPPORT) 26242 if (SOC_IS_TOMAHAWK3(unit)) { 26243 if (MEM_IS_MPLS(cb->src_mem)) { 26244 num_rows_per_bkt = 4/tbl_entries_per_sram_entry; 26245 bucket *= 26246 _soc_mem_shared_hash_entries_per_bkt(unit, cb->src_mem); 26247 } else { 26248 num_rows_per_bkt = 1; 26249 } 26250 26251 if (SHR_BITGET(bkt_trace, bucket)) { 26252 continue; 26253 } 26254 SHR_BITSET(bkt_trace, bucket); 26255 } else 26256 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26257 { 26258 num_rows_per_bkt = 4/tbl_entries_per_sram_entry; 26259 26260 base_mem_bkt = bucket/tbl_entries_per_sram_entry; 26261 if (SHR_BITGET(bkt_trace, base_mem_bkt)) { 26262 continue; 26263 } 26264 SHR_BITSET(bkt_trace, base_mem_bkt); 26265 } 26266 26267 26268 if (tbl_entries_per_sram_entry == 4) { 26269 row_idx = bucket & 3; 26270 } else if (tbl_entries_per_sram_entry == 2) { 26271 row_idx = (bucket & 1)*2; 26272 } else { 26273 row_idx = 0; 26274 } 26275 26276 cb->bucket = bucket; 26277 26278 /* Read all entries in a bucket */ 26279 memset(bkt_entry, 0, sizeof(bkt_entry)); 26280 for (wide_entry = 0; wide_entry < num_rows_per_bkt; wide_entry++) { 26281 #if defined(BCM_TOMAHAWK3_SUPPORT) 26282 if (SOC_IS_TOMAHAWK3(unit)) { 26283 rv = soc_mem_read(unit, base_mem, copyno, 26284 bucket + wide_entry, 26285 bkt_entry[wide_entry]); 26286 } else 26287 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26288 { 26289 rv = soc_mem_read(unit, base_mem, copyno, 26290 (base_mem_bkt * 4) + row_idx + wide_entry, 26291 bkt_entry[wide_entry]); 26292 } 26293 if (SOC_FAILURE(rv)) { 26294 goto cleanup; 26295 } 26296 26297 /* Read all base_valid information for the given entry */ 26298 for (i = 0; i < max_entries_per_row; i++) { 26299 if (soc_mem_field_valid(unit, base_mem, vld_flds[i])) { 26300 soc_mem_field_get (unit, base_mem, bkt_entry[wide_entry], 26301 vld_flds[i], 26302 &v[(wide_entry*max_entries_per_row)+i]); 26303 } else if (soc_mem_field_valid(unit, base_mem, vld_flds[4])) { 26304 soc_mem_field_get (unit, base_mem, bkt_entry[wide_entry], 26305 vld_flds[4], 26306 &v[(wide_entry*max_entries_per_row)+i]); 26307 } 26308 26309 } 26310 26311 /* 26312 * A valid entry starts with a start_of_key (sok). 26313 * To identify the type of entry, we need to identify the sok 26314 * and traverse to the next entries. 26315 * 26316 * In TD3, every single entry wide may not have Key_type information. 26317 * So only base valid fields should be used to identify if the entry 26318 * is single, double or quad wide. 26319 * 26320 * For Instance: 26321 * Single Wide Entry : BASE_VALID_0 : 1 26322 * Double Wide Entry : BASE_VALID_1 : 4, BASE_VALID_0 : 3 26323 * Quad Wide Entry : BASE_VALID_1 : 6, BASE_VALID_0 : 5 26324 * Quad Wide Entry : BASE_VALID_3 : 7, BASE_VALID_2 : 6 26325 * 26326 * BASE Valid value of 1,3,5 represent start of key. 26327 * Base Valid value of 4,6 represent key+data (extension). 26328 * Base Valid value of 7 represent data only(extension). 26329 */ 26330 sok=-1; /* start of key */ 26331 for (i = 0; i < max_entries_per_row; i++) { 26332 if (!v[wide_entry*max_entries_per_row + i]) { 26333 w[wide_entry*max_entries_per_row + i]=0; 26334 sok = -1; 26335 } else if ((v[wide_entry*max_entries_per_row + i] != 7) && 26336 (v[wide_entry*max_entries_per_row + i] & 1)) { 26337 w[wide_entry*max_entries_per_row + i]= 1; 26338 sok = wide_entry*max_entries_per_row + i; 26339 } else { 26340 if (sok == -1) 26341 w[wide_entry*max_entries_per_row + i] = 0; 26342 else { 26343 w[sok] += 1; 26344 } 26345 } 26346 } 26347 26348 /* Once width is identified, make valid array a bit representation */ 26349 for (i = 0; i < max_entries_per_row; i++) { 26350 v[wide_entry*max_entries_per_row + i] = 26351 v[wide_entry*max_entries_per_row + i] ? 1 : 0; 26352 } 26353 cb->td3_status[wide_entry] = 0; 26354 for (i = 0; i < max_entries_per_row; i++) { 26355 cb->td3_status[wide_entry] |= 26356 (v[(wide_entry*max_entries_per_row)+i] << i); 26357 } 26358 } 26359 26360 /* 26361 * For UFT: a Quad entry bucket has 4 quad entries and it could have 26362 * upto 16 valid single entries in the quad bucket. 26363 * For UAT: a Double entry bucket has 4 double entries and it could have 26364 * upto 8 valid single entries in the quad bucket. 26365 * 26366 * num_rows_per_bkt*max_entries_per_row gives possible number of 26367 * valid single entries in the bucket. So traverse through all possible 26368 * valid entries.., 26369 */ 26370 for (ent = 0; ent < (num_rows_per_bkt*max_entries_per_row); ent++) { 26371 if (!w[ent]) { 26372 continue; 26373 } 26374 26375 me = _soc_mem_hash_entry_buffer_get(unit, cb->src_mem, cb, ent); 26376 26377 rv = SOC_E_UNAVAIL; 26378 #ifdef BCM_TOMAHAWK3_SUPPORT 26379 if (SOC_IS_TOMAHAWK3(unit)) { 26380 rv = soc_tomahawk3_shared_hash_mem_bucket_read (unit, 26381 ent%max_entries_per_row, w[ent], &ent_incr, base_mem, 26382 &src_mem, bkt_entry[ent/max_entries_per_row], me); 26383 } else 26384 #endif 26385 { 26386 #ifdef BCM_TRIDENT3_SUPPORT 26387 rv = soc_td3_shared_hash_mem_bucket_read (unit, 26388 ent%max_entries_per_row, w[ent], &ent_incr, base_mem, 26389 &src_mem, bkt_entry[ent/max_entries_per_row], me); 26390 #endif 26391 } 26392 if (SOC_FAILURE(rv)) { 26393 goto cleanup; 26394 } 26395 ent_incr = w[ent]; 26396 26397 rv = soc_mem_generic_insert(unit, src_mem, copyno, 26398 bi.banks & ~(1 << bank_num), 26399 me, NULL, &move_bkt); 26400 moved = 0; 26401 free = 0; 26402 26403 if (SOC_SUCCESS(rv)) { 26404 26405 /* TD3 every bucket has 4 entries. Divide index by 4 to get bucket # */ 26406 #if defined(BCM_TOMAHAWK3_SUPPORT) 26407 if (SOC_IS_TOMAHAWK3(unit)) { 26408 move_bkt /= tbl_entries_per_sram_entry; 26409 } else 26410 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26411 { 26412 move_bkt /= TD3_ENTRIES_PER_BUCKET; 26413 } 26414 26415 if (SHR_BITGET(bkt_trace, move_bkt)) { 26416 rv = soc_mem_generic_delete(unit, src_mem, 26417 MEM_BLOCK_ANY, 26418 bi.banks & ~(1 << bank_num), 26419 me, NULL, NULL); 26420 if (SOC_FAILURE(rv)) { 26421 goto cleanup; 26422 } 26423 } else { 26424 rv = soc_mem_generic_delete(unit, src_mem, 26425 MEM_BLOCK_ANY, 26426 1 << bank_num, me, 26427 NULL, NULL); 26428 if (SOC_FAILURE(rv)) { 26429 goto cleanup; 26430 } 26431 moved = 1; 26432 cb->td3_status[ent/max_entries_per_row] &= 26433 ~(((1 << ent_incr) - 1) << 26434 (ent%max_entries_per_row)); 26435 26436 _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, cb->src_mem, 26437 cb->td3_status[ent/max_entries_per_row]); 26438 } 26439 } 26440 26441 if (!free) { 26442 if (!moved) { 26443 /* Construct buckets in next level for this entry */ 26444 nl_bkt_idx = bkt_idx * (bi.num_banks-1) * NUM_ENT_TD3 + 26445 (ent) * (bi.num_banks-1); 26446 26447 for (bix = 0; bix < bi.num_banks && buckets[level + 1]; bix++) { 26448 cbix = cb->src_bix + bix + 1; 26449 cbix = cbix % bi.num_banks; 26450 if (bank_num == bi.bank_nums[cbix]) { 26451 continue; 26452 } 26453 tb = &buckets[level + 1][nl_bkt_idx++]; 26454 tb->src_bkt_idx = bkt_idx; 26455 tb->src_bix = cbix; 26456 tb->src_mem = src_mem; 26457 tb->src_width= ent_incr; 26458 tb->src_ent = ent; 26459 } 26460 } 26461 continue; 26462 } 26463 26464 ibank_num = bank_num; 26465 pbi = cb; 26466 for (i = level; i > 0; i--) { 26467 cbi = pbi; 26468 pbi = &buckets[i - 1][cbi->src_bkt_idx]; 26469 26470 me = _soc_mem_hash_entry_buffer_get(unit, cbi->src_mem, 26471 pbi, cbi->src_ent); 26472 26473 rv = soc_mem_bank_insert(unit, cbi->src_mem, 26474 (1 << ibank_num), copyno, 26475 me, NULL); 26476 if (SOC_FAILURE(rv)) { 26477 goto cleanup; 26478 } 26479 26480 ibank_num = bi.bank_nums[pbi->src_bix]; 26481 26482 rv = soc_mem_generic_delete(unit, cbi->src_mem, 26483 MEM_BLOCK_ANY, 26484 (1 << ibank_num), 26485 me, NULL, NULL); 26486 if (SOC_FAILURE(rv)) { 26487 goto cleanup; 26488 } 26489 26490 pbi->td3_status[cbi->src_ent/max_entries_per_row] &= 26491 ~(((1 << cbi->src_width) - 1) << 26492 (cbi->src_ent%max_entries_per_row)); 26493 26494 _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, pbi->src_mem, 26495 pbi->td3_status[cbi->src_ent/max_entries_per_row]); 26496 26497 if (!free) { 26498 break; 26499 } 26500 } 26501 26502 /* now i is the toppest level with free slot available */ 26503 26504 if (free) { 26505 job_done = 1; 26506 goto done; 26507 } else { 26508 /* cbi --> level i; pbi --> level i - 1. 26509 * cbi is the toppest bucket with entry moved. 26510 * pbi is the bucket with entry removed. 26511 * Entire sub tree of pbi's removed entry needs be skipped. 26512 */ 26513 for (j = i; j <= level; j++) { 26514 if (j == i) { 26515 num = (bi.num_banks - 1); 26516 bkt_idx1 = (cbi->src_bkt_idx * ((bi.num_banks - 1) * NUM_ENT_TD3)) + 26517 ((cbi->src_ent) * (bi.num_banks - 1)); 26518 bkt_idx2 = bkt_idx1 + (cbi->src_width * (bi.num_banks - 1)); 26519 } else { 26520 num *= (bi.num_banks - 1) * NUM_ENT_TD3; 26521 bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT_TD3; 26522 bkt_idx2 *= (bi.num_banks - 1) * NUM_ENT_TD3; 26523 } 26524 } 26525 26526 /* assert (bkt_idx2 > bkt_idx && bkt_idx >= bkt_idx1); */ 26527 if (buckets[j]) { 26528 num *= (bi.num_banks - 1) * NUM_ENT_TD3; 26529 bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT_TD3; 26530 sal_memset(&buckets[j][bkt_idx1], 0, 26531 num * sizeof(_soc_breadth_bucket_td3_t)); 26532 } 26533 bkt_idx = bkt_idx2 - 1; 26534 break; 26535 } 26536 } 26537 } 26538 num_cl_bkts *= (bi.num_banks - 1) * NUM_ENT_TD3; 26539 } 26540 26541 done: 26542 if (job_done) { 26543 rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num, 26544 entry, entry, NULL); 26545 } else { 26546 rv = SOC_E_FULL; 26547 } 26548 26549 cleanup: 26550 if (bkt_trace) { 26551 sal_free(bkt_trace); 26552 } 26553 26554 if (buckets[0]) { 26555 cb = buckets[0]; 26556 for (i = 0; i < total_buckets; i++, cb++){ 26557 if (cb->src_mem) { 26558 for (ent = 0; ent < NUM_ENT_TD3; ent++){ 26559 if (cb->e.l2[ent]) { 26560 sal_free(cb->e.l2[ent]); 26561 cb->e.l2[ent] = NULL; 26562 } 26563 } 26564 memset(cb, 0, sizeof(_soc_breadth_bucket_td3_t)); 26565 } 26566 } 26567 } 26568 26569 TD3_HASH_UNLOCK(unit); 26570 if (SOC_FAILURE(rv)) { 26571 LOG_VERBOSE(BSL_LS_SOC_COMMON, 26572 (BSL_META_U(unit, 26573 "Insert entry: %d\n"), rv)); 26574 } 26575 return rv; 26576 } 26577 #endif /* defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) */ 26578 26579 #ifdef BCM_TOMAHAWK3_SUPPORT 26580 int 26581 soc_tomahawk3_hash_mutex_init (int unit) 26582 { 26583 return soc_td3_hash_mutex_init(unit); 26584 } 26585 26586 STATIC int 26587 _soc_mem_shared_hash_tomahawk3_breadth_mix_move(int unit, soc_mem_t mem, int copyno, 26588 void *entry, int num_levels) 26589 { 26590 return _soc_mem_shared_hash_td3_breadth_mix_move(unit, mem, copyno, entry, num_levels); 26591 } 26592 26593 #endif /* BCM_TOMAHAWK3_SUPPORT */ 26594 26595 STATIC int 26596 _soc_mem_shared_hash_breadth_mix_move(int unit, soc_mem_t mem, int copyno, 26597 void *entry, int num_levels) 26598 { 26599 SHR_BITDCL *bkt_trace = NULL; 26600 _soc_breadth_bucket_t *buckets[MAX_MIX_LEVELS + 1] = {0}; 26601 _soc_breadth_bucket_t *cb, *tb, *cbi = NULL, *pbi; 26602 uint32 bkt_entry[NUM_ENT][SOC_MAX_MEM_WORDS]; 26603 uint32 v[NUM_ENT], k[NUM_ENT]; 26604 void *se, *me; 26605 int rv; 26606 int level, job_done = 0; 26607 int move_bkt; 26608 int bank_num, ibank_num = 0; 26609 int bix, cbix; 26610 int free = 0, moved = 0; 26611 int bkt_idx, bkt_idx1 = 0, bkt_idx2 = 0; 26612 int nl_bkt_idx, num_cl_bkts; 26613 int ent, ent_incr, bucket; 26614 int num = 0; 26615 int i, j; 26616 int vld_fld_0 = VALID_0f; 26617 int key_type_0 = KEY_TYPE_0f; 26618 _soc_hash_bank_info_t bi = {0}; 26619 soc_mem_t src_mem, base_mem; 26620 #if defined(BCM_TOMAHAWK_SUPPORT) 26621 int pipenum = -1; 26622 #endif 26623 if (num_levels <= 0) { 26624 return SOC_E_FULL; 26625 } else if (num_levels > MAX_MIX_LEVELS) { 26626 return _soc_mem_shared_hash_breadth_mix_move2(unit, mem, copyno, 26627 entry, num_levels); 26628 } 26629 26630 base_mem = _soc_mem_hash_base_mem_get(unit, mem); 26631 #if defined(BCM_TOMAHAWK_SUPPORT) 26632 if (base_mem == EXACT_MATCH_4m) { 26633 switch (mem) { 26634 case EXACT_MATCH_4_PIPE0m: 26635 case EXACT_MATCH_2_PIPE0m: 26636 base_mem = EXACT_MATCH_4_PIPE0m; 26637 pipenum = 0; 26638 break; 26639 case EXACT_MATCH_4_PIPE1m: 26640 case EXACT_MATCH_2_PIPE1m: 26641 base_mem = EXACT_MATCH_4_PIPE1m; 26642 pipenum = 1; 26643 break; 26644 case EXACT_MATCH_4_PIPE2m: 26645 case EXACT_MATCH_2_PIPE2m: 26646 base_mem = EXACT_MATCH_4_PIPE2m; 26647 pipenum = 2; 26648 break; 26649 case EXACT_MATCH_4_PIPE3m: 26650 case EXACT_MATCH_2_PIPE3m: 26651 base_mem = EXACT_MATCH_4_PIPE3m; 26652 pipenum = 3; 26653 break; 26654 default: 26655 break; 26656 } 26657 } 26658 #endif 26659 26660 SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init 26661 (unit, base_mem, &bkt_trace, &bi, num_levels, &buckets[0], NULL)); 26662 26663 num_cl_bkts = bi.num_banks; 26664 26665 for (level = 0; level < num_levels; level++) { 26666 if (level + 1 < num_levels) { 26667 buckets[level + 1] = buckets[level] + num_cl_bkts; 26668 } else { 26669 buckets[level + 1] = 0; 26670 } 26671 26672 for (bkt_idx = 0; bkt_idx < num_cl_bkts; bkt_idx++) { 26673 cb = &buckets[level][bkt_idx]; 26674 if (level == 0) { 26675 cb->src_bix = bkt_idx; 26676 cb->src_mem = mem; 26677 cb->src_width = _soc_mem_hash_mem_width_get(unit, mem); 26678 se = entry; 26679 } else { 26680 if (cb->src_mem == 0) { 26681 continue; 26682 } 26683 #ifdef BCM_TOMAHAWK_SUPPORT 26684 if (MEM_IS_EXACT_MATCH_4(mem)) { 26685 se = &buckets[level - 1][cb->src_bkt_idx].e.em_4[cb->src_ent]; 26686 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 26687 se = &buckets[level - 1][cb->src_bkt_idx].e.em_2[cb->src_ent]; 26688 } else 26689 #endif 26690 { 26691 se = &buckets[level - 1][cb->src_bkt_idx].e.l3[cb->src_ent]; 26692 } 26693 } 26694 26695 bank_num = bi.bank_nums[cb->src_bix]; 26696 bucket = _soc_mem_shared_hash_bucket(unit, cb->src_mem, bank_num, se); 26697 if (SHR_BITGET(bkt_trace, bucket)) { 26698 continue; 26699 } 26700 SHR_BITSET(bkt_trace, bucket); 26701 cb->bucket = bucket; 26702 if (MEM_IS_EXACT_MATCH_4(mem)) { 26703 rv = soc_mem_read(unit, base_mem, copyno, 26704 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4, bkt_entry[0]); 26705 if (SOC_FAILURE(rv)) { 26706 goto cleanup; 26707 } 26708 rv = soc_mem_read(unit, base_mem, copyno, 26709 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 1, 26710 bkt_entry[1]); 26711 if (SOC_FAILURE(rv)) { 26712 goto cleanup; 26713 } 26714 rv = soc_mem_read(unit, base_mem, copyno, 26715 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 2, 26716 bkt_entry[2]); 26717 if (SOC_FAILURE(rv)) { 26718 goto cleanup; 26719 } 26720 rv = soc_mem_read(unit, base_mem, copyno, 26721 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 3, 26722 bkt_entry[3]); 26723 if (SOC_FAILURE(rv)) { 26724 goto cleanup; 26725 } 26726 soc_mem_field_get(unit, base_mem, bkt_entry[3], vld_fld_0, &v[3]); 26727 soc_mem_field_get(unit, base_mem, bkt_entry[2], vld_fld_0, &v[2]); 26728 soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_0, &v[1]); 26729 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]); 26730 soc_mem_field_get(unit, base_mem, bkt_entry[3], key_type_0, &k[3]); 26731 soc_mem_field_get(unit, base_mem, bkt_entry[2], key_type_0, &k[2]); 26732 soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_0, &k[1]); 26733 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]); 26734 26735 } else if (MEM_IS_EXACT_MATCH_2(mem)){ 26736 rv = soc_mem_read(unit, base_mem, copyno, 26737 bucket * SRAM_ENTRIES_PER_BUCKET_EM_2, bkt_entry[0]); 26738 if (SOC_FAILURE(rv)) { 26739 goto cleanup; 26740 } 26741 rv = soc_mem_read(unit, base_mem, copyno, 26742 bucket * SRAM_ENTRIES_PER_BUCKET_EM_2 + 1, 26743 bkt_entry[1]); 26744 if (SOC_FAILURE(rv)) { 26745 goto cleanup; 26746 } 26747 26748 soc_mem_field_get(unit, base_mem, bkt_entry[1], VALID_2f, &v[3]); 26749 soc_mem_field_get(unit, base_mem, bkt_entry[1], VALID_0f, &v[2]); 26750 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_2f, &v[1]); 26751 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_0f, &v[0]); 26752 soc_mem_field_get(unit, base_mem, bkt_entry[1], KEY_TYPE_2f, &k[3]); 26753 soc_mem_field_get(unit, base_mem, bkt_entry[1], KEY_TYPE_0f, &k[2]); 26754 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_2f, &k[1]); 26755 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_0f, &k[0]); 26756 26757 } else { 26758 rv = soc_mem_read(unit, base_mem, copyno, bucket, bkt_entry[0]); 26759 if (SOC_FAILURE(rv)) { 26760 goto cleanup; 26761 } 26762 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_3f, &v[3]); 26763 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_2f, &v[2]); 26764 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_1f, &v[1]); 26765 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_0f, &v[0]); 26766 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_3f, &k[3]); 26767 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_2f, &k[2]); 26768 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_1f, &k[1]); 26769 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_0f, &k[0]); 26770 26771 } 26772 26773 cb->status = (v[3] << 3) | (v[2] << 2) | (v[1] << 1) | (v[0] << 0); 26774 26775 for (ent = 0; ent < NUM_ENT; ent += ent_incr) { 26776 if (!v[ent]) { 26777 ent_incr = 1; 26778 continue; 26779 } 26780 #ifdef BCM_TOMAHAWK_SUPPORT 26781 if (MEM_IS_EXACT_MATCH_4(mem)) { 26782 me = &cb->e.em_4[ent]; 26783 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 26784 me = &cb->e.em_2[ent]; 26785 } else 26786 #endif 26787 { 26788 me = &cb->e.l3[ent]; 26789 } 26790 26791 #if defined(BCM_TOMAHAWK_SUPPORT) 26792 if (MEM_IS_EXACT_MATCH_4(mem)) { 26793 me = &cb->e.em_4[ent]; 26794 _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent], 26795 &ent_incr, &src_mem, 26796 bkt_entry[ent], 26797 me, pipenum); 26798 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 26799 me = &cb->e.em_2[ent]; 26800 _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent], 26801 &ent_incr, &src_mem, 26802 bkt_entry[ent / SRAM_ENTRIES_PER_BUCKET_EM_2], 26803 me, pipenum); 26804 } else 26805 #endif 26806 { 26807 _soc_mem_shared_hash_l3_bucket_read(unit, ent, k[ent], 26808 &ent_incr, &src_mem, bkt_entry[0], me); 26809 } 26810 26811 rv = soc_mem_generic_insert(unit, src_mem, copyno, 26812 bi.banks & ~(1 << bank_num), 26813 me, NULL, &move_bkt); 26814 moved = 0; 26815 free = 0; 26816 if (SOC_SUCCESS(rv)) { 26817 26818 move_bkt /= _soc_mem_shared_hash_entries_per_bkt(unit, src_mem); 26819 if (SHR_BITGET(bkt_trace, move_bkt)) { 26820 rv = soc_mem_generic_delete(unit, src_mem, MEM_BLOCK_ANY, 26821 bi.banks & ~(1 << bank_num), 26822 me, NULL, NULL); 26823 26824 if (SOC_FAILURE(rv)) { 26825 goto cleanup; 26826 } 26827 } else { 26828 rv = soc_mem_generic_delete(unit, src_mem, MEM_BLOCK_ANY, 26829 1 << bank_num, me, NULL, NULL); 26830 if (SOC_FAILURE(rv)) { 26831 goto cleanup; 26832 } 26833 moved = 1; 26834 cb->status &= ~(((1 << ent_incr) - 1) << ent); 26835 26836 _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, cb->src_mem, cb->status); 26837 26838 } 26839 } 26840 26841 if (!free) { 26842 if (!moved) { 26843 /* Construct buckets in next level for this entry */ 26844 nl_bkt_idx = bkt_idx * (bi.num_banks - 1) * NUM_ENT + 26845 ent * (bi.num_banks - 1); 26846 26847 for (bix = 0; bix < bi.num_banks && buckets[level + 1]; bix++) { 26848 cbix = cb->src_bix + bix + 1; 26849 cbix = cbix % bi.num_banks; 26850 if (bank_num == bi.bank_nums[cbix]) { 26851 continue; 26852 } 26853 26854 tb = &buckets[level + 1][nl_bkt_idx++]; 26855 tb->src_bkt_idx = bkt_idx; 26856 tb->src_bix = cbix; 26857 tb->src_mem = src_mem; 26858 tb->src_width= ent_incr; 26859 tb->src_ent = ent; 26860 } 26861 } 26862 continue; 26863 } 26864 26865 ibank_num = bank_num; 26866 pbi = cb; 26867 for (i = level; i > 0; i--) { 26868 cbi = pbi; 26869 pbi = &buckets[i - 1][cbi->src_bkt_idx]; 26870 #ifdef BCM_TOMAHAWK_SUPPORT 26871 if (MEM_IS_EXACT_MATCH_4(mem)) { 26872 me = &pbi->e.em_4[cbi->src_ent]; 26873 } else if (MEM_IS_EXACT_MATCH_2(mem)) { 26874 me = &pbi->e.em_2[cbi->src_ent]; 26875 } else 26876 #endif 26877 { 26878 me = &pbi->e.l3[cbi->src_ent]; 26879 } 26880 26881 rv = soc_mem_bank_insert(unit, cbi->src_mem, 26882 (1 << ibank_num), copyno, 26883 me, NULL); 26884 if (SOC_FAILURE(rv)) { 26885 goto cleanup; 26886 } 26887 26888 ibank_num = bi.bank_nums[pbi->src_bix]; 26889 26890 rv = soc_mem_generic_delete(unit, cbi->src_mem, 26891 MEM_BLOCK_ANY, 26892 (1 << ibank_num), 26893 me, NULL, NULL); 26894 if (SOC_FAILURE(rv)) { 26895 goto cleanup; 26896 } 26897 26898 pbi->status &= ~(((1 << cbi->src_width) - 1) << cbi->src_ent); 26899 26900 _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, pbi->src_mem, pbi->status); 26901 26902 if (!free) { 26903 break; 26904 } 26905 } 26906 26907 /* now i is the toppest level with free slot available */ 26908 26909 if (free) { 26910 job_done = 1; 26911 goto done; 26912 } else { 26913 /* cbi --> level i; pbi --> level i - 1. 26914 * cbi is the toppest bucket with entry moved. 26915 * pbi is the bucket with entry removed. 26916 * Entire sub tree of pbi's removed entry needs be skipped. 26917 */ 26918 for (j = i; j <= level; j++) { 26919 if (j == i) { 26920 num = (bi.num_banks - 1); 26921 bkt_idx1 = (cbi->src_bkt_idx * ((bi.num_banks - 1) * NUM_ENT)) + 26922 (cbi->src_ent * (bi.num_banks - 1)); 26923 bkt_idx2 = bkt_idx1 + (cbi->src_width * (bi.num_banks - 1)); 26924 } else { 26925 num *= (bi.num_banks - 1) * NUM_ENT; 26926 bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT; 26927 bkt_idx2 *= (bi.num_banks - 1) * NUM_ENT; 26928 } 26929 } 26930 26931 /* assert (bkt_idx2 > bkt_idx && bkt_idx >= bkt_idx1); */ 26932 if (buckets[j]) { 26933 num *= (bi.num_banks - 1) * NUM_ENT; 26934 bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT; 26935 sal_memset(&buckets[j][bkt_idx1], 0, 26936 num * sizeof(_soc_breadth_bucket_t)); 26937 } 26938 bkt_idx = bkt_idx2 - 1; 26939 break; 26940 } 26941 } 26942 } 26943 num_cl_bkts *= (bi.num_banks - 1) * NUM_ENT; 26944 } 26945 26946 done: 26947 if (job_done) { 26948 rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num, 26949 entry, entry, NULL); 26950 } else { 26951 rv = SOC_E_FULL; 26952 } 26953 26954 cleanup: 26955 if (bkt_trace) { 26956 sal_free(bkt_trace); 26957 } 26958 26959 if (buckets[0]) { 26960 sal_free(buckets[0]); 26961 } 26962 26963 if (SOC_FAILURE(rv)) { 26964 LOG_VERBOSE(BSL_LS_SOC_COMMON, 26965 (BSL_META_U(unit, 26966 "Insert entry: %d\n"), rv)); 26967 } 26968 26969 return rv; 26970 } 26971 26972 26973 STATIC int 26974 _soc_mem_shared_hash_depth_move(int unit, soc_mem_t mem, 26975 int32 bank_num_start, int copyno, 26976 void *entry, int recurse_depth, 26977 _soc_hash_bank_info_t *bi_ptr, 26978 SHR_BITDCL *trace) 26979 { 26980 _soc_hash_bank_info_t bi; 26981 SHR_BITDCL *bkt_trace = NULL; 26982 SHR_BITDCL *bkt_trace2 = NULL; 26983 soc_mem_t l3_mem = L3_ENTRY_IPV6_MULTICASTm; 26984 soc_mem_t em_mem = EXACT_MATCH_4m; 26985 soc_mem_t orig_mem = 0; 26986 uint32 orig_entry[NUM_ENT][SOC_MAX_MEM_WORDS]; 26987 uint32 bkt_entry[NUM_ENT][SOC_MAX_MEM_WORDS]; 26988 uint32 v[NUM_ENT] = {0, 0, 0, 0}; 26989 uint32 k[NUM_ENT] = {0, 0, 0, 0}; 26990 int bank_num = 0; 26991 int cbix, bix; 26992 int rv = SOC_E_NONE; 26993 int vld_fld_0 = VALID_0f, vld_fld_2=VALID_2f; 26994 int key_type_0 = KEY_TYPE_0f, key_type_2=KEY_TYPE_2f; 26995 int ent, ent_incr, bucket, retry; 26996 int found = 0, status = 0, moved, move_bkt; 26997 int buckets[7] = {0}, mark = 0; 26998 26999 #if defined(BCM_TOMAHAWK_SUPPORT) 27000 int pipenum = -1; 27001 if (MEM_IS_EXACT_MATCH_2(mem) || MEM_IS_EXACT_MATCH_4(mem)) { 27002 switch (mem) { 27003 case EXACT_MATCH_4_PIPE0m: 27004 case EXACT_MATCH_2_PIPE0m: 27005 pipenum = 0; 27006 break; 27007 case EXACT_MATCH_4_PIPE1m: 27008 case EXACT_MATCH_2_PIPE1m: 27009 pipenum = 1; 27010 break; 27011 case EXACT_MATCH_4_PIPE2m: 27012 case EXACT_MATCH_2_PIPE2m: 27013 pipenum = 2; 27014 break; 27015 case EXACT_MATCH_4_PIPE3m: 27016 case EXACT_MATCH_2_PIPE3m: 27017 pipenum = 3; 27018 break; 27019 default: 27020 break; 27021 } 27022 } 27023 #endif 27024 27025 #ifdef BCM_TRIDENT3_SUPPORT 27026 if (SOC_IS_TRIDENT3X(unit)) { 27027 vld_fld_0 = BASE_VALID_0f; 27028 vld_fld_2 = BASE_VALID_2f; 27029 key_type_0 = KEY_TYPEf; 27030 key_type_2 = KEY_TYPEf; 27031 } 27032 #endif 27033 sal_memset(&bi, 0, sizeof(bi)); 27034 if (bank_num_start == SOC_MEM_HASH_BANK_ALL) { 27035 if (recurse_depth < 0) { 27036 return SOC_E_FULL; 27037 } 27038 SOC_IF_ERROR_RETURN( 27039 _soc_mem_shared_hash_init(unit, mem, &bkt_trace, 27040 &bi, 0, NULL, NULL)); 27041 } else { 27042 if (trace) { 27043 bkt_trace = trace; 27044 } else { 27045 return SOC_E_INTERNAL; 27046 } 27047 27048 if (bi_ptr) { 27049 sal_memcpy(&bi, bi_ptr, sizeof(_soc_hash_bank_info_t)); 27050 } else { 27051 sal_free(bkt_trace); 27052 return SOC_E_INTERNAL; 27053 } 27054 } 27055 27056 bkt_trace2 = bkt_trace; 27057 27058 if (SOC_MULTI_HASH_MOVE_ALGORITHM(unit) == MULTI_MOVE_MODE_DEPTH_FAST) { 27059 bkt_trace2 = bkt_trace + _SHR_BITDCLSIZE(bi.numb); 27060 } 27061 27062 for (bix = 0; bix < bi.num_banks; bix++) { 27063 cbix = bix % bi.num_banks; 27064 bank_num = bi.bank_nums[cbix]; 27065 if (bank_num_start == bank_num) { 27066 continue; 27067 } 27068 27069 bucket = _soc_mem_shared_hash_bucket(unit, mem, bank_num, entry); 27070 27071 if (SHR_BITGET(bkt_trace, bucket)) { 27072 continue; 27073 } 27074 SHR_BITSET(bkt_trace, bucket); 27075 SHR_BITSET(bkt_trace2, bucket); 27076 buckets[mark++] = bucket; 27077 27078 if (mem != L2Xm) { 27079 if (mem == L3_ENTRY_ONLYm || 27080 mem == L3_ENTRY_IPV4_UNICASTm || 27081 mem == L3_ENTRY_IPV4_MULTICASTm || 27082 mem == L3_ENTRY_IPV6_UNICASTm || 27083 mem == L3_ENTRY_IPV6_MULTICASTm) { 27084 rv = soc_mem_read(unit, l3_mem, copyno, bucket, bkt_entry[0]); 27085 if (SOC_FAILURE(rv)) { 27086 goto cleanup; 27087 } 27088 #ifdef BCM_TRIDENT3_SUPPORT 27089 if (SOC_IS_TRIDENT3(unit)) { 27090 soc_td3_hash_mem_status_get(unit, mem, bkt_entry[0], v); 27091 soc_mem_field_get(unit, l3_mem, bkt_entry[0], KEY_TYPEf, &k[0]); 27092 k[3] = k[2] = k[1] = k[0]; 27093 } else 27094 #endif /* BCM_TRIDENT3_SUPPORT */ 27095 #ifdef BCM_HELIX5_SUPPORT 27096 if (SOC_IS_HELIX5(unit)) { 27097 soc_hx5_hash_mem_status_get(unit, mem, bkt_entry[0], v); 27098 soc_mem_field_get(unit, l3_mem, bkt_entry[0], KEY_TYPEf, &k[0]); 27099 k[3] = k[2] = k[1] = k[0]; 27100 } else 27101 #endif /* BCM_HELIX5_SUPPORT */ 27102 #ifdef BCM_TOMAHAWK3_SUPPORT 27103 if (SOC_IS_TOMAHAWK3(unit)) { 27104 soc_tomahawk3_hash_mem_status_get(unit, mem, bkt_entry[0], v); 27105 soc_mem_field_get(unit, l3_mem, bkt_entry[0], KEY_TYPEf, &k[0]); 27106 k[3] = k[2] = k[1] = k[0]; 27107 } else 27108 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27109 { 27110 v[3] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_3f); 27111 v[2] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_2f); 27112 v[1] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_1f); 27113 v[0] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_0f); 27114 k[3] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_3f); 27115 k[2] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_2f); 27116 k[1] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_1f); 27117 k[0] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_0f); 27118 } 27119 } else if ((MEM_IS_EXACT_MATCH_4(mem)) || 27120 (SOC_IS_TRIDENT3X(unit) && (MEM_IS_EXACT_MATCH_2(mem)))) { 27121 rv = soc_mem_read(unit, em_mem, copyno, 27122 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4, bkt_entry[0]); 27123 if (SOC_FAILURE(rv)) { 27124 goto cleanup; 27125 } 27126 rv = soc_mem_read(unit, em_mem, copyno, 27127 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 1, 27128 bkt_entry[1]); 27129 if (SOC_FAILURE(rv)) { 27130 goto cleanup; 27131 } 27132 rv = soc_mem_read(unit, em_mem, copyno, 27133 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 2, 27134 bkt_entry[2]); 27135 if (SOC_FAILURE(rv)) { 27136 goto cleanup; 27137 } 27138 rv = soc_mem_read(unit, em_mem, copyno, 27139 bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 3, 27140 bkt_entry[3]); 27141 if (SOC_FAILURE(rv)) { 27142 goto cleanup; 27143 } 27144 v[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[3], vld_fld_0); 27145 v[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[2], vld_fld_0); 27146 v[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], vld_fld_0); 27147 v[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], vld_fld_0); 27148 k[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[3], key_type_0); 27149 k[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[2], key_type_0); 27150 k[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], key_type_0); 27151 k[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], key_type_0); 27152 } else if ((MEM_IS_EXACT_MATCH_2(mem))){ 27153 rv = soc_mem_read(unit, em_mem, copyno, 27154 bucket * SRAM_ENTRIES_PER_BUCKET_EM_2, bkt_entry[0]); 27155 if (SOC_FAILURE(rv)) { 27156 goto cleanup; 27157 } 27158 rv = soc_mem_read(unit, em_mem, copyno, 27159 bucket * SRAM_ENTRIES_PER_BUCKET_EM_2 + 1, 27160 bkt_entry[1]); 27161 if (SOC_FAILURE(rv)) { 27162 goto cleanup; 27163 } 27164 v[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], vld_fld_2); 27165 v[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], vld_fld_0); 27166 v[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], vld_fld_2); 27167 v[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], vld_fld_0); 27168 k[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], key_type_2); 27169 k[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], key_type_0); 27170 k[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], key_type_2); 27171 k[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], key_type_0); 27172 } 27173 status = (v[3]? 1 << 3 : 0) | (v[2]? 1 << 2 : 0) | 27174 (v[1]? 1 << 1 : 0) | (v[0]? 1 : 0); 27175 } 27176 27177 ent_incr = 1; 27178 retry = 0; 27179 for (ent = 0; ent < NUM_ENT; ent += ent_incr) { 27180 if (retry) { 27181 retry = 0; 27182 } else { 27183 if (mem == L2Xm) { 27184 rv = soc_mem_read(unit, mem, copyno, 27185 (bucket << 2) + ent, &orig_entry[ent]); 27186 if (SOC_FAILURE(rv)) { 27187 goto cleanup; 27188 } 27189 orig_mem = mem; 27190 ent_incr = 1; 27191 } else if (mem == L3_ENTRY_ONLYm || 27192 mem == L3_ENTRY_IPV4_UNICASTm || 27193 mem == L3_ENTRY_IPV4_MULTICASTm || 27194 mem == L3_ENTRY_IPV6_UNICASTm || 27195 mem == L3_ENTRY_IPV6_MULTICASTm) { 27196 if (!v[ent]) { 27197 ent_incr = 1; 27198 continue; 27199 } 27200 #ifdef BCM_HELIX5_SUPPORT 27201 if (SOC_IS_HELIX5(unit)) { 27202 rv = soc_hx5_shared_hash_mem_bucket_read 27203 (unit, ent, k[ent], &ent_incr, l3_mem, 27204 &orig_mem, bkt_entry[0], &orig_entry[ent]); 27205 if (SOC_FAILURE(rv)) { 27206 goto cleanup; 27207 } 27208 } else 27209 #endif /* BCM_HELIX5_SUPPORT */ 27210 #ifdef BCM_TRIDENT3_SUPPORT 27211 if (SOC_IS_TRIDENT3X(unit)) { 27212 rv = soc_td3_shared_hash_mem_bucket_read 27213 (unit, ent, k[ent], &ent_incr, l3_mem, 27214 &orig_mem, bkt_entry[0], &orig_entry[ent]); 27215 if (SOC_FAILURE(rv)) { 27216 goto cleanup; 27217 } 27218 } else 27219 #endif /* BCM_TRIDENT3_SUPPORT */ 27220 #ifdef BCM_TOMAHAWK3_SUPPORT 27221 if (SOC_IS_TOMAHAWK3(unit)) { 27222 rv = soc_tomahawk3_shared_hash_mem_bucket_read 27223 (unit, ent, k[ent], &ent_incr, l3_mem, 27224 &orig_mem, bkt_entry[0], &orig_entry[ent]); 27225 if (SOC_FAILURE(rv)) { 27226 goto cleanup; 27227 } 27228 } else 27229 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27230 { 27231 _soc_mem_shared_hash_l3_bucket_read(unit, ent, k[ent], 27232 &ent_incr, &orig_mem, bkt_entry[0], 27233 &orig_entry[ent]); 27234 } 27235 } else { 27236 #if defined(BCM_TOMAHAWK_SUPPORT) 27237 if (!v[ent]) { 27238 ent_incr = 1; 27239 continue; 27240 } 27241 #ifdef BCM_HELIX5_SUPPORT 27242 if (SOC_IS_HELIX5(unit)) { 27243 if (MEM_IS_EXACT_MATCH_2(mem) || 27244 MEM_IS_EXACT_MATCH_4(mem)) { 27245 rv = soc_hx5_shared_hash_mem_bucket_read 27246 (unit, ent, k[ent], &ent_incr, em_mem, 27247 &orig_mem, bkt_entry[0], &orig_entry[ent]); 27248 if (SOC_FAILURE(rv)) { 27249 goto cleanup; 27250 } 27251 } 27252 } else 27253 #endif /* BCM_HELIX5_SUPPORT */ 27254 #ifdef BCM_TRIDENT3_SUPPORT 27255 if (SOC_IS_TRIDENT3X(unit)) { 27256 if (MEM_IS_EXACT_MATCH_2(mem) || 27257 MEM_IS_EXACT_MATCH_4(mem)) { 27258 rv = soc_td3_shared_hash_mem_bucket_read 27259 (unit, ent, k[ent], &ent_incr, em_mem, 27260 &orig_mem, bkt_entry[ent], &orig_entry[ent]); 27261 if (SOC_FAILURE(rv)) { 27262 goto cleanup; 27263 } 27264 } 27265 } else 27266 #endif /* BCM_TRIDENT3_SUPPORT */ 27267 #ifdef BCM_TOMAHAWK3_SUPPORT 27268 if (SOC_IS_TOMAHAWK3(unit)) { 27269 if (MEM_IS_EXACT_MATCH_2(mem) || 27270 MEM_IS_EXACT_MATCH_4(mem)) { 27271 rv = soc_tomahawk3_shared_hash_mem_bucket_read 27272 (unit, ent, k[ent], &ent_incr, em_mem, 27273 &orig_mem, bkt_entry[ent], &orig_entry[ent]); 27274 if (SOC_FAILURE(rv)) { 27275 goto cleanup; 27276 } 27277 } 27278 } else 27279 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27280 if (MEM_IS_EXACT_MATCH_2(mem)) { 27281 _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent], 27282 &ent_incr, &orig_mem, bkt_entry[ent / SRAM_ENTRIES_PER_BUCKET_EM_2], 27283 &orig_entry[ent], pipenum); 27284 } else if (MEM_IS_EXACT_MATCH_4(mem)) { 27285 _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent], 27286 &ent_incr, &orig_mem, bkt_entry[ent], 27287 &orig_entry[ent], pipenum); 27288 } 27289 #endif /* BCM_TOMAHAWK_SUPPORT */ 27290 } 27291 } 27292 27293 rv = soc_mem_generic_insert(unit, orig_mem, copyno, 27294 bi.banks & ~(1 << bank_num), 27295 orig_entry[ent], NULL, &move_bkt); 27296 27297 moved = 0; 27298 if (SOC_SUCCESS(rv)) { 27299 move_bkt /= _soc_mem_shared_hash_entries_per_bkt(unit, orig_mem); 27300 if (SHR_BITGET(bkt_trace2, move_bkt)) { 27301 rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY, 27302 bi.banks & ~(1 << bank_num), 27303 orig_entry[ent], NULL, NULL); 27304 if (SOC_FAILURE(rv)) { 27305 goto cleanup; 27306 } 27307 } else { 27308 rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY, 27309 (uint32)1<<bank_num, 27310 orig_entry[ent], NULL, NULL); 27311 if (SOC_FAILURE(rv)) { 27312 goto cleanup; 27313 } 27314 moved = 1; 27315 27316 if (mem == L2Xm) { 27317 found = 1; 27318 break; 27319 } else { 27320 status &= ~(((1 << ent_incr) - 1) << ent); 27321 _SOC_MEM_SHARED_HASH_STATUS_CHECK(found, mem, status); 27322 } 27323 } 27324 } 27325 27326 if (found) { 27327 break; 27328 } else if (!moved && recurse_depth) { 27329 27330 rv = _soc_mem_shared_hash_depth_move(unit, orig_mem, 27331 bank_num, copyno, 27332 orig_entry[ent], 27333 recurse_depth - 1, 27334 &bi, bkt_trace); 27335 if (SOC_SUCCESS(rv)) { 27336 /* Deeper entry is moved, try again */ 27337 retry = 1; 27338 ent -= ent_incr; 27339 } else if (rv != SOC_E_FULL) { 27340 goto cleanup; 27341 } 27342 } 27343 } 27344 if (found) { 27345 break; 27346 } 27347 } 27348 27349 if (!found) { 27350 rv = SOC_E_FULL; 27351 } 27352 27353 if (bank_num_start == SOC_MEM_HASH_BANK_ALL) { 27354 if (found) { 27355 rv = soc_mem_generic_insert(unit, mem, copyno, (uint32)1<<bank_num, 27356 entry, entry, NULL); 27357 } 27358 if (rv) { 27359 LOG_VERBOSE(BSL_LS_SOC_COMMON, 27360 (BSL_META_U(unit, 27361 "Insert entry: %d\n"), rv)); 27362 } 27363 } 27364 27365 cleanup: 27366 for (ent_incr = 0; ent_incr < mark; ent_incr++) { 27367 SHR_BITCLR(bkt_trace2, buckets[ent_incr]); 27368 } 27369 if (bank_num_start == SOC_MEM_HASH_BANK_ALL) { 27370 sal_free(bkt_trace); 27371 } 27372 return rv; 27373 } 27374 27375 27376 /* 27377 * Function: 27378 * _soc_mem_shared_hash_init 27379 * Purpose: 27380 * Stack variables initialization & memory allocations for recursion algorithm 27381 * Param: 27382 * mem - memory for new insert 27383 * *num_ent - how may entries in each bucket 27384 * **trace - bucket bitmap used to trace which buckets have been moved during recursion 27385 * bank_info - bank properties 27386 * num_bkt - how may buckets we need trace in recursion 27387 * num_banks - how may banks for this type of entry 27388 * bank_ids - mapping for logical bank id to physical bank id for insert mem 27389 * bank_bmp - physical bank id bitmap for this kind of mem table 27390 * Notes: 27391 * None. 27392 */ 27393 27394 STATIC INLINE int 27395 _soc_mem_shared_hash_init(int unit, soc_mem_t mem, 27396 SHR_BITDCL **trace, 27397 _soc_hash_bank_info_t *bank_info, 27398 int num_levels, 27399 _soc_breadth_bucket_t **buckets, 27400 _soc_breadth_bucket2_t **buckets2) 27401 { 27402 uint8 bix; 27403 int alloc_size; 27404 SHR_BITDCL *bkt_trace = NULL; 27405 27406 if (NULL == bank_info) { 27407 return SOC_E_PARAM; 27408 } 27409 27410 /* Get the bank number of this mem table */ 27411 #ifdef BCM_APACHE_SUPPORT 27412 if (SOC_IS_APACHE(unit)) { 27413 SOC_IF_ERROR_RETURN 27414 (soc_apache_hash_bank_count_get(unit, mem, &bank_info->num_banks)); 27415 } else 27416 #endif /* BCM_APACHE_SUPPORT */ 27417 #ifdef BCM_TOMAHAWK_SUPPORT 27418 if (SOC_IS_TOMAHAWKX(unit)) { 27419 #ifdef BCM_TOMAHAWK3_SUPPORT 27420 if (SOC_IS_TOMAHAWK3(unit)) { 27421 SOC_IF_ERROR_RETURN 27422 (soc_tomahawk3_hash_bank_count_get(unit, mem, &bank_info->num_banks)); 27423 } else 27424 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27425 { 27426 SOC_IF_ERROR_RETURN 27427 (soc_tomahawk_hash_bank_count_get(unit, mem, &bank_info->num_banks)); 27428 } 27429 } else 27430 #endif /* BCM_TOMAHAWK_SUPPORT */ 27431 #ifdef BCM_HELIX5_SUPPORT 27432 if (SOC_IS_HELIX5(unit)) { 27433 SOC_IF_ERROR_RETURN 27434 (soc_helix5_hash_bank_count_get(unit, mem, &bank_info->num_banks)); 27435 } else 27436 #endif /* BCM_HELIX5_SUPPORT */ 27437 #ifdef BCM_TRIDENT3_SUPPORT 27438 if (SOC_IS_TRIDENT3X(unit)) { 27439 SOC_IF_ERROR_RETURN 27440 (soc_trident3_hash_bank_count_get(unit, mem, &bank_info->num_banks)); 27441 } else 27442 #endif /* BCM_TRIDENT3_SUPPORT */ 27443 { 27444 SOC_IF_ERROR_RETURN 27445 (soc_trident2_hash_bank_count_get(unit, mem, &bank_info->num_banks)); 27446 } 27447 27448 /* Clear banks bitmap. */ 27449 bank_info->banks = 0; 27450 27451 for (bix = 0; bix < bank_info->num_banks; bix++) { 27452 #ifdef BCM_APACHE_SUPPORT 27453 if (SOC_IS_APACHE(unit)) { 27454 SOC_IF_ERROR_RETURN 27455 (soc_apache_hash_bank_number_get(unit, mem, bix, 27456 &bank_info->bank_nums[bix])); 27457 } else 27458 #endif /* BCM_APACHE_SUPPORT */ 27459 #ifdef BCM_TOMAHAWK_SUPPORT 27460 if (SOC_IS_TOMAHAWKX(unit)) { 27461 #ifdef BCM_TOMAHAWK3_SUPPORT 27462 if (SOC_IS_TOMAHAWK3(unit)) { 27463 SOC_IF_ERROR_RETURN 27464 (soc_tomahawk3_hash_bank_number_get(unit, mem, bix, 27465 &bank_info->bank_nums[bix])); 27466 } else 27467 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27468 { 27469 SOC_IF_ERROR_RETURN 27470 (soc_tomahawk_hash_bank_number_get(unit, mem, bix, 27471 &bank_info->bank_nums[bix])); 27472 } 27473 } else 27474 #endif /* BCM_TOMAHAWK_SUPPORT */ 27475 #ifdef BCM_HELIX5_SUPPORT 27476 if (SOC_IS_HELIX5(unit)) { 27477 SOC_IF_ERROR_RETURN 27478 (soc_hx5_hash_bank_number_get(unit, mem, bix, 27479 &bank_info->bank_nums[bix])); 27480 } else 27481 #endif /* BCM_TRIDENT3_SUPPORT */ 27482 #ifdef BCM_TRIDENT3_SUPPORT 27483 if (SOC_IS_TRIDENT3X(unit)) { 27484 SOC_IF_ERROR_RETURN 27485 (soc_td3_hash_bank_number_get(unit, mem, bix, 27486 &bank_info->bank_nums[bix])); 27487 } else 27488 #endif /* BCM_TRIDENT3_SUPPORT */ 27489 { 27490 SOC_IF_ERROR_RETURN 27491 (soc_trident2_hash_bank_number_get(unit, mem, bix, 27492 &bank_info->bank_nums[bix])); 27493 } 27494 27495 /* Get the all banks bitmap for hash insert. */ 27496 bank_info->banks |= 1 << bank_info->bank_nums[bix]; 27497 } 27498 27499 if (SOC_MULTI_HASH_MOVE_ALGORITHM(unit) == MULTI_MOVE_MODE_LEGACY || 27500 SOC_MULTI_HASH_MOVE_ALGORITHM(unit) == MULTI_MOVE_MODE_MIX) { 27501 bank_info->numb = 65536; 27502 /* Keep back trace of all buckets affected by recursion. */ 27503 alloc_size = SHR_BITALLOCSIZE(bank_info->numb * 10); 27504 /* For simplicity, allocate same number of bits for buckets per bank */ 27505 } else { 27506 bank_info->numb = soc_mem_index_count(unit, mem) >> (L2Xm == mem ? 2 : 0); 27507 #ifdef BCM_TOMAHAWK3_SUPPORT 27508 if (SOC_IS_TOMAHAWK3(unit)) { 27509 int tbl_entries_per_sram_entry, rv; 27510 rv = soc_tomahawk3_tbl_entries_per_sram_entry_get(unit, mem, 27511 &tbl_entries_per_sram_entry); 27512 if (SOC_FAILURE(rv)){ 27513 return (rv); 27514 } 27515 bank_info->numb *= 4/tbl_entries_per_sram_entry; 27516 } 27517 #endif 27518 alloc_size = SHR_BITALLOCSIZE(bank_info->numb); 27519 if (SOC_MULTI_HASH_MOVE_ALGORITHM(unit) == 27520 MULTI_MOVE_MODE_DEPTH_FAST) { 27521 alloc_size *= 2; 27522 } 27523 } 27524 27525 bkt_trace = sal_alloc(alloc_size, "Shared hash"); 27526 if (NULL == bkt_trace) { 27527 return SOC_E_MEMORY; 27528 } 27529 sal_memset(bkt_trace, 0, alloc_size); 27530 *trace = bkt_trace; 27531 27532 27533 if (buckets) { 27534 int num_cl_buckets; 27535 int level; 27536 27537 alloc_size = 0; 27538 num_cl_buckets = bank_info->num_banks; 27539 for (level = 0; level < num_levels; level++) { 27540 alloc_size += num_cl_buckets; 27541 num_cl_buckets *= (bank_info->num_banks - 1) * 4; 27542 } 27543 alloc_size *= sizeof(_soc_breadth_bucket_t); 27544 27545 *buckets = sal_alloc(alloc_size, "Buckets"); 27546 if (*buckets == NULL) { 27547 sal_free(bkt_trace); 27548 return SOC_E_MEMORY; 27549 } 27550 sal_memset(*buckets, 0, alloc_size); 27551 } 27552 27553 if (buckets2) { 27554 alloc_size = (bank_info->numb + 1) * sizeof(_soc_breadth_bucket2_t); 27555 *buckets2 = sal_alloc(alloc_size, "Buckets"); 27556 if (*buckets2 == NULL) { 27557 sal_free(bkt_trace); 27558 if (buckets && *buckets) { 27559 sal_free(*buckets); 27560 } 27561 return SOC_E_MEMORY; 27562 } 27563 sal_memset(*buckets2, 0, alloc_size); 27564 } 27565 27566 return SOC_E_NONE; 27567 } 27568 27569 /* 27570 * Function: 27571 * _soc_mem_shared_hash_move_entry_resolve 27572 * Purpose: 27573 * Resolve the move mem and entry from current slot/index(with new mem view), 27574 * 1. If there is enough space for new mem insert (!(v0 || v1 || v2 || v3)), 27575 * return free_slot = TRUE directly. 27576 * 2. If there is no enough space, resolve the move mem type and 27577 * entry content for hash move. 27578 * Param: 27579 * mem - memory for new insert 27580 * copyno - copy number 27581 * index - Hash calculated HW index for this mem view in current bank 27582 * *free_slot - If have enough spaces for hash move return TRUE; else FALSE 27583 * *move_mem - mem type which will be moved. 27584 * *move_entry - mem entry which will be moved. 27585 * Notes: 27586 * None. 27587 */ 27588 27589 STATIC INLINE int 27590 _soc_mem_shared_hash_move_entry_resolve(int unit, soc_mem_t mem, int copyno, 27591 int index, int *free_slot, 27592 soc_mem_t *move_mem, void *move_entry) 27593 { 27594 int rv; 27595 uint32 v0, v1, v2, v3, k0, k1, k2, k3; 27596 soc_mem_t old_mem; 27597 int key_type, offset, l3_entry_only_index; 27598 soc_field_t fld_vld = VALIDf; 27599 if (mem == L2Xm && 27600 soc_feature(unit, soc_feature_base_valid)) { 27601 fld_vld = BASE_VALIDf; 27602 } 27603 27604 /* Read entry information from current slot/index with new mem view */ 27605 rv = soc_mem_read(unit, mem, copyno, index, move_entry); 27606 if (SOC_FAILURE(rv)) { 27607 return SOC_E_MEMORY; 27608 } 27609 /* Could be an empty slot here */ 27610 v0 = v1 = v2 = v3 = 0; 27611 k0 = k1 = k2 = k3 = 0; 27612 *free_slot = FALSE; 27613 27614 switch (mem) { 27615 case L3_ENTRY_IPV6_MULTICASTm: 27616 soc_mem_field_get(unit, mem, move_entry, VALID_3f, &v3); 27617 soc_mem_field_get(unit, mem, move_entry, VALID_2f, &v2); 27618 soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_3f, &k3); 27619 soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_2f, &k2); 27620 /* pass through */ 27621 case L3_ENTRY_IPV6_UNICASTm: 27622 case L3_ENTRY_IPV4_MULTICASTm: 27623 soc_mem_field_get(unit, mem, move_entry, VALID_1f, &v1); 27624 soc_mem_field_get(unit, mem, move_entry, VALID_0f, &v0); 27625 soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_1f, &k1); 27626 soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_0f, &k0); 27627 break; 27628 case L3_ENTRY_IPV4_UNICASTm: 27629 case L3_ENTRY_ONLYm: 27630 case L2Xm: 27631 soc_mem_field_get(unit, mem, move_entry, fld_vld, &v0); 27632 soc_mem_field_get(unit, mem, move_entry, KEY_TYPEf, &k0); 27633 break; 27634 default: 27635 v0 = v1 = v2 = v3 = 1; 27636 break; 27637 } 27638 27639 LOG_VERBOSE(BSL_LS_SOC_COMMON, 27640 (BSL_META_U(unit, 27641 "Read %s from index %d (%d %d %d %d)\n"), 27642 SOC_MEM_NAME(unit, mem), index, v0, v1, v2, v3)); 27643 27644 /* If it is an emty bucket or there are enough spaces for hash insert, 27645 * v0, v1, v2, v3 are all zero. */ 27646 if (!(v0 || v1 || v2 || v3)) { 27647 *free_slot = TRUE; 27648 return SOC_E_NONE; 27649 } 27650 27651 /* If no enough spaces, resolve move mem and move entry */ 27652 if (mem == L2Xm) { 27653 *move_mem = L2Xm; 27654 } else { 27655 /* what is the key_type of old entry */ 27656 key_type = v0 ? k0 : (v1 ? k1 : (v2 ? k2 : (v3 ? k3 : 0))); 27657 27658 /* what is the mem table type of old entry */ 27659 switch (key_type) { 27660 case TD2_L3_HASH_KEY_TYPE_V4UC: 27661 case TD2_L3_HASH_KEY_TYPE_TRILL: 27662 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 27663 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 27664 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 27665 old_mem = L3_ENTRY_IPV4_UNICASTm; 27666 break; 27667 case TD2_L3_HASH_KEY_TYPE_V4UC_EXT: 27668 case TD2_L3_HASH_KEY_TYPE_V4MC: 27669 case TD2_L3_HASH_KEY_TYPE_V4L2MC: 27670 case TD2_L3_HASH_KEY_TYPE_V4L2VPMC: 27671 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 27672 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 27673 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 27674 case TD2_L3_HASH_KEY_TYPE_DST_NAT: 27675 case TD2_L3_HASH_KEY_TYPE_DST_NAPT: 27676 old_mem = L3_ENTRY_IPV4_MULTICASTm; 27677 break; 27678 case TD2_L3_HASH_KEY_TYPE_V6UC: 27679 old_mem = L3_ENTRY_IPV6_UNICASTm; 27680 break; 27681 case TD2_L3_HASH_KEY_TYPE_V6UC_EXT: 27682 case TD2_L3_HASH_KEY_TYPE_V6MC: 27683 case TD2_L3_HASH_KEY_TYPE_V6L2MC: 27684 case TD2_L3_HASH_KEY_TYPE_V6L2VPMC: 27685 old_mem = L3_ENTRY_IPV6_MULTICASTm; 27686 break; 27687 default: 27688 return SOC_E_INTERNAL; 27689 } 27690 27691 /* If different mem table, re-calculate the index and re-read the move entry */ 27692 if (mem != old_mem) { 27693 /* coverity[dead_error_line] */ 27694 offset = v0 ? 0 : (v1 ? 1 : (v2 ? 2 : (v3 ? 3 : 0))); 27695 switch (mem) { 27696 case L3_ENTRY_IPV6_MULTICASTm: 27697 l3_entry_only_index = index * 4 + offset; 27698 break; 27699 case L3_ENTRY_IPV6_UNICASTm: 27700 case L3_ENTRY_IPV4_MULTICASTm: 27701 l3_entry_only_index = index * 2 + offset; 27702 break; 27703 case L3_ENTRY_IPV4_UNICASTm: 27704 default: 27705 l3_entry_only_index = index + offset; 27706 break; 27707 } 27708 /* re-calculate the move entry index */ 27709 switch (old_mem) { 27710 case L3_ENTRY_IPV6_MULTICASTm: 27711 index = l3_entry_only_index / 4; 27712 break; 27713 case L3_ENTRY_IPV6_UNICASTm: 27714 case L3_ENTRY_IPV4_MULTICASTm: 27715 index = l3_entry_only_index / 2; 27716 break; 27717 case L3_ENTRY_IPV4_UNICASTm: 27718 default: 27719 index = l3_entry_only_index; 27720 break; 27721 } 27722 /* re-read the move entry */ 27723 rv = soc_mem_read(unit, old_mem, copyno, index, move_entry); 27724 if (SOC_FAILURE(rv)) { 27725 return SOC_E_MEMORY; 27726 } 27727 } 27728 27729 /* return move mem table type */ 27730 *move_mem = old_mem; 27731 } 27732 27733 return SOC_E_NONE; 27734 } 27735 27736 /* 27737 * Function: 27738 * _soc_mem_shared_hash_breadth_move 27739 * Purpose: 27740 * Breadth recursion algorithm for shared hash move 27741 * Notes: 27742 * None. 27743 */ 27744 27745 STATIC int 27746 _soc_mem_shared_hash_breadth_move(int unit, soc_mem_t mem, 27747 int32 banks, int copyno, 27748 void *entry, SHR_BITDCL *bucket_trace, 27749 int recurse, int recurse_depth, 27750 _soc_hash_bank_info_t *bank_info) 27751 { 27752 SHR_BITDCL *trace = NULL; 27753 _soc_hash_bank_info_t bank_inf = {0}; 27754 uint8 num_ent = 0; 27755 int nbix, cbix; 27756 int rv = SOC_E_NONE, index; 27757 uint8 i, bix, found = FALSE, cb = 0; 27758 uint32 db, dest_bucket, dbs; 27759 uint32 bucket, move_entry[SOC_MAX_MEM_WORDS]; 27760 soc_mem_t ori_mem = mem; 27761 int banks_seq_num = 0; 27762 27763 if (recurse_depth < 0) { 27764 return SOC_E_FULL; 27765 } 27766 /* Get the entry number per each bucket */ 27767 num_ent = _soc_mem_shared_hash_entries_per_bkt(unit, mem); 27768 27769 /* Stack variables initialization & memory allocations */ 27770 if (NULL == bucket_trace) { 27771 SOC_IF_ERROR_RETURN( 27772 _soc_mem_shared_hash_init(unit, mem, &trace, &bank_inf, 0, NULL, NULL)); 27773 } else { 27774 trace = bucket_trace; 27775 if (NULL != bank_info) { 27776 sal_memcpy(&bank_inf, bank_info, sizeof(_soc_hash_bank_info_t)); 27777 } else { 27778 rv = SOC_E_INTERNAL; 27779 goto clean_up; 27780 } 27781 } 27782 if (banks != SOC_MEM_HASH_BANK_ALL) { 27783 #ifdef BCM_APACHE_SUPPORT 27784 if (SOC_IS_APACHE(unit)) { 27785 rv = soc_apache_hash_seq_number_get(unit, mem, banks, 27786 &banks_seq_num); 27787 } else 27788 #endif /* BCM_APACHE_SUPPORT */ 27789 #ifdef BCM_TOMAHAWK_SUPPORT 27790 if (SOC_IS_TOMAHAWKX(unit)) { 27791 #ifdef BCM_TOMAHAWK3_SUPPORT 27792 if (SOC_IS_TOMAHAWK3(unit)) { 27793 rv = soc_tomahawk3_hash_seq_number_get(unit, mem, banks, 27794 &banks_seq_num); 27795 } else 27796 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27797 { 27798 rv = soc_tomahawk_hash_seq_number_get(unit, mem, banks, 27799 &banks_seq_num); 27800 } 27801 } else 27802 #endif /* BCM_TOMAHAWK_SUPPORT */ 27803 #ifdef BCM_HELIX5_SUPPORT 27804 if (SOC_IS_HELIX5(unit)) { 27805 rv = soc_hx5_hash_seq_number_get(unit, mem, banks, &banks_seq_num); 27806 } else 27807 #endif /* BCM_HELIX5_SUPPORT */ 27808 #ifdef BCM_TRIDENT3_SUPPORT 27809 if (SOC_IS_TRIDENT3X(unit)) { 27810 rv = soc_td3_hash_seq_number_get(unit, mem, banks, &banks_seq_num); 27811 } else 27812 #endif /* BCM_TRIDENT3_SUPPORT */ 27813 { 27814 rv = soc_trident2_hash_seq_number_get(unit, mem, banks, 27815 &banks_seq_num); 27816 } 27817 if (SOC_FAILURE(rv)) { 27818 goto clean_up; 27819 } 27820 } else { 27821 /* Make sure we will try from the first bank */ 27822 banks_seq_num = -1; 27823 } 27824 /* Iterate over banks. */ 27825 for (bix = 0; bix < bank_inf.num_banks; bix++) { 27826 /* if banks is present, try interate from next bank */ 27827 cbix = banks_seq_num + bix + 1; 27828 cbix = cbix % bank_inf.num_banks; 27829 cb = bank_inf.bank_nums[cbix]; 27830 if (banks == cb) { 27831 /* Not this bank */ 27832 continue; 27833 } 27834 #ifdef BCM_APACHE_SUPPORT 27835 if (SOC_IS_APACHE(unit)) { 27836 rv = soc_ap_hash_bucket_get(unit, mem, cb, entry, &bucket); 27837 } else 27838 #endif /* BCM_APACHE_SUPPORT */ 27839 #ifdef BCM_TOMAHAWK_SUPPORT 27840 if (SOC_IS_TOMAHAWKX(unit)) { 27841 #ifdef BCM_TOMAHAWK3_SUPPORT 27842 if (SOC_IS_TOMAHAWK3(unit)) { 27843 rv = soc_tomahawk3_hash_bucket_get(unit, mem, cb, entry, &bucket); 27844 } else 27845 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27846 { 27847 rv = soc_th_hash_bucket_get(unit, mem, cb, entry, &bucket); 27848 } 27849 } else 27850 #endif /* BCM_TOMAHAWK_SUPPORT */ 27851 #ifdef BCM_HELIX5_SUPPORT 27852 if (SOC_IS_HELIX5(unit)) { 27853 rv = soc_hx5_hash_bucket_get(unit, mem, cb, entry, &bucket); 27854 } else 27855 #endif /* BCM_HELIX5_SUPPORT */ 27856 #ifdef BCM_TRIDENT3_SUPPORT 27857 if (SOC_IS_TRIDENT3X(unit)) { 27858 rv = soc_td3_hash_bucket_get(unit, mem, cb, entry, &bucket); 27859 } else 27860 #endif /* BCM_TRIDENT3_SUPPORT */ 27861 { 27862 rv = soc_hash_bucket_get(unit, mem, cb, entry, &bucket); 27863 } 27864 27865 if (SOC_FAILURE(rv)) { 27866 break; 27867 } 27868 nbix = (cbix + 1) % bank_inf.num_banks; /* next bank index */ 27869 db = bank_inf.bank_nums[nbix]; /* next destination bank */ 27870 /* For simplicity, use dbs instead of db for hash move. 27871 * The dbs only used in breadth iteration loop */ 27872 dbs = bank_inf.banks & ~(1 << cb); 27873 /* Only record the buckets in breadth iteration loop */ 27874 if (!recurse) { 27875 /* If this bucket was already iterated, Try next */ 27876 if (SHR_BITGET(trace, (bank_inf.numb * cbix) + bucket)) { 27877 continue; 27878 } 27879 SHR_BITSET(trace, (bank_inf.numb * cbix) + bucket); 27880 } 27881 #ifdef BCM_APACHE_SUPPORT 27882 if (SOC_IS_APACHE(unit)) { 27883 index = soc_ap_hash_index_get(unit, mem, cb, bucket); 27884 } else 27885 #endif /* BCM_APACHE_SUPPORT */ 27886 #ifdef BCM_TOMAHAWK_SUPPORT 27887 if (SOC_IS_TOMAHAWKX(unit)) { 27888 #ifdef BCM_TOMAHAWK3_SUPPORT 27889 if (SOC_IS_TOMAHAWK3(unit)) { 27890 index = soc_tomahawk3_hash_index_get(unit, mem, cb, bucket); 27891 } else 27892 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27893 { 27894 index = soc_th_hash_index_get(unit, mem, cb, bucket); 27895 } 27896 } else 27897 #endif /* BCM_TOMAHAWK_SUPPORT */ 27898 #ifdef BCM_HELIX5_SUPPORT 27899 if (SOC_IS_HELIX5(unit)) { 27900 index = soc_hx5_hash_index_get(unit, mem, cb, bucket); 27901 } else 27902 #endif /* BCM_HELIX5_SUPPORT */ 27903 #ifdef BCM_TRIDENT3_SUPPORT 27904 if (SOC_IS_TRIDENT3X(unit)) { 27905 index = soc_td3_hash_index_get(unit, mem, cb, bucket); 27906 } else 27907 #endif /* BCM_TRIDENT3_SUPPORT */ 27908 { 27909 index = soc_hash_index_get(unit, mem, cb, bucket); 27910 } 27911 for (i = 0; i < num_ent;) { 27912 int free_slot = FALSE; 27913 /* Is there free slot to insert this new entry? 27914 If no, resolve the move_mem and move_entry from current index */ 27915 rv = _soc_mem_shared_hash_move_entry_resolve(unit, mem, copyno, 27916 index + i, &free_slot, 27917 &mem, move_entry); 27918 if (SOC_FAILURE(rv)) { 27919 break; 27920 } 27921 /* If have free slot for move entry, insert directly */ 27922 if (free_slot) { 27923 found = TRUE; 27924 break; 27925 } 27926 27927 /* Are we already in recursion */ 27928 if (recurse) { 27929 /* Will we be in recursion */ 27930 if (recurse_depth) { 27931 /* Calculate destination entry hash value. */ 27932 #ifdef BCM_APACHE_SUPPORT 27933 if (SOC_IS_APACHE(unit)) { 27934 (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry, 27935 &dest_bucket); 27936 } else 27937 #endif /* BCM_APACHE_SUPPORT */ 27938 #ifdef BCM_TOMAHAWK_SUPPORT 27939 if (SOC_IS_TOMAHAWKX(unit)) { 27940 #ifdef BCM_TOMAHAWK3_SUPPORT 27941 if (SOC_IS_TOMAHAWK3(unit)) { 27942 (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry, 27943 &dest_bucket); 27944 } else 27945 #endif /* BCM_TOMAHAWK3_SUPPORT */ 27946 { 27947 (void)soc_th_hash_bucket_get(unit, mem, db, move_entry, 27948 &dest_bucket); 27949 } 27950 } else 27951 #endif /* BCM_TOMAHAWK_SUPPORT */ 27952 #ifdef BCM_HELIX5_SUPPORT 27953 if (SOC_IS_HELIX5(unit)) { 27954 (void)soc_hx5_hash_bucket_get(unit, mem, db, move_entry, 27955 &dest_bucket); 27956 } else 27957 #endif /* BCM_HELIX5_SUPPORT */ 27958 #ifdef BCM_TRIDENT3_SUPPORT 27959 if (SOC_IS_TRIDENT3X(unit)) { 27960 (void)soc_td3_hash_bucket_get(unit, mem, db, move_entry, 27961 &dest_bucket); 27962 } else 27963 #endif /* BCM_TRIDENT3_SUPPORT */ 27964 { 27965 (void)soc_hash_bucket_get(unit, mem, db, move_entry, 27966 &dest_bucket); 27967 } 27968 if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) { 27969 /* Try next entry in the same bucket in original 27970 * memory view */ 27971 mem = ori_mem; 27972 i += _soc_mem_shared_hash_incr_per_entry(unit, mem, 27973 move_entry, 27974 entry); 27975 LOG_VERBOSE(BSL_LS_SOC_COMMON, 27976 (BSL_META_U(unit, 27977 " Skip bank %d bucket %d\n"), 27978 db, dest_bucket)); 27979 continue; 27980 } 27981 } 27982 27983 /* Recursive call - attempt to create a slot 27984 in another bank's bucket. */ 27985 rv = _soc_mem_shared_hash_breadth_move(unit, mem, cb, copyno, 27986 move_entry, trace, FALSE, 27987 recurse_depth - 1, 27988 &bank_inf); 27989 } else { 27990 /* Attempt to insert it into the other banks. Use dbs instead of db. */ 27991 rv = soc_mem_bank_insert(unit, mem, dbs, copyno, 27992 move_entry, NULL); 27993 } 27994 27995 if (SOC_FAILURE(rv)) { 27996 if (rv != SOC_E_FULL) { 27997 break; 27998 } 27999 mem = ori_mem; 28000 i += _soc_mem_shared_hash_incr_per_entry(unit, mem, 28001 move_entry, entry); 28002 continue; 28003 } 28004 /* Delete old entry from original location */ 28005 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, (uint32)1<<cb, 28006 move_entry, NULL, NULL); 28007 mem = ori_mem; 28008 if ((rv < 0) && (rv != SOC_E_FULL)) { 28009 break; 28010 } 28011 } /* Bucket iteration loop. */ 28012 28013 if (found || ((rv < 0) && (rv != SOC_E_FULL))) { 28014 break; 28015 } 28016 } 28017 28018 if (!recurse && !found && (rv == SOC_E_NONE || rv == SOC_E_FULL)) { 28019 /* Recursive call - attempt to go deeper in the hierarchy. */ 28020 rv = _soc_mem_shared_hash_breadth_move(unit, mem, banks, copyno, entry, 28021 trace, TRUE, recurse_depth, 28022 &bank_inf); 28023 if (SOC_SUCCESS(rv)) { 28024 goto clean_up; 28025 } 28026 } 28027 28028 /* Bank iteration loop. */ 28029 if ((rv < 0) && (rv != SOC_E_FULL)) { 28030 goto clean_up; 28031 } 28032 if (!found) { 28033 rv = SOC_E_FULL; 28034 goto clean_up; 28035 } 28036 28037 rv = soc_mem_generic_insert(unit, mem, copyno, (uint32)1<<cb, 28038 entry, entry, NULL); 28039 if (rv) { 28040 LOG_VERBOSE(BSL_LS_SOC_COMMON, 28041 (BSL_META_U(unit, 28042 "Insert entry: %d\n"), rv)); 28043 } 28044 28045 clean_up: 28046 if (NULL == bucket_trace) { 28047 sal_free(trace); 28048 } 28049 28050 return rv; 28051 } 28052 28053 28054 STATIC int 28055 _soc_mem_shared_hash_insert(int unit, soc_mem_t mem, int copyno, 28056 void *entry_data, void *old_entry_data, 28057 int recurse_depth) 28058 { 28059 int rv = SOC_E_NONE; 28060 rv = soc_mem_bank_insert(unit, mem, SOC_MEM_HASH_BANK_ALL, copyno, 28061 entry_data, old_entry_data); 28062 if (rv != SOC_E_FULL) { 28063 return rv; 28064 } 28065 28066 /* Time to shuffle the entries */ 28067 soc_mem_lock(unit, mem); 28068 switch (SOC_MULTI_HASH_MOVE_ALGORITHM(unit)) { 28069 case MULTI_MOVE_MODE_LEGACY: 28070 rv = _soc_mem_shared_hash_move(unit, mem, SOC_MEM_HASH_BANK_ALL, 28071 copyno, entry_data, NULL, 28072 recurse_depth - 1, NULL); 28073 break; 28074 case MULTI_MOVE_MODE_MIX: 28075 rv = _soc_mem_shared_hash_breadth_move(unit, mem, SOC_MEM_HASH_BANK_ALL, 28076 copyno, entry_data, NULL, 0, 28077 recurse_depth - 1, NULL); 28078 break; 28079 case MULTI_MOVE_MODE_DEPTH_FAST: 28080 case MULTI_MOVE_MODE_DEPTH: 28081 rv = _soc_mem_shared_hash_depth_move(unit, mem, SOC_MEM_HASH_BANK_ALL, 28082 copyno, entry_data, 28083 recurse_depth - 1, NULL, NULL); 28084 break; 28085 default: 28086 if (mem == L2Xm) { 28087 rv = _soc_mem_shared_hash_breadth_l2_move(unit, mem, copyno, 28088 entry_data, recurse_depth); 28089 } else { 28090 #ifdef BCM_TRIDENT3_SUPPORT 28091 if (SOC_IS_TRIDENT3X(unit)) { 28092 rv = _soc_mem_shared_hash_td3_breadth_mix_move(unit, mem, copyno, 28093 entry_data, recurse_depth); 28094 } else 28095 #endif /* BCM_TRIDENT3_SUPPORT */ 28096 #ifdef BCM_TOMAHAWK3_SUPPORT 28097 if (SOC_IS_TOMAHAWK3(unit)) { 28098 rv = _soc_mem_shared_hash_tomahawk3_breadth_mix_move(unit, mem, copyno, 28099 entry_data, recurse_depth); 28100 } else 28101 #endif /* BCM_TOMAHAWK3_SUPPORT */ 28102 { 28103 rv = _soc_mem_shared_hash_breadth_mix_move(unit, mem, copyno, 28104 entry_data, recurse_depth); 28105 } 28106 } 28107 break; 28108 } 28109 soc_mem_unlock(unit, mem); 28110 28111 return rv; 28112 } 28113 #endif /* BCM_TRIDENT2_SUPPORT */ 28114 28115 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT \ 28116 || BCM_RAVEN_SUPPORT */ 28117 28118 /* 28119 * Function: 28120 * _soc_mem_insert 28121 * Purpose: 28122 * Helper routine for soc_mem_insert 28123 */ 28124 28125 STATIC int 28126 _soc_mem_insert(int unit, 28127 soc_mem_t mem, /* Assumes memory locked */ 28128 int copyno, 28129 void *entry_data) 28130 { 28131 uint32 entry_tmp[SOC_MAX_MEM_WORDS]; 28132 int max, ins_index, index, last, rv; 28133 28134 max = soc_mem_index_max(unit, mem); 28135 last = soc_mem_index_last(unit, mem, copyno); 28136 28137 rv = soc_mem_search(unit, mem, copyno, 28138 &ins_index, entry_data, entry_tmp, 0); 28139 28140 if (rv == SOC_E_NONE) { 28141 /* If entry with matching key already exists, overwrite it. */ 28142 28143 if ((rv = soc_mem_write(unit, mem, copyno, 28144 ins_index, entry_data)) < 0) { 28145 LOG_ERROR(BSL_LS_SOC_SOCMEM, 28146 (BSL_META_U(unit, 28147 "soc_mem_insert: write %s.%s[%d] failed\n"), 28148 SOC_MEM_UFNAME(unit, mem), 28149 SOC_BLOCK_NAME(unit, copyno), ins_index)); 28150 return rv; 28151 } 28152 28153 return SOC_E_NONE; 28154 } 28155 28156 if (rv != SOC_E_NOT_FOUND) { 28157 return rv; 28158 } 28159 28160 /* Point to first unused entry; fail if table is already full. */ 28161 28162 if ((index = last + 1) > max) { 28163 return SOC_E_FULL; 28164 } 28165 28166 while (index > ins_index) { 28167 /* Move up one entry */ 28168 28169 if ((rv = soc_mem_read(unit, mem, copyno, 28170 index - 1, entry_tmp)) < 0) { 28171 LOG_ERROR(BSL_LS_SOC_SOCMEM, 28172 (BSL_META_U(unit, 28173 "soc_mem_insert: read %s.%s[%d] failed\n"), 28174 SOC_MEM_UFNAME(unit, mem), 28175 SOC_BLOCK_NAME(unit, copyno), index - 1)); 28176 return rv; 28177 } 28178 28179 if ((rv = soc_mem_write(unit, mem, copyno, 28180 index, entry_tmp)) < 0) { 28181 LOG_ERROR(BSL_LS_SOC_SOCMEM, 28182 (BSL_META_U(unit, 28183 "soc_mem_insert: write %s.%s[%d] failed\n"), 28184 SOC_MEM_UFNAME(unit, mem), 28185 SOC_BLOCK_NAME(unit, copyno), index)); 28186 return rv; 28187 } 28188 28189 index--; 28190 } 28191 28192 /* Write entry data at insertion point */ 28193 28194 if ((rv = soc_mem_write(unit, mem, copyno, 28195 ins_index, entry_data)) < 0) { 28196 LOG_ERROR(BSL_LS_SOC_SOCMEM, 28197 (BSL_META_U(unit, 28198 "soc_mem_insert: write %s.%s[%d] failed\n"), 28199 SOC_MEM_UFNAME(unit, mem), 28200 SOC_BLOCK_NAME(unit, copyno), ins_index)); 28201 return rv; 28202 } 28203 _SOC_MEM_REUSE_MEM_STATE(unit, mem); 28204 SOP_MEM_STATE(unit, mem).count[copyno]++; 28205 28206 return SOC_E_NONE; 28207 } 28208 28209 /* 28210 * Function: 28211 * soc_mem_insert 28212 * Purpose: 28213 * Insert an entry into a structured table based on key. 28214 * Returns: 28215 * SOC_E_NONE - insertion succeeded 28216 * SOC_E_FULL - table full 28217 * SOC_E_XXX - other error 28218 * Notes: 28219 * Tables may be binary, hashed, CAM, or command. 28220 * 28221 * Binary tables: 28222 * A binary search is made for the entry, and if a matching key is 28223 * found, the entry is overwritten with new data, and 0 is returned. 28224 * If key is not found: 28225 * Starting with the last entry (kept in soc_control_t structure), 28226 * entries are moved down until a space is made for the required 28227 * index. The moving process results in temporary duplicates but not 28228 * temporarily-out-of-order entries. 28229 * Fails if the table is already full before the insert. 28230 * 28231 * Hashed tables: 28232 * The entry is passed to the hardware, which performs a hash 28233 * calculation on the key. The entry will be added to the 28234 * corresponding hash bucket, if an available slot exists. 28235 * Fails if the hash bucket for that key is full. 28236 * 28237 * CAM tables: 28238 * Entries are added to the CAM based on the device's 28239 * implementation-specific algorithm. 28240 * Fails if table resources are exhausted. 28241 * 28242 * Command supported tables: 28243 * Uses memory command hardware support to handle table state, 28244 * based on the entry key. 28245 * Fails if hardware insert operation is unsuccessful. 28246 * 28247 * If COPYNO_ALL is specified, the insertion is repeated for each 28248 * copy of the table. 28249 */ 28250 28251 int 28252 soc_mem_insert(int unit, 28253 soc_mem_t mem, 28254 int copyno, 28255 void *entry_data) 28256 { 28257 int rv = SOC_E_NONE; 28258 28259 #ifdef BCM_TRIDENT3_SUPPORT 28260 soc_mem_t phy_mem; 28261 #endif 28262 28263 #ifdef BCM_TRIDENT3_SUPPORT 28264 if (soc_feature(unit, soc_feature_flex_flow)) { 28265 if (SOC_MEM_IS_VIEW(unit, mem)) { 28266 rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem); 28267 if (rv != SOC_E_NONE) { 28268 return rv; 28269 } 28270 mem = phy_mem; 28271 } 28272 } 28273 #endif 28274 28275 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE)); 28276 28277 assert(soc_mem_is_sorted(unit, mem) || 28278 soc_mem_is_hashed(unit, mem) || 28279 soc_mem_is_cam(unit, mem) || 28280 soc_mem_is_cmd(unit, mem)); 28281 assert(entry_data); 28282 28283 if (copyno == COPYNO_ALL) { 28284 28285 #ifdef BCM_TRX_SUPPORT 28286 if (SOC_IS_TRX(unit)) { 28287 _SOC_MEM_REPLACE_MEM(unit, mem); 28288 switch (mem) { 28289 case MPLS_ENTRYm: 28290 if (SOC_IS_SC_CQ(unit) || SOC_IS_TRIDENT3X(unit)) { 28291 break; 28292 } 28293 case VLAN_XLATEm: 28294 case EGR_VLAN_XLATEm: 28295 #ifdef BCM_ISM_SUPPORT 28296 if (soc_feature(unit, soc_feature_ism_memory)) { 28297 break; 28298 } 28299 #endif /* BCM_ISM_SUPPORT */ 28300 case VLAN_MACm: 28301 case AXP_WRX_WCDm: 28302 case AXP_WRX_SVP_ASSIGNMENTm: 28303 #ifdef BCM_TRIUMPH3_SUPPORT 28304 case FT_SESSIONm: 28305 case FT_SESSION_IPV6m: 28306 #endif /* BCM_TRIUMPH3_SUPPORT */ 28307 #ifdef BCM_TRIDENT2_SUPPORT 28308 case ING_VP_VLAN_MEMBERSHIPm: 28309 case EGR_VP_VLAN_MEMBERSHIPm: 28310 case ING_DNAT_ADDRESS_TYPEm: 28311 case L2_ENDPOINT_IDm: 28312 case ENDPOINT_QUEUE_MAPm: 28313 #ifdef BCM_TRIDENT3_SUPPORT 28314 case SUBPORT_ID_TO_SGPP_MAPm: 28315 #endif /* BCM_TRIDENT3_SUPPORT */ 28316 #endif /* BCM_TRIDENT2_SUPPORT */ 28317 #ifdef BCM_KATANA2_SUPPORT 28318 case EGR_MP_GROUPm: 28319 #endif 28320 #ifdef BCM_SABER2_SUPPORT 28321 case MP_GROUPm: 28322 #endif 28323 return _soc_mem_dual_hash_insert(unit, mem, copyno, 28324 entry_data, NULL, 28325 soc_dual_hash_recurse_depth_get(unit, mem)); 28326 default: 28327 break; 28328 } 28329 } 28330 #endif /* BCM_TRX_SUPPORT */ 28331 28332 #ifdef BCM_FIREBOLT_SUPPORT 28333 if (SOC_IS_FBX(unit)) { 28334 switch (mem) { 28335 case L2Xm: 28336 #ifdef BCM_TRIDENT2_SUPPORT 28337 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 28338 return _soc_mem_shared_hash_insert(unit, mem, copyno, 28339 entry_data, NULL, 28340 soc_multi_hash_recurse_depth_get(unit, mem)); 28341 } 28342 #endif /* BCM_TRIDENT2_SUPPORT */ 28343 return soc_fb_l2x_insert(unit, entry_data); 28344 #if defined(INCLUDE_L3) 28345 case L3_DEFIPm: 28346 case L3_DEFIP_LEVEL1m: 28347 return soc_fb_lpm_insert(unit, entry_data); 28348 case MPLS_ENTRYm: 28349 /* If TD3 then pass through */ 28350 if (!SOC_IS_TRIDENT3X(unit)) { 28351 break; 28352 } 28353 case L3_ENTRY_ONLYm: 28354 case L3_ENTRY_IPV4_UNICASTm: 28355 case L3_ENTRY_IPV4_MULTICASTm: 28356 case L3_ENTRY_IPV6_UNICASTm: 28357 case L3_ENTRY_IPV6_MULTICASTm: 28358 case EXACT_MATCH_2m: 28359 case EXACT_MATCH_2_PIPE0m: 28360 case EXACT_MATCH_2_PIPE1m: 28361 case EXACT_MATCH_2_PIPE2m: 28362 case EXACT_MATCH_2_PIPE3m: 28363 case EXACT_MATCH_4m: 28364 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 28365 case L3_ENTRY_SINGLEm: 28366 case L3_ENTRY_DOUBLEm: 28367 case L3_ENTRY_QUADm: 28368 case L3_TUNNEL_SINGLEm: 28369 case L3_TUNNEL_DOUBLEm: 28370 case L3_TUNNEL_QUADm: 28371 case MPLS_ENTRY_SINGLEm: 28372 case VLAN_XLATE_1_SINGLEm: 28373 case VLAN_XLATE_1_DOUBLEm: 28374 case VLAN_XLATE_2_SINGLEm: 28375 case VLAN_XLATE_2_DOUBLEm: 28376 case EGR_VLAN_XLATE_1_SINGLEm: 28377 case EGR_VLAN_XLATE_1_DOUBLEm: 28378 case EGR_VLAN_XLATE_2_SINGLEm: 28379 case EGR_VLAN_XLATE_2_DOUBLEm: 28380 #endif 28381 case EXACT_MATCH_4_PIPE0m: 28382 case EXACT_MATCH_4_PIPE1m: 28383 case EXACT_MATCH_4_PIPE2m: 28384 case EXACT_MATCH_4_PIPE3m: 28385 #ifdef BCM_HELIX5_SUPPORT 28386 case FT_KEY_SINGLEm: 28387 case FT_KEY_DOUBLEm: 28388 #endif 28389 #ifdef BCM_TRIDENT2_SUPPORT 28390 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 28391 return _soc_mem_shared_hash_insert(unit, mem, copyno, 28392 entry_data, NULL, 28393 soc_multi_hash_recurse_depth_get(unit, mem)); 28394 } 28395 #endif /* BCM_TRIDENT2_SUPPORT */ 28396 return soc_fb_l3x_insert(unit, entry_data); 28397 #endif /* INCLUDE_L3 */ 28398 case VLAN_MACm: 28399 #if defined(BCM_RAVEN_SUPPORT) 28400 if (soc_feature(unit, soc_feature_dual_hash) && 28401 (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) { 28402 return _soc_mem_dual_hash_insert(unit, mem, copyno, 28403 entry_data, NULL, 28404 soc_dual_hash_recurse_depth_get(unit, mem)); 28405 } else 28406 #endif 28407 { 28408 return soc_fb_vlanmac_entry_ins(unit, entry_data); 28409 } 28410 #ifdef BCM_TRIUMPH3_SUPPORT 28411 case EXT_L2_ENTRY_1m: 28412 case EXT_L2_ENTRY_2m: 28413 return soc_mem_generic_insert(unit, mem, copyno, -1, 28414 entry_data, NULL, NULL); 28415 #endif /* BCM_TRIUMPH3_SUPPORT */ 28416 default: 28417 break; 28418 } 28419 } 28420 #endif /* BCM_FIREBOLT_SUPPORT */ 28421 28422 #ifdef BCM_ISM_SUPPORT 28423 if (soc_feature(unit, soc_feature_ism_memory) && 28424 soc_mem_is_mview(unit, mem)) { 28425 return _soc_mem_multi_hash_insert(unit, mem, copyno, entry_data, 28426 NULL, soc_multi_hash_recurse_depth_get(unit, mem)); 28427 } 28428 #endif /* BCM_ISM_SUPPORT */ 28429 28430 MEM_LOCK(unit, mem); 28431 SOC_MEM_BLOCK_ITER(unit, mem, copyno) { 28432 if ((rv = _soc_mem_insert(unit, mem, copyno, entry_data)) < 0) { 28433 break; 28434 } 28435 } 28436 } else { 28437 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 28438 MEM_LOCK(unit, mem); 28439 rv = _soc_mem_insert(unit, mem, copyno, entry_data); 28440 } 28441 28442 MEM_UNLOCK(unit, mem); 28443 28444 return rv; 28445 } 28446 28447 /* 28448 * Function: 28449 * soc_mem_insert_return_old 28450 * Purpose: 28451 * Same as soc_mem_insert() with the additional feature 28452 * that if an exiting entry was replaced, the old entry data 28453 * is returned back. 28454 * Returns: 28455 * SOC_E_NONE - insertion succeeded 28456 * SOC_E_EXISTS - insertion succeeded, old_entry_data is valid 28457 * SOC_E_FULL - table full 28458 * SOC_E_UNAVAIL - not supported on the specified unit, mem 28459 * SOC_E_XXX - other error 28460 */ 28461 int 28462 soc_mem_insert_return_old(int unit, 28463 soc_mem_t mem, 28464 int copyno, 28465 void *entry_data, 28466 void *old_entry_data) 28467 { 28468 #ifdef BCM_TRIDENT3_SUPPORT 28469 int rv = SOC_E_NONE; 28470 soc_mem_t phy_mem; 28471 #endif 28472 28473 #ifdef BCM_TRIDENT3_SUPPORT 28474 if (soc_feature(unit, soc_feature_flex_flow)) { 28475 if (SOC_MEM_IS_VIEW(unit, mem)) { 28476 rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem); 28477 if (rv != SOC_E_NONE) { 28478 return rv; 28479 } 28480 mem = phy_mem; 28481 } 28482 } 28483 #endif 28484 #ifdef BCM_TRX_SUPPORT 28485 if (SOC_IS_TRX(unit)) { 28486 _SOC_MEM_REPLACE_MEM(unit, mem); 28487 switch (mem) { 28488 case L2Xm: /* Note: the order of the case statements should be 28489 changed with care */ 28490 #if defined(INCLUDE_L3) 28491 case L3_ENTRY_ONLYm: 28492 case L3_ENTRY_IPV4_UNICASTm: 28493 case L3_ENTRY_IPV4_MULTICASTm: 28494 case L3_ENTRY_IPV6_UNICASTm: 28495 case L3_ENTRY_IPV6_MULTICASTm: 28496 #endif /* INCLUDE_L3 */ 28497 case EXACT_MATCH_2m: 28498 case EXACT_MATCH_2_PIPE0m: 28499 case EXACT_MATCH_2_PIPE1m: 28500 case EXACT_MATCH_2_PIPE2m: 28501 case EXACT_MATCH_2_PIPE3m: 28502 case EXACT_MATCH_4m: 28503 case EXACT_MATCH_4_PIPE0m: 28504 case EXACT_MATCH_4_PIPE1m: 28505 case EXACT_MATCH_4_PIPE2m: 28506 case EXACT_MATCH_4_PIPE3m: 28507 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 28508 case L3_ENTRY_SINGLEm: 28509 case L3_ENTRY_DOUBLEm: 28510 case L3_ENTRY_QUADm: 28511 case MPLS_ENTRY_SINGLEm: 28512 case VLAN_XLATE_1_SINGLEm: 28513 case VLAN_XLATE_1_DOUBLEm: 28514 case VLAN_XLATE_2_SINGLEm: 28515 case VLAN_XLATE_2_DOUBLEm: 28516 case EGR_VLAN_XLATE_1_SINGLEm: 28517 case EGR_VLAN_XLATE_1_DOUBLEm: 28518 case EGR_VLAN_XLATE_2_SINGLEm: 28519 case EGR_VLAN_XLATE_2_DOUBLEm: 28520 #endif 28521 #ifdef BCM_TRIDENT2_SUPPORT 28522 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 28523 return _soc_mem_shared_hash_insert(unit, mem, copyno, entry_data, 28524 NULL, soc_multi_hash_recurse_depth_get(unit, mem)); 28525 } else 28526 #endif /* BCM_TRIDENT2_SUPPORT */ 28527 { 28528 return _soc_mem_dual_hash_insert(unit, mem, copyno, 28529 entry_data, old_entry_data, 28530 soc_dual_hash_recurse_depth_get(unit, mem)); 28531 } 28532 case MPLS_ENTRYm: /* Note: the order of the case statements should be 28533 changed with care */ 28534 if (SOC_IS_SC_CQ(unit)) { 28535 break; 28536 } 28537 /* passthru */ 28538 /* coverity[fallthrough: FALSE] */ 28539 case EGR_VLAN_XLATEm: 28540 case VLAN_XLATEm: 28541 case VLAN_MACm: 28542 case AXP_WRX_WCDm: 28543 case AXP_WRX_SVP_ASSIGNMENTm: 28544 #ifdef BCM_TRIUMPH3_SUPPORT 28545 case FT_SESSIONm: 28546 case FT_SESSION_IPV6m: 28547 #endif /* BCM_TRIUMPH3_SUPPORT */ 28548 #ifdef BCM_TRIDENT2_SUPPORT 28549 case ING_VP_VLAN_MEMBERSHIPm: 28550 case EGR_VP_VLAN_MEMBERSHIPm: 28551 case ING_DNAT_ADDRESS_TYPEm: 28552 case L2_ENDPOINT_IDm: 28553 case ENDPOINT_QUEUE_MAPm: 28554 #endif /* BCM_TRIDENT2_SUPPORT */ 28555 #ifdef BCM_ISM_SUPPORT 28556 if (soc_feature(unit, soc_feature_ism_memory) && 28557 soc_mem_is_mview(unit, mem)) { 28558 return _soc_mem_multi_hash_insert(unit, mem, copyno, 28559 entry_data, old_entry_data, 28560 soc_multi_hash_recurse_depth_get(unit, mem)); 28561 } else 28562 #endif /* BCM_ISM_SUPPORT */ 28563 { 28564 return _soc_mem_dual_hash_insert(unit, mem, copyno, 28565 entry_data, old_entry_data, 28566 soc_dual_hash_recurse_depth_get(unit, mem)); 28567 } 28568 #ifdef BCM_TRIUMPH3_SUPPORT 28569 case EXT_L2_ENTRY_1m: 28570 case EXT_L2_ENTRY_2m: 28571 return soc_mem_generic_insert(unit, mem, copyno, -1, 28572 entry_data, old_entry_data, NULL); 28573 #endif /* BCM_TRIUMPH3_SUPPORT */ 28574 #ifdef BCM_ISM_SUPPORT 28575 case L2_ENTRY_1m: 28576 case L2_ENTRY_2m: 28577 case L3_ENTRY_1m: 28578 case L3_ENTRY_2m: 28579 case L3_ENTRY_4m: 28580 case VLAN_XLATE_EXTDm: 28581 case MPLS_ENTRY_EXTDm: 28582 return _soc_mem_multi_hash_insert(unit, mem, copyno, 28583 entry_data, old_entry_data, 28584 soc_multi_hash_recurse_depth_get(unit, mem)); 28585 #endif /* BCM_ISM_SUPPORT */ 28586 break; 28587 } 28588 } 28589 #endif 28590 return SOC_E_UNAVAIL; 28591 } 28592 28593 /* 28594 * Function: 28595 * _soc_mem_delete_index 28596 * Purpose: 28597 * Helper function for soc_mem_delete and soc_mem_delete_index. 28598 */ 28599 28600 STATIC int 28601 _soc_mem_delete_index(int unit, 28602 soc_mem_t mem, /* Assumes memory locked */ 28603 int copyno, 28604 int del_index) 28605 { 28606 uint32 entry_tmp[SOC_MAX_MEM_WORDS]; 28607 int min, index, eot_index, rv; 28608 28609 /* eot_index points one past last entry in use */ 28610 28611 if (soc_mem_is_cam(unit, mem)) { 28612 index = del_index; 28613 } else { 28614 min = soc_mem_index_min(unit, mem); 28615 eot_index = soc_mem_index_last(unit, mem, copyno) + 1; 28616 28617 if (del_index < min || del_index >= eot_index) { 28618 return SOC_E_NOT_FOUND; 28619 } 28620 28621 for (index = del_index; index + 1 < eot_index; index++) { 28622 /* Move down one entry */ 28623 28624 if ((rv = soc_mem_read(unit, mem, copyno, 28625 index + 1, entry_tmp)) < 0) { 28626 LOG_ERROR(BSL_LS_SOC_SOCMEM, 28627 (BSL_META_U(unit, 28628 "soc_mem_delete_index: " 28629 "read %s.%s[%d] failed\n"), 28630 SOC_MEM_UFNAME(unit, mem), 28631 SOC_BLOCK_NAME(unit, copyno), index + 1)); 28632 return rv; 28633 } 28634 28635 if ((rv = soc_mem_write(unit, mem, copyno, 28636 index, entry_tmp)) < 0) { 28637 LOG_ERROR(BSL_LS_SOC_SOCMEM, 28638 (BSL_META_U(unit, 28639 "soc_mem_delete_index: " 28640 "write %s.%s[%d] failed\n"), 28641 SOC_MEM_UFNAME(unit, mem), 28642 SOC_BLOCK_NAME(unit, copyno), index)); 28643 return rv; 28644 } 28645 } 28646 } 28647 28648 if ((rv = soc_mem_write(unit, mem, copyno, index, 28649 soc_mem_entry_null(unit, mem))) < 0) { 28650 LOG_ERROR(BSL_LS_SOC_SOCMEM, 28651 (BSL_META_U(unit, 28652 "soc_mem_delete_index: " 28653 "write %s.%s[%d] failed\n"), 28654 SOC_MEM_UFNAME(unit, mem), 28655 SOC_BLOCK_NAME(unit, copyno), index + 1)); 28656 return rv; 28657 } 28658 _SOC_MEM_REUSE_MEM_STATE(unit, mem); 28659 SOP_MEM_STATE(unit, mem).count[copyno]--; 28660 28661 return SOC_E_NONE; 28662 } 28663 28664 /* 28665 * Function: 28666 * soc_mem_delete_index 28667 * Purpose: 28668 * Delete an entry from a sorted table based on index, 28669 * moving up all successive entries. 28670 * Notes: 28671 * If COPYNO_ALL is specified, the deletion is repeated for each 28672 * copy of the table. 28673 * 28674 * For deletes from the ARL, reads the entry and requests hardware 28675 * deletion by key. This shouldn't generally be done, because the 28676 * hardware may change the ARL table at any time. 28677 */ 28678 28679 int 28680 soc_mem_delete_index(int unit, 28681 soc_mem_t mem, 28682 int copyno, 28683 int index) 28684 { 28685 int rv = SOC_E_NONE; 28686 28687 assert(soc_mem_is_sorted(unit, mem) || 28688 soc_mem_is_hashed(unit, mem) || 28689 soc_mem_is_cam(unit, mem) || 28690 soc_mem_is_cmd(unit, mem)); 28691 28692 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 28693 28694 #ifdef BCM_TRX_SUPPORT 28695 if (soc_feature(unit, soc_feature_generic_table_ops)) { 28696 uint32 entry_tmp[SOC_MAX_MEM_WORDS]; 28697 _SOC_MEM_REPLACE_MEM(unit, mem); 28698 switch (mem) { 28699 case L2Xm: 28700 case L3_ENTRY_IPV4_UNICASTm: 28701 case L3_ENTRY_IPV4_MULTICASTm: 28702 case L3_ENTRY_IPV6_UNICASTm: 28703 case L3_ENTRY_IPV6_MULTICASTm: 28704 case EXACT_MATCH_2m: 28705 case EXACT_MATCH_2_PIPE0m: 28706 case EXACT_MATCH_2_PIPE1m: 28707 case EXACT_MATCH_2_PIPE2m: 28708 case EXACT_MATCH_2_PIPE3m: 28709 case EXACT_MATCH_4m: 28710 case EXACT_MATCH_4_PIPE0m: 28711 case EXACT_MATCH_4_PIPE1m: 28712 case EXACT_MATCH_4_PIPE2m: 28713 case EXACT_MATCH_4_PIPE3m: 28714 case EGR_VLAN_XLATEm: 28715 case VLAN_XLATEm: 28716 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 28717 case L3_ENTRY_SINGLEm: 28718 case L3_ENTRY_DOUBLEm: 28719 case L3_ENTRY_QUADm: 28720 case VLAN_XLATE_1_SINGLEm: 28721 case VLAN_XLATE_2_SINGLEm: 28722 case VLAN_XLATE_1_DOUBLEm: 28723 case VLAN_XLATE_2_DOUBLEm: 28724 case EGR_VLAN_XLATE_1_SINGLEm: 28725 case EGR_VLAN_XLATE_2_SINGLEm: 28726 case EGR_VLAN_XLATE_1_DOUBLEm: 28727 case EGR_VLAN_XLATE_2_DOUBLEm: 28728 case MPLS_ENTRY_SINGLEm: 28729 case SUBPORT_ID_TO_SGPP_MAPm: 28730 #endif 28731 case VLAN_MACm: 28732 case MPLS_ENTRYm: 28733 case AXP_WRX_WCDm: 28734 case AXP_WRX_SVP_ASSIGNMENTm: 28735 #ifdef BCM_TRIDENT2_SUPPORT 28736 case ING_VP_VLAN_MEMBERSHIPm: 28737 case EGR_VP_VLAN_MEMBERSHIPm: 28738 case ING_DNAT_ADDRESS_TYPEm: 28739 case L2_ENDPOINT_IDm: 28740 case ENDPOINT_QUEUE_MAPm: 28741 #endif /* BCM_TRIDENT2_SUPPORT */ 28742 case EXT_L2_ENTRYm: 28743 #ifdef BCM_ISM_SUPPORT 28744 case L2_ENTRY_1m: 28745 case L2_ENTRY_2m: 28746 case L3_ENTRY_1m: 28747 case L3_ENTRY_2m: 28748 case L3_ENTRY_4m: 28749 case VLAN_XLATE_EXTDm: 28750 case MPLS_ENTRY_EXTDm: 28751 #endif /* BCM_ISM_SUPPORT */ 28752 #ifdef BCM_TRIUMPH3_SUPPORT 28753 case EXT_L2_ENTRY_1m: 28754 case EXT_L2_ENTRY_2m: 28755 case FT_SESSIONm: 28756 case FT_SESSION_IPV6m: 28757 #endif /* BCM_TRIUMPH3_SUPPORT */ 28758 #if defined(BCM_KATANA2_SUPPORT) 28759 case EGR_MP_GROUPm: 28760 #endif 28761 #ifdef BCM_SABER2_SUPPORT 28762 case MP_GROUPm: 28763 #endif 28764 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 28765 index, entry_tmp)); 28766 return soc_mem_delete(unit, mem, copyno, entry_tmp); 28767 default: 28768 break; 28769 } 28770 } 28771 #endif /* BCM_TRX_SUPPORT */ 28772 28773 #ifdef BCM_FIREBOLT_SUPPORT 28774 if (SOC_IS_FBX(unit)) { 28775 uint32 entry_tmp[SOC_MAX_MEM_WORDS]; 28776 28777 switch (mem) { 28778 case L3_ENTRY_IPV4_UNICASTm: 28779 case L3_ENTRY_IPV4_MULTICASTm: 28780 case L3_ENTRY_IPV6_UNICASTm: 28781 case L3_ENTRY_IPV6_MULTICASTm: 28782 case L2Xm: 28783 case VLAN_MACm: 28784 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 28785 index, entry_tmp)); 28786 return soc_mem_delete(unit, mem, copyno, entry_tmp); 28787 case L3_DEFIPm: 28788 default: 28789 return (SOC_E_UNAVAIL); 28790 } 28791 } 28792 #endif /* BCM_FIREBOLT_SUPPORT */ 28793 28794 if (copyno != COPYNO_ALL){ 28795 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 28796 MEM_LOCK(unit, mem); 28797 rv = _soc_mem_delete_index(unit, mem, copyno, index); 28798 } 28799 28800 MEM_UNLOCK(unit, mem); 28801 28802 return rv; 28803 } 28804 28805 /* 28806 * Function: 28807 * soc_mem_delete 28808 * Purpose: 28809 * Delete an entry from a sorted table based on key, 28810 * moving up all successive entries. 28811 * Returns: 28812 * 0 on success (whether or not entry was found), 28813 * SOC_E_XXX on read or write error. 28814 * Notes: 28815 * A binary search for the key is performed. If the key is found, 28816 * the entry is deleted by moving up successive entries until 28817 * the last entry is moved up. The previously last entry is 28818 * overwritten with the null key. 28819 * 28820 * If COPYNO_ALL is specified, the deletion is repeated for each copy 28821 * of the table. 28822 */ 28823 28824 int 28825 soc_mem_delete(int unit, 28826 soc_mem_t mem, 28827 int copyno, 28828 void *key_data) 28829 { 28830 int index, rv; 28831 uint32 entry_tmp[SOC_MAX_MEM_WORDS]; 28832 #ifdef BCM_TRIDENT3_SUPPORT 28833 soc_mem_t phy_mem; 28834 #endif 28835 28836 #ifdef BCM_TRIDENT3_SUPPORT 28837 if (soc_feature(unit, soc_feature_flex_flow)) { 28838 if (SOC_MEM_IS_VIEW(unit, mem)) { 28839 rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem); 28840 if (rv != SOC_E_NONE) { 28841 return rv; 28842 } 28843 mem = phy_mem; 28844 } 28845 } 28846 #endif 28847 28848 assert(soc_mem_is_sorted(unit, mem) || 28849 soc_mem_is_hashed(unit, mem) || 28850 soc_mem_is_cam(unit, mem) || 28851 soc_mem_is_cmd(unit, mem)); 28852 assert(key_data); 28853 28854 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE)); 28855 28856 #ifdef BCM_TRX_SUPPORT 28857 if (soc_feature(unit, soc_feature_generic_table_ops)) { 28858 int32 banks = 0; 28859 _SOC_MEM_REPLACE_MEM(unit, mem); 28860 switch (mem) { 28861 case L2Xm: 28862 case L3_ENTRY_IPV4_UNICASTm: 28863 case L3_ENTRY_IPV4_MULTICASTm: 28864 case L3_ENTRY_IPV6_UNICASTm: 28865 case L3_ENTRY_IPV6_MULTICASTm: 28866 case EXACT_MATCH_2m: 28867 case EXACT_MATCH_2_PIPE0m: 28868 case EXACT_MATCH_2_PIPE1m: 28869 case EXACT_MATCH_2_PIPE2m: 28870 case EXACT_MATCH_2_PIPE3m: 28871 case EXACT_MATCH_4m: 28872 case EXACT_MATCH_4_PIPE0m: 28873 case EXACT_MATCH_4_PIPE1m: 28874 case EXACT_MATCH_4_PIPE2m: 28875 case EXACT_MATCH_4_PIPE3m: 28876 #ifdef BCM_ISM_SUPPORT 28877 case L2_ENTRY_1m: 28878 case L2_ENTRY_2m: 28879 case L3_ENTRY_1m: 28880 case L3_ENTRY_2m: 28881 case L3_ENTRY_4m: 28882 case VLAN_XLATE_EXTDm: 28883 case MPLS_ENTRY_EXTDm: 28884 #endif /* BCM_ISM_SUPPORT */ 28885 case EGR_VLAN_XLATEm: 28886 case VLAN_XLATEm: 28887 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 28888 case L3_ENTRY_SINGLEm: 28889 case L3_ENTRY_DOUBLEm: 28890 case L3_ENTRY_QUADm: 28891 case VLAN_XLATE_1_SINGLEm: 28892 case VLAN_XLATE_2_SINGLEm: 28893 case VLAN_XLATE_1_DOUBLEm: 28894 case VLAN_XLATE_2_DOUBLEm: 28895 case EGR_VLAN_XLATE_1_SINGLEm: 28896 case EGR_VLAN_XLATE_2_SINGLEm: 28897 case EGR_VLAN_XLATE_1_DOUBLEm: 28898 case EGR_VLAN_XLATE_2_DOUBLEm: 28899 case MPLS_ENTRY_SINGLEm: 28900 case L3_TUNNEL_SINGLEm: 28901 case SUBPORT_ID_TO_SGPP_MAPm: 28902 #endif 28903 case MPLS_ENTRYm: 28904 /* passthru */ 28905 /* coverity[fallthrough: FALSE] */ 28906 #ifdef BCM_TRIUMPH3_SUPPORT 28907 case AXP_WRX_WCDm: 28908 case AXP_WRX_SVP_ASSIGNMENTm: 28909 case EXT_L2_ENTRY_1m: 28910 case EXT_L2_ENTRY_2m: 28911 case FT_SESSIONm: 28912 case FT_SESSION_IPV6m: 28913 #endif /* BCM_TRIUMPH3_SUPPORT */ 28914 case VLAN_MACm: 28915 #ifdef BCM_TRIDENT2_SUPPORT 28916 case ING_VP_VLAN_MEMBERSHIPm: 28917 case EGR_VP_VLAN_MEMBERSHIPm: 28918 case ING_DNAT_ADDRESS_TYPEm: 28919 case L2_ENDPOINT_IDm: 28920 case ENDPOINT_QUEUE_MAPm: 28921 #endif /* BCM_TRIDENT2_SUPPORT */ 28922 #if defined(BCM_KATANA2_SUPPORT) 28923 case EGR_MP_GROUPm: 28924 #endif 28925 #ifdef BCM_SABER2_SUPPORT 28926 case MP_GROUPm: 28927 #endif 28928 case EXT_L2_ENTRYm: 28929 #ifdef BCM_HELIX5_SUPPORT 28930 case FT_KEY_SINGLEm: 28931 case FT_KEY_DOUBLEm: 28932 #endif 28933 if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) { 28934 banks = -1; 28935 } 28936 return soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 28937 banks, key_data, NULL, 0); 28938 default: 28939 break; 28940 } 28941 } 28942 #endif /* BCM_TRX_SUPPORT */ 28943 28944 #ifdef BCM_FIREBOLT_SUPPORT 28945 if (SOC_IS_FBX(unit)) { 28946 switch (mem) { 28947 case L2Xm: 28948 return soc_fb_l2x_delete(unit, key_data); 28949 #if defined(INCLUDE_L3) 28950 case L3_DEFIPm: 28951 case L3_DEFIP_LEVEL1m: 28952 return soc_fb_lpm_delete(unit, key_data); 28953 case L3_ENTRY_IPV4_UNICASTm: 28954 case L3_ENTRY_IPV4_MULTICASTm: 28955 case L3_ENTRY_IPV6_UNICASTm: 28956 case L3_ENTRY_IPV6_MULTICASTm: 28957 return soc_fb_l3x_delete(unit, key_data); 28958 #endif 28959 case VLAN_MACm: 28960 return soc_fb_vlanmac_entry_del(unit, key_data); 28961 default: 28962 break; 28963 } 28964 } 28965 #endif /* BCM_FIREBOLT_SUPPORT */ 28966 28967 rv = SOC_E_NONE; 28968 if (copyno == COPYNO_ALL) { 28969 MEM_LOCK(unit, mem); 28970 SOC_MEM_BLOCK_ITER(unit, mem, copyno) { 28971 if ((rv = soc_mem_search(unit, mem, copyno, 28972 &index, key_data, entry_tmp, 0)) < 0) { 28973 break; 28974 } 28975 if ((rv = soc_mem_delete_index(unit, mem, copyno, index)) < 0) { 28976 break; 28977 } 28978 } 28979 } else { 28980 assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno)); 28981 MEM_LOCK(unit, mem); 28982 rv = soc_mem_search(unit, mem, copyno, &index, key_data, entry_tmp, 0); 28983 if (rv >= 0) { 28984 rv = soc_mem_delete_index(unit, mem, copyno, index); 28985 } 28986 } 28987 28988 MEM_UNLOCK(unit, mem); 28989 28990 return rv; 28991 } 28992 28993 /* 28994 * Function: 28995 * soc_mem_delete_return_old 28996 * Purpose: 28997 * Same as soc_mem_delete() with the additional feature 28998 * that if an exiting entry was deleted, the old entry data 28999 * is returned back. 29000 * Returns: 29001 * SOC_E_NONE - delete succeeded 29002 * SOC_E_UNAVAIL - not supported on the specified unit, mem 29003 * SOC_E_XXX - other error 29004 */ 29005 int 29006 soc_mem_delete_return_old(int unit, 29007 soc_mem_t mem, 29008 int copyno, 29009 void *key_data, 29010 void *old_entry_data) 29011 { 29012 #ifdef BCM_TRX_SUPPORT 29013 if (SOC_IS_TRX(unit)) { 29014 int32 banks = 0; 29015 _SOC_MEM_REPLACE_MEM(unit, mem); 29016 switch (mem) { 29017 case MPLS_ENTRYm: /* Note: the order of the case statements should 29018 be changed with care */ 29019 if (SOC_IS_SC_CQ(unit)) { 29020 break; 29021 } 29022 /* passthru */ 29023 /* coverity[fallthrough: FALSE] */ 29024 case L2Xm: 29025 case L3_ENTRY_ONLYm: 29026 case L3_ENTRY_IPV4_UNICASTm: 29027 case L3_ENTRY_IPV4_MULTICASTm: 29028 case L3_ENTRY_IPV6_UNICASTm: 29029 case L3_ENTRY_IPV6_MULTICASTm: 29030 case EXACT_MATCH_2m: 29031 case EXACT_MATCH_2_PIPE0m: 29032 case EXACT_MATCH_2_PIPE1m: 29033 case EXACT_MATCH_2_PIPE2m: 29034 case EXACT_MATCH_2_PIPE3m: 29035 case EXACT_MATCH_4m: 29036 case EXACT_MATCH_4_PIPE0m: 29037 case EXACT_MATCH_4_PIPE1m: 29038 case EXACT_MATCH_4_PIPE2m: 29039 case EXACT_MATCH_4_PIPE3m: 29040 #ifdef BCM_ISM_SUPPORT 29041 case L2_ENTRY_1m: 29042 case L2_ENTRY_2m: 29043 case L3_ENTRY_1m: 29044 case L3_ENTRY_2m: 29045 case L3_ENTRY_4m: 29046 case VLAN_XLATE_EXTDm: 29047 case MPLS_ENTRY_EXTDm: 29048 #endif /* BCM_ISM_SUPPORT */ 29049 case EGR_VLAN_XLATEm: 29050 case VLAN_XLATEm: 29051 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 29052 case L3_ENTRY_SINGLEm: 29053 case L3_ENTRY_DOUBLEm: 29054 case L3_ENTRY_QUADm: 29055 case MPLS_ENTRY_SINGLEm: 29056 #endif 29057 #ifdef BCM_TRIDENT3_SUPPORT 29058 case VLAN_XLATE_1_SINGLEm: 29059 case VLAN_XLATE_2_SINGLEm: 29060 case VLAN_XLATE_1_DOUBLEm: 29061 case VLAN_XLATE_2_DOUBLEm: 29062 case EGR_VLAN_XLATE_1_SINGLEm: 29063 case EGR_VLAN_XLATE_2_SINGLEm: 29064 case EGR_VLAN_XLATE_1_DOUBLEm: 29065 case EGR_VLAN_XLATE_2_DOUBLEm: 29066 case SUBPORT_ID_TO_SGPP_MAPm: 29067 #endif 29068 /* passthru */ 29069 /* coverity[fallthrough: FALSE] */ 29070 #ifdef BCM_TRIUMPH3_SUPPORT 29071 case AXP_WRX_WCDm: 29072 case AXP_WRX_SVP_ASSIGNMENTm: 29073 case EXT_L2_ENTRY_1m: 29074 case EXT_L2_ENTRY_2m: 29075 case FT_SESSIONm: 29076 case FT_SESSION_IPV6m: 29077 #endif /* BCM_TRIUMPH3_SUPPORT */ 29078 case VLAN_MACm: 29079 #ifdef BCM_TRIDENT2_SUPPORT 29080 case ING_VP_VLAN_MEMBERSHIPm: 29081 case EGR_VP_VLAN_MEMBERSHIPm: 29082 case ING_DNAT_ADDRESS_TYPEm: 29083 case L2_ENDPOINT_IDm: 29084 case ENDPOINT_QUEUE_MAPm: 29085 #endif /* BCM_TRIDENT2_SUPPORT */ 29086 #ifdef BCM_TRIDENT2PLUS_SUPPORT 29087 if (soc_feature(unit, soc_feature_td2p_a0_sw_war) && 29088 ((mem == EGR_VLAN_XLATEm) || (mem == VLAN_XLATEm))) { 29089 int rv, index; 29090 rv = soc_mem_generic_lookup(unit, mem, copyno, banks, key_data, 29091 old_entry_data, &index); 29092 if (rv == SOC_E_NONE) { 29093 rv = soc_mem_write(unit, mem, copyno, index, 29094 soc_mem_entry_null(unit, mem)); 29095 } 29096 return rv; 29097 } 29098 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 29099 if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) { 29100 banks = -1; 29101 } 29102 return soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 29103 banks, key_data, old_entry_data, 0); 29104 } 29105 } 29106 #endif 29107 return SOC_E_UNAVAIL; 29108 29109 } 29110 29111 #if defined(BCM_TRX_SUPPORT) 29112 /* 29113 * Function: 29114 * _soc_mem_pop 29115 * Purpose: 29116 * Helper function for soc_mem_pop. 29117 */ 29118 STATIC int 29119 _soc_mem_pop(int unit, soc_mem_t mem, int copyno, void *entry_data) 29120 { 29121 schan_msg_t schan_msg; 29122 int rv, entry_dw, allow_intr=0; 29123 uint8 at; 29124 int src_blk, dst_blk, acc_type; 29125 int opcode, nack; 29126 int data_len = 0; 29127 29128 assert(SOC_MEM_IS_VALID(unit, mem)); 29129 assert(soc_attached(unit)); 29130 29131 if (copyno == MEM_BLOCK_ANY) { 29132 /* Overrun of "mem_block_any" is not possible as it is of MAX "mem" value NUM_SOC_MEM */ 29133 /* coverity[overrun-local : FALSE] */ 29134 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 29135 } 29136 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 29137 LOG_WARN(BSL_LS_SOC_SOCMEM, 29138 (BSL_META_U(unit, 29139 "soc_mem_pop: invalid block %d for memory %s\n"), 29140 copyno, SOC_MEM_NAME(unit, mem))); 29141 return SOC_E_PARAM; 29142 } 29143 29144 entry_dw = soc_mem_entry_words(unit, mem); 29145 29146 schan_msg_clear(&schan_msg); 29147 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 29148 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 29149 dst_blk = SOC_BLOCK2SCH(unit, copyno); 29150 29151 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 29152 29153 #ifdef BCM_TOMAHAWK3_SUPPORT 29154 if (SOC_IS_TOMAHAWK3(unit)) { 29155 data_len = 4; 29156 } 29157 #endif 29158 soc_schan_header_cmd_set(unit, &schan_msg.header, FIFO_POP_CMD_MSG, 29159 dst_blk, src_blk, acc_type, data_len, 0, 0); 29160 29161 if (SOC_IS_SAND(unit)) { 29162 allow_intr = 1; 29163 } 29164 29165 /* 29166 * Execute S-Channel "fifo pop" command packet consisting of 29167 * (header word + address word), and read back 29168 * (header word + entry_dw) data words. 29169 */ 29170 29171 rv = soc_schan_op(unit, &schan_msg, 2, entry_dw + 1, allow_intr); 29172 29173 /* Check result */ 29174 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 29175 NULL, NULL, &nack); 29176 if (opcode != FIFO_POP_DONE_MSG) { 29177 LOG_ERROR(BSL_LS_SOC_SOCMEM, 29178 (BSL_META_U(unit, 29179 "soc_mem_pop: " 29180 "invalid S-Channel reply, expected FIFO_POP_DONE_MSG:\n"))); 29181 soc_schan_dump(unit, &schan_msg, entry_dw + 2); 29182 return SOC_E_INTERNAL; 29183 } 29184 29185 if (rv == SOC_E_NONE) { 29186 if (nack != 0) { 29187 rv = SOC_E_NOT_FOUND; 29188 } else { 29189 sal_memcpy(entry_data, schan_msg.popresp.data, entry_dw * 4); 29190 } 29191 } 29192 29193 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 29194 LOG_INFO(BSL_LS_SOC_SOCMEM, 29195 (BSL_META_U(unit, 29196 "Fifo pop: "))); 29197 soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM); 29198 } 29199 29200 return rv; 29201 } 29202 29203 29204 /* 29205 * Function: 29206 * _soc_mem_push 29207 * Purpose: 29208 * Helper function for soc_mem_push. 29209 */ 29210 29211 STATIC int 29212 _soc_mem_push(int unit, soc_mem_t mem, int copyno, void *entry_data) 29213 { 29214 schan_msg_t schan_msg; 29215 int rv, entry_dw, allow_intr=0; 29216 uint8 at; 29217 int src_blk, dst_blk, acc_type, data_byte_len; 29218 int opcode, nack; 29219 29220 assert(SOC_MEM_IS_VALID(unit, mem)); 29221 assert(soc_attached(unit)); 29222 29223 if (copyno == MEM_BLOCK_ANY) { 29224 /* Overrun of "mem_block_any" is not possible as it is of MAX "mem" value NUM_SOC_MEM */ 29225 /* coverity[overrun-local : FALSE] */ 29226 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 29227 } 29228 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 29229 LOG_WARN(BSL_LS_SOC_SOCMEM, 29230 (BSL_META_U(unit, 29231 "soc_mem_push: invalid block %d for memory %s\n"), 29232 copyno, SOC_MEM_NAME(unit, mem))); 29233 return SOC_E_PARAM; 29234 } 29235 29236 entry_dw = soc_mem_entry_words(unit, mem); 29237 29238 schan_msg_clear(&schan_msg); 29239 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 29240 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 29241 dst_blk = SOC_BLOCK2SCH(unit, copyno); 29242 data_byte_len = entry_dw * 4; 29243 29244 schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 29245 29246 /* Fill in packet data */ 29247 sal_memcpy(schan_msg.pushcmd.data, entry_data, data_byte_len); 29248 29249 soc_schan_header_cmd_set(unit, &schan_msg.header, FIFO_PUSH_CMD_MSG, 29250 dst_blk, src_blk, acc_type, 0, 0, 0); 29251 29252 if(SOC_IS_SAND(unit)) { 29253 allow_intr = 1; 29254 } 29255 29256 /* 29257 * Execute S-Channel "fifo push" command packet consisting of 29258 * (header word + address word + entry_dw), and read back 29259 * (header word + entry_dw) data words. 29260 */ 29261 29262 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 1, allow_intr); 29263 29264 /* Check result */ 29265 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL, 29266 NULL, NULL, &nack); 29267 if (opcode != FIFO_PUSH_DONE_MSG) { 29268 LOG_ERROR(BSL_LS_SOC_SOCMEM, 29269 (BSL_META_U(unit, 29270 "soc_mem_push: " 29271 "invalid S-Channel reply, expected FIFO_PUSH_DONE_MSG:\n"))); 29272 soc_schan_dump(unit, &schan_msg, entry_dw + 2); 29273 return SOC_E_INTERNAL; 29274 } 29275 29276 if ((rv == SOC_E_NONE) && (nack != 0)) { 29277 rv = SOC_E_FULL; 29278 } 29279 29280 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 29281 LOG_INFO(BSL_LS_SOC_SOCMEM, 29282 (BSL_META_U(unit, 29283 "Fifo push: "))); 29284 soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM); 29285 } 29286 29287 return rv; 29288 } 29289 29290 #endif /* defined(BCM_TRX_SUPPORT) */ 29291 29292 #if defined(BCM_TRX_SUPPORT) 29293 29294 static const struct { 29295 soc_reg_t cfg; 29296 soc_reg_t sbus_addr; 29297 soc_reg_t hostmem_addr; 29298 soc_reg_t read_ptr; 29299 soc_reg_t write_ptr; 29300 soc_reg_t threshold; 29301 soc_field_t overflow_fld; 29302 int overflow_bit; 29303 } _soc_mem_fifo_dma[] = { 29304 { 29305 CMIC_FIFO_CH0_RD_DMA_CFGr, 29306 CMIC_FIFO_CH0_RD_DMA_SBUS_START_ADDRESSr, 29307 CMIC_FIFO_CH0_RD_DMA_HOSTMEM_START_ADDRESSr, 29308 CMIC_FIFO_CH0_RD_DMA_HOSTMEM_READ_PTRr, 29309 CMIC_FIFO_CH0_RD_DMA_HOSTMEM_WRITE_PTRr, 29310 CMIC_FIFO_CH0_RD_DMA_HOSTMEM_THRESHOLDr, 29311 FIFO_CH0_DMA_HOSTMEM_OVERFLOWf, 29312 0, 29313 }, 29314 { 29315 CMIC_FIFO_CH1_RD_DMA_CFGr, 29316 CMIC_FIFO_CH1_RD_DMA_SBUS_START_ADDRESSr, 29317 CMIC_FIFO_CH1_RD_DMA_HOSTMEM_START_ADDRESSr, 29318 CMIC_FIFO_CH1_RD_DMA_HOSTMEM_READ_PTRr, 29319 CMIC_FIFO_CH1_RD_DMA_HOSTMEM_WRITE_PTRr, 29320 CMIC_FIFO_CH1_RD_DMA_HOSTMEM_THRESHOLDr, 29321 FIFO_CH1_DMA_HOSTMEM_OVERFLOWf, 29322 2, 29323 }, 29324 { 29325 CMIC_FIFO_CH2_RD_DMA_CFGr, 29326 CMIC_FIFO_CH2_RD_DMA_SBUS_START_ADDRESSr, 29327 CMIC_FIFO_CH2_RD_DMA_HOSTMEM_START_ADDRESSr, 29328 CMIC_FIFO_CH2_RD_DMA_HOSTMEM_READ_PTRr, 29329 CMIC_FIFO_CH2_RD_DMA_HOSTMEM_WRITE_PTRr, 29330 CMIC_FIFO_CH2_RD_DMA_HOSTMEM_THRESHOLDr, 29331 FIFO_CH2_DMA_HOSTMEM_OVERFLOWf, 29332 4, 29333 }, 29334 { 29335 CMIC_FIFO_CH3_RD_DMA_CFGr, 29336 CMIC_FIFO_CH3_RD_DMA_SBUS_START_ADDRESSr, 29337 CMIC_FIFO_CH3_RD_DMA_HOSTMEM_START_ADDRESSr, 29338 CMIC_FIFO_CH3_RD_DMA_HOSTMEM_READ_PTRr, 29339 CMIC_FIFO_CH3_RD_DMA_HOSTMEM_WRITE_PTRr, 29340 CMIC_FIFO_CH3_RD_DMA_HOSTMEM_THRESHOLDr, 29341 FIFO_CH3_DMA_HOSTMEM_OVERFLOWf, 29342 6, 29343 }, 29344 }; 29345 STATIC int 29346 _soc_mem_fifo_dma_start(int unit, int chan, soc_mem_t mem, int copyno, 29347 int host_entries, void *host_buf) 29348 { 29349 soc_control_t *soc = SOC_CONTROL(unit); 29350 soc_reg_t cfg_reg; 29351 uint32 addr, rval, data_beats, sel, spacing; 29352 uint8 at; 29353 29354 if (chan < 0 || chan > 3 || host_buf == NULL) { 29355 return SOC_E_PARAM; 29356 } 29357 29358 cfg_reg = _soc_mem_fifo_dma[chan].cfg; 29359 29360 switch (host_entries) { 29361 case 64: sel = 0; break; 29362 case 128: sel = 1; break; 29363 case 256: sel = 2; break; 29364 case 512: sel = 3; break; 29365 case 1024: sel = 4; break; 29366 case 2048: sel = 5; break; 29367 case 4096: sel = 6; break; 29368 case 8192: sel = 7; break; 29369 case 16384: sel = 8; break; 29370 case 32768: sel = 9; break; 29371 case 65536: sel = 10; break; 29372 default: 29373 return SOC_E_PARAM; 29374 } 29375 29376 if (mem != ING_IPFIX_EXPORT_FIFOm && mem != EGR_IPFIX_EXPORT_FIFOm && 29377 mem != EXT_L2_MOD_FIFOm && mem != L2_MOD_FIFOm ) { 29378 return SOC_E_BADID; 29379 } 29380 29381 if (copyno == MEM_BLOCK_ANY) { 29382 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 29383 } 29384 29385 data_beats = soc_mem_entry_words(unit, mem); 29386 29387 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].sbus_addr, REG_PORT_ANY, 29388 0); 29389 rval = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 29390 soc_pci_write(unit, addr, rval); 29391 29392 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].hostmem_addr, 29393 REG_PORT_ANY, 0); 29394 rval = soc_cm_l2p(unit, host_buf); 29395 soc_pci_write(unit, addr, rval); 29396 29397 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].read_ptr, REG_PORT_ANY, 29398 0); 29399 soc_pci_write(unit, addr, rval); 29400 29401 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].threshold, REG_PORT_ANY, 29402 0); 29403 rval = 0; 29404 soc_reg_field_set(unit, _soc_mem_fifo_dma[chan].threshold, &rval, ADDRESSf, 29405 host_entries / 16 * data_beats * sizeof(uint32)); 29406 soc_pci_write(unit, addr, rval); 29407 29408 addr = soc_reg_addr(unit, cfg_reg, REG_PORT_ANY, 0); 29409 rval = 0; 29410 soc_reg_field_set(unit, cfg_reg, &rval, BEAT_COUNTf, data_beats); 29411 soc_reg_field_set(unit, cfg_reg, &rval, HOST_NUM_ENTRIES_SELf, sel); 29412 soc_reg_field_set(unit, cfg_reg, &rval, TIMEOUT_COUNTf, 200); 29413 if (soc_feature(unit, soc_feature_multi_sbus_cmds)) { 29414 29415 if (soc->sbusCmdSpacing < 0) { 29416 spacing = data_beats > 7 ? data_beats + 1 : 8; 29417 } else { 29418 spacing = soc->sbusCmdSpacing; 29419 } 29420 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 29421 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XQPORT) || 29422 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GXPORT) || 29423 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SPORT) || 29424 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GPORT)) { 29425 spacing = 0; 29426 } 29427 if (spacing) { 29428 soc_reg_field_set(unit, cfg_reg, &rval, 29429 MULTIPLE_SBUS_CMD_SPACINGf, spacing); 29430 soc_reg_field_set(unit, cfg_reg, &rval, 29431 ENABLE_MULTIPLE_SBUS_CMDSf, 1); 29432 } 29433 } 29434 soc_pci_write(unit, addr, rval); 29435 29436 soc_reg_field_set(unit, cfg_reg, &rval, ENABLEf, 1); 29437 soc_reg_field_set(unit, cfg_reg, &rval, ENABLE_VALf, 1); 29438 soc_pci_write(unit, addr, rval); 29439 29440 return SOC_E_NONE; 29441 } 29442 29443 STATIC int 29444 _soc_mem_fifo_dma_stop(int unit, int chan) 29445 { 29446 uint32 addr, rval; 29447 29448 if (chan < 0 || chan > 3) { 29449 return SOC_E_PARAM; 29450 } 29451 29452 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].cfg, REG_PORT_ANY, 0); 29453 rval = 0; 29454 soc_reg_field_set(unit, _soc_mem_fifo_dma[chan].cfg, &rval, ENABLEf, 1); 29455 soc_pci_write(unit, addr, rval); 29456 29457 return SOC_E_NONE; 29458 } 29459 29460 STATIC int 29461 _soc_mem_fifo_dma_get_read_ptr(int unit, int chan, void **host_ptr, int *count) 29462 { 29463 soc_reg_t cfg_reg; 29464 int host_entries, data_beats; 29465 uint32 addr, rval, debug, hostmem_addr, read_ptr, write_ptr; 29466 29467 if (chan < 0 || chan > 3 || host_ptr == NULL) { 29468 return SOC_E_PARAM; 29469 } 29470 29471 /* read CFG reg first so that write pointer is valid later on */ 29472 cfg_reg = _soc_mem_fifo_dma[chan].cfg; 29473 addr = soc_reg_addr(unit, cfg_reg, REG_PORT_ANY, 0); 29474 soc_pci_getreg(unit, addr, &rval); 29475 29476 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].read_ptr, REG_PORT_ANY, 29477 0); 29478 soc_pci_getreg(unit, addr, &read_ptr); 29479 29480 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].write_ptr, REG_PORT_ANY, 29481 0); 29482 soc_pci_getreg(unit, addr, &write_ptr); 29483 29484 if (write_ptr == 0 || 29485 (soc_feature(unit, soc_feature_fifo_dma_active) && 29486 !soc_reg_field_get(unit, cfg_reg, rval, ACTIVEf))) { 29487 return SOC_E_EMPTY; 29488 } 29489 29490 if (read_ptr == write_ptr) { 29491 addr = soc_reg_addr(unit, CMIC_FIFO_RD_DMA_DEBUGr, REG_PORT_ANY, 0); 29492 soc_pci_getreg(unit, addr, &debug); 29493 if (!soc_reg_field_get(unit, CMIC_FIFO_RD_DMA_DEBUGr, 29494 debug, _soc_mem_fifo_dma[chan].overflow_fld)) { 29495 return SOC_E_EMPTY; 29496 } 29497 /* Re-read write pointer */ 29498 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].write_ptr, 29499 REG_PORT_ANY, 0); 29500 soc_pci_getreg(unit, addr, &write_ptr); 29501 } 29502 29503 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].hostmem_addr, 29504 REG_PORT_ANY, 0); 29505 soc_pci_getreg(unit, addr, &hostmem_addr); 29506 29507 data_beats = soc_reg_field_get(unit, cfg_reg, rval, BEAT_COUNTf); 29508 if (data_beats <= 0) { 29509 LOG_ERROR(BSL_LS_SOC_SOCMEM, 29510 (BSL_META_U(unit, 29511 "Invalid BEAT_COUNT (%d) in " 29512 "CMIC_FIFO_CH%d_RD_DMA_CFG \n"), data_beats, chan)); 29513 return SOC_E_CONFIG; 29514 } 29515 29516 switch (soc_reg_field_get(unit, cfg_reg, rval, HOST_NUM_ENTRIES_SELf)) { 29517 case 0: host_entries = 64; break; 29518 case 1: host_entries = 128; break; 29519 case 2: host_entries = 256; break; 29520 case 3: host_entries = 512; break; 29521 case 4: host_entries = 1024; break; 29522 case 5: host_entries = 2048; break; 29523 case 6: host_entries = 4096; break; 29524 case 7: host_entries = 8192; break; 29525 case 8: host_entries = 16384; break; 29526 case 9: host_entries = 32768; break; 29527 case 10: host_entries = 65536; break; 29528 default: return SOC_E_CONFIG; 29529 } 29530 29531 *host_ptr = soc_cm_p2l(unit, read_ptr); 29532 if (read_ptr >= write_ptr) { 29533 *count = host_entries - 29534 (read_ptr - hostmem_addr) / data_beats / sizeof(uint32); 29535 } else { 29536 *count = (write_ptr - read_ptr) / data_beats / sizeof(uint32); 29537 } 29538 29539 if (SAL_BOOT_QUICKTURN) { 29540 /* Delay to ensure PCI DMA tranfer to host memory completes */ 29541 sal_usleep(soc_mem_fifo_delay_value); 29542 } 29543 return (*count) ? SOC_E_NONE : SOC_E_EMPTY; 29544 } 29545 29546 STATIC int 29547 _soc_mem_fifo_dma_advance_read_ptr(int unit, int chan, int count) 29548 { 29549 soc_reg_t cfg_reg; 29550 int host_entries, data_beats; 29551 uint32 addr, rval, debug; 29552 uint32 *host_buf, *read_ptr; 29553 29554 if (chan < 0 || chan > 3) { 29555 return SOC_E_PARAM; 29556 } 29557 29558 cfg_reg = _soc_mem_fifo_dma[chan].cfg; 29559 29560 addr = soc_reg_addr(unit, cfg_reg, REG_PORT_ANY, 0); 29561 soc_pci_getreg(unit, addr, &rval); 29562 data_beats = soc_reg_field_get(unit, cfg_reg, rval, BEAT_COUNTf); 29563 29564 switch (soc_reg_field_get(unit, cfg_reg, rval, HOST_NUM_ENTRIES_SELf)) { 29565 case 0: host_entries = 64; break; 29566 case 1: host_entries = 128; break; 29567 case 2: host_entries = 256; break; 29568 case 3: host_entries = 512; break; 29569 case 4: host_entries = 1024; break; 29570 case 5: host_entries = 2048; break; 29571 case 6: host_entries = 4096; break; 29572 case 7: host_entries = 8192; break; 29573 case 8: host_entries = 16384; break; 29574 case 9: host_entries = 32768; break; 29575 case 10: host_entries = 65536; break; 29576 default: return SOC_E_CONFIG; 29577 } 29578 29579 if (count < 0 || count >= host_entries) { 29580 return SOC_E_PARAM; 29581 } 29582 29583 /* Clear threshold overflow bit */ 29584 addr = soc_reg_addr(unit, CMIC_FIFO_RD_DMA_DEBUGr, REG_PORT_ANY, 0); 29585 debug = 0; 29586 soc_reg_field_set(unit, CMIC_FIFO_RD_DMA_DEBUGr, 29587 &debug, BIT_POSf, _soc_mem_fifo_dma[chan].overflow_bit); 29588 soc_pci_write(unit, addr, debug); 29589 29590 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].hostmem_addr, 29591 REG_PORT_ANY, 0); 29592 soc_pci_getreg(unit, addr, &rval); 29593 host_buf = soc_cm_p2l(unit, rval); 29594 29595 addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].read_ptr, REG_PORT_ANY, 29596 0); 29597 soc_pci_getreg(unit, addr, &rval); 29598 read_ptr = soc_cm_p2l(unit, rval); 29599 29600 read_ptr += count * data_beats; 29601 if (read_ptr >= &host_buf[host_entries * data_beats]) { 29602 read_ptr -= host_entries * data_beats; 29603 } 29604 rval = soc_cm_l2p(unit, read_ptr); 29605 soc_pci_write(unit, addr, rval); 29606 29607 return SOC_E_NONE; 29608 } 29609 29610 #endif /* BCM_TRX_SUPPORT */ 29611 29612 /* 29613 * Function: 29614 * soc_mem_pop 29615 * Purpose: 29616 * Pop an entry from a FIFO. 29617 * Parameters: 29618 * mem Memory to search 29619 * copyno Which copy to search (if multiple copies) 29620 * entry_data OUT: Data if found 29621 * CAN NO LONGER BE NULL. Must be big enough 29622 * to handle the appropriate data. 29623 * Returns: 29624 * SOC_E_NOT_FOUND Entry not found: Fifo is empty 29625 * SOC_E_NONE Entry is found 29626 * SOC_E_XXX If internal error occurs 29627 */ 29628 29629 int 29630 soc_mem_pop(int unit, 29631 soc_mem_t mem, 29632 int copyno, 29633 void *entry_data) 29634 { 29635 #ifdef BCM_TRX_SUPPORT 29636 if (soc_feature(unit, soc_feature_mem_push_pop)) { 29637 switch (mem) { 29638 case ING_IPFIX_EXPORT_FIFOm: 29639 case EGR_IPFIX_EXPORT_FIFOm: 29640 case EXT_L2_MOD_FIFOm: 29641 case L2_MOD_FIFOm: 29642 #ifdef BCM_TRIUMPH3_SUPPORT 29643 case ING_SER_FIFOm: 29644 case ING_SER_FIFO_Xm: 29645 case ING_SER_FIFO_Ym: 29646 case EGR_SER_FIFOm: 29647 case EGR_SER_FIFO_Xm: 29648 case EGR_SER_FIFO_Ym: 29649 case ISM_SER_FIFOm: 29650 #endif /* BCM_TRIUMPH3_SUPPORT */ 29651 #ifdef BCM_TOMAHAWK_SUPPORT 29652 case ING_SER_FIFO_PIPE0m: 29653 case ING_SER_FIFO_PIPE1m: 29654 case ING_SER_FIFO_PIPE2m: 29655 case ING_SER_FIFO_PIPE3m: 29656 case EGR_SER_FIFO_PIPE0m: 29657 case EGR_SER_FIFO_PIPE1m: 29658 case EGR_SER_FIFO_PIPE2m: 29659 case EGR_SER_FIFO_PIPE3m: 29660 case L2_MGMT_SER_FIFOm: 29661 case MMU_GCFG_MEM_FAIL_ADDR_64m: 29662 case MMU_XCFG_MEM_FAIL_ADDR_64m: 29663 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE0m: 29664 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE1m: 29665 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE2m: 29666 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE3m: 29667 case MMU_SCFG_MEM_FAIL_ADDR_64m: 29668 case MMU_SCFG_MEM_FAIL_ADDR_64_SC0m: 29669 case MMU_SCFG_MEM_FAIL_ADDR_64_SC1m: 29670 case CENTRAL_CTR_EVICTION_FIFOm: 29671 #endif /* BCM_TOMAHAWK_SUPPORT */ 29672 #ifdef BCM_TOMAHAWK2_SUPPORT 29673 case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC0m: 29674 case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC1m: 29675 #endif /* BCM_TOMAHAWK2_SUPPORT */ 29676 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) 29677 case MMU_SEDCFG_MEM_FAIL_ADDR_64m: 29678 #endif 29679 #ifdef BCM_TOMAHAWK3_SUPPORT 29680 case ING_SER_FIFO_PIPE4m: 29681 case ING_SER_FIFO_PIPE5m: 29682 case ING_SER_FIFO_PIPE6m: 29683 case ING_SER_FIFO_PIPE7m: 29684 case EGR_SER_FIFO_PIPE4m: 29685 case EGR_SER_FIFO_PIPE5m: 29686 case EGR_SER_FIFO_PIPE6m: 29687 case EGR_SER_FIFO_PIPE7m: 29688 case EDB_SER_FIFOm: 29689 case EDB_SER_FIFO_PIPE0m: 29690 case EDB_SER_FIFO_PIPE1m: 29691 case EDB_SER_FIFO_PIPE2m: 29692 case EDB_SER_FIFO_PIPE3m: 29693 case EDB_SER_FIFO_PIPE4m: 29694 case EDB_SER_FIFO_PIPE5m: 29695 case EDB_SER_FIFO_PIPE6m: 29696 case EDB_SER_FIFO_PIPE7m: 29697 case EGR_SER_FIFO_2m: 29698 case EGR_SER_FIFO_2_PIPE0m: 29699 case EGR_SER_FIFO_2_PIPE1m: 29700 case EGR_SER_FIFO_2_PIPE2m: 29701 case EGR_SER_FIFO_2_PIPE3m: 29702 case EGR_SER_FIFO_2_PIPE4m: 29703 case EGR_SER_FIFO_2_PIPE5m: 29704 case EGR_SER_FIFO_2_PIPE6m: 29705 case EGR_SER_FIFO_2_PIPE7m: 29706 case MMU_GLBCFG_MEM_FAIL_ADDR_64m: 29707 case MMU_ITMCFG_MEM_FAIL_ADDR_64m: 29708 case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM0m: 29709 case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM1m: 29710 case MMU_EBCFG_MEM_FAIL_ADDR_64m: 29711 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE0m: 29712 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE1m: 29713 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE2m: 29714 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE3m: 29715 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE4m: 29716 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE5m: 29717 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE6m: 29718 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE7m: 29719 case DLB_ECMP_SER_FIFOm: 29720 #endif 29721 return _soc_mem_pop(unit, mem, copyno, entry_data); 29722 default: 29723 return SOC_E_BADID; 29724 break; 29725 } 29726 } 29727 #endif /* BCM_TRX_SUPPORT */ 29728 29729 return SOC_E_UNAVAIL; 29730 } 29731 29732 /* 29733 * Function: 29734 * soc_mem_push 29735 * Purpose: 29736 * Push an entry to a FIFO. 29737 * Parameters: 29738 * mem Memory to search 29739 * copyno Which copy to search (if multiple copies) 29740 * entry_data In: Data to be pushed 29741 * 29742 * Returns: 29743 * SOC_E_FULL Fifo is full 29744 * SOC_E_NONE Entry is pushed successfully 29745 * SOC_E_XXX If internal error occurs 29746 */ 29747 29748 int 29749 soc_mem_push(int unit, 29750 soc_mem_t mem, 29751 int copyno, 29752 void *entry_data) 29753 { 29754 #ifdef BCM_TRX_SUPPORT 29755 if (soc_feature(unit, soc_feature_mem_push_pop)) { 29756 switch (mem) { 29757 case ING_IPFIX_EXPORT_FIFOm: 29758 case EGR_IPFIX_EXPORT_FIFOm: 29759 case EXT_L2_MOD_FIFOm: 29760 case L2_MOD_FIFOm: 29761 return _soc_mem_push(unit, mem, copyno, entry_data); 29762 default: 29763 return SOC_E_BADID; 29764 break; 29765 } 29766 } 29767 #endif /* BCM_TRX_SUPPORT */ 29768 29769 return SOC_E_UNAVAIL; 29770 } 29771 29772 int 29773 soc_mem_fifo_dma_start(int unit, int chan, soc_mem_t mem, int copyno, 29774 int host_entries, void *host_buf) 29775 { 29776 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT) 29777 if (SOC_IS_KATANA(unit) && soc_feature(unit, soc_feature_cmicm)) { 29778 return _soc_mem_kt_fifo_dma_start(unit, chan, mem, copyno, 29779 host_entries, host_buf); 29780 } 29781 #endif 29782 #ifdef BCM_CMICX_SUPPORT 29783 if (soc_feature(unit, soc_feature_cmicx) && 29784 soc_feature(unit, soc_feature_fifo_dma)) { 29785 return soc_fifodma_start(unit, chan, TRUE, mem, 0, copyno, 0, 29786 host_entries, host_buf); 29787 } 29788 #endif /* BCM_CMICX_SUPPORT */ 29789 #ifdef BCM_CMICM_SUPPORT 29790 if (soc_feature(unit, soc_feature_cmicm)) { 29791 return _soc_mem_sbus_fifo_dma_start(unit, chan, mem, copyno, 29792 host_entries, host_buf); 29793 } 29794 #endif /* BCM_CMICM_SUPPORT */ 29795 #if defined(BCM_TRX_SUPPORT) 29796 if (soc_feature(unit, soc_feature_fifo_dma)) { 29797 return _soc_mem_fifo_dma_start(unit, chan, mem, copyno, 29798 host_entries, host_buf); 29799 } 29800 #endif /* BCM_TRX_SUPPORT */ 29801 29802 return SOC_E_UNAVAIL; 29803 } 29804 29805 int 29806 soc_mem_fifo_dma_stop(int unit, int chan) 29807 { 29808 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT) 29809 if (SOC_IS_KATANA(unit) && soc_feature(unit, soc_feature_cmicm)) { 29810 return _soc_mem_kt_fifo_dma_stop(unit, chan); 29811 } 29812 #endif 29813 #ifdef BCM_CMICX_SUPPORT 29814 if (soc_feature(unit, soc_feature_cmicx) && 29815 soc_feature(unit, soc_feature_fifo_dma)) { 29816 return soc_fifodma_stop(unit, chan); 29817 } 29818 #endif /* BCM_CMICX_SUPPORT */ 29819 #ifdef BCM_CMICM_SUPPORT 29820 if (soc_feature(unit, soc_feature_cmicm)) { 29821 return _soc_mem_sbus_fifo_dma_stop(unit, chan); 29822 } 29823 #endif /* BCM_CMICM_SUPPORT */ 29824 #if defined(BCM_TRX_SUPPORT) 29825 if (soc_feature(unit, soc_feature_fifo_dma)) { 29826 return _soc_mem_fifo_dma_stop(unit, chan); 29827 } 29828 #endif /* BCM_TRX_SUPPORT */ 29829 29830 return SOC_E_UNAVAIL; 29831 } 29832 29833 int 29834 soc_mem_fifo_dma_get_read_ptr(int unit, int chan, void **host_ptr, int *count) 29835 { 29836 29837 #if defined(BCM_HURRICANE2_SUPPORT) && defined(BCM_CMICM_SUPPORT) 29838 if (soc_feature(unit, soc_feature_cmicm) && 29839 soc_feature(unit, soc_feature_fifo_dma_hu2)) { 29840 return _soc_mem_hu2_fifo_dma_get_read_ptr(unit, chan, host_ptr, count); 29841 } 29842 #endif 29843 #ifdef BCM_CMICX_SUPPORT 29844 if (soc_feature(unit, soc_feature_cmicx) && 29845 soc_feature(unit, soc_feature_fifo_dma)) { 29846 return soc_fifodma_get_read_ptr(unit, chan, host_ptr, count); 29847 } 29848 #endif /* BCM_CMICX_SUPPORT */ 29849 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT) 29850 if (soc_feature(unit, soc_feature_cmicm)) { 29851 return _soc_mem_kt_fifo_dma_get_read_ptr(unit, chan, host_ptr, count); 29852 } 29853 #endif 29854 #if defined(BCM_TRX_SUPPORT) 29855 if (soc_feature(unit, soc_feature_fifo_dma)) { 29856 return _soc_mem_fifo_dma_get_read_ptr(unit, chan, host_ptr, count); 29857 } 29858 #endif /* BCM_TRX_SUPPORT */ 29859 29860 return SOC_E_UNAVAIL; 29861 } 29862 29863 int 29864 soc_mem_fifo_dma_advance_read_ptr(int unit, int chan, int count) 29865 { 29866 29867 #if defined(BCM_HURRICANE2_SUPPORT) && defined(BCM_CMICM_SUPPORT) 29868 if (soc_feature(unit, soc_feature_cmicm) && SOC_IS_HURRICANE2(unit)) { 29869 return _soc_mem_hu2_fifo_dma_advance_read_ptr(unit, chan, count); 29870 } 29871 #endif 29872 #ifdef BCM_CMICX_SUPPORT 29873 if (soc_feature(unit, soc_feature_cmicx) && 29874 soc_feature(unit, soc_feature_fifo_dma)) { 29875 return soc_fifodma_advance_read_ptr(unit, chan, count); 29876 } 29877 #endif /* BCM_CMICX_SUPPORT */ 29878 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT) 29879 if (soc_feature(unit, soc_feature_cmicm)) { 29880 return _soc_mem_kt_fifo_dma_advance_read_ptr(unit, chan, count); 29881 } 29882 #endif 29883 #if defined(BCM_TRX_SUPPORT) 29884 if (soc_feature(unit, soc_feature_fifo_dma)) { 29885 return _soc_mem_fifo_dma_advance_read_ptr(unit, chan, count); 29886 } 29887 #endif /* BCM_TRX_SUPPORT */ 29888 return SOC_E_UNAVAIL; 29889 } 29890 29891 int 29892 soc_mem_fifo_dma_get_num_entries(int unit, int chan, int *count) 29893 { 29894 #ifdef BCM_CMICM_SUPPORT 29895 if (soc_feature(unit, soc_feature_cmicm)) { 29896 return _soc_mem_sbus_fifo_dma_get_num_entries(unit, chan, count); 29897 } 29898 #endif /* BCM_CMICM_SUPPORT */ 29899 return SOC_E_UNAVAIL; 29900 } 29901 29902 int 29903 soc_mem_fifo_dma_set_entries_read(int unit, int chan, uint32 num) 29904 { 29905 #ifdef BCM_CMICM_SUPPORT 29906 if (soc_feature(unit, soc_feature_cmicm)) { 29907 return _soc_mem_sbus_fifo_dma_set_entries_read(unit, chan, num); 29908 } 29909 #endif /* BCM_CMICM_SUPPORT */ 29910 return SOC_E_UNAVAIL; 29911 } 29912 29913 #ifdef BCM_XGS_SWITCH_SUPPORT 29914 29915 /* 29916 * Function: 29917 * soc_vlan_entries 29918 * Purpose: 29919 * Return the number of entries in VLAN_TAB with the VALID bit set. 29920 */ 29921 29922 STATIC int 29923 soc_vlan_entries(int unit) 29924 { 29925 int index_min, index_max, index; 29926 vlan_tab_entry_t ve; 29927 int total; 29928 29929 index_min = soc_mem_index_min(unit, VLAN_TABm); 29930 index_max = soc_mem_index_max(unit, VLAN_TABm); 29931 29932 total = 0; 29933 29934 for (index = index_min; index <= index_max; index++) { 29935 SOC_IF_ERROR_RETURN 29936 (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, index, &ve)); 29937 29938 total += soc_VLAN_TABm_field32_get(unit, &ve, VALIDf); 29939 } 29940 29941 return total; 29942 } 29943 29944 #endif /* BCM_XGS_SWITCH_SUPPORT */ 29945 29946 /* 29947 * Function: 29948 * soc_mem_entries 29949 * Purpose: 29950 * Return the number of entries in a sorted table. 29951 * Notes: 29952 * Performs special functions for some tables. 29953 */ 29954 29955 int 29956 soc_mem_entries(int unit, 29957 soc_mem_t mem, 29958 int copyno) 29959 { 29960 int entries = 0; 29961 assert(SOC_MEM_IS_VALID(unit, mem)); 29962 assert(soc_attached(unit)); 29963 assert(soc_mem_is_sorted(unit, mem) || 29964 soc_mem_is_hashed(unit, mem) || 29965 soc_mem_is_cam(unit, mem) || 29966 soc_mem_is_cmd(unit, mem) || 29967 mem == VLAN_TABm); 29968 if (copyno == MEM_BLOCK_ANY) { 29969 /* Overrun of "mem_block_any" is not possible as it is of MAX "mem" value NUM_SOC_MEM */ 29970 /* coverity[overrun-local : FALSE] */ 29971 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 29972 } 29973 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 29974 LOG_WARN(BSL_LS_SOC_SOCMEM, 29975 (BSL_META_U(unit, 29976 "soc_mem_entries: invalid block %d for memory %s\n"), 29977 copyno, SOC_MEM_NAME(unit, mem))); 29978 return SOC_E_PARAM; 29979 } 29980 29981 switch (mem) { 29982 #ifdef BCM_XGS_SWITCH_SUPPORT 29983 case VLAN_TABm: 29984 entries = soc_vlan_entries(unit); /* Warning: very slow */ 29985 break; 29986 #endif 29987 29988 default: 29989 _SOC_MEM_REUSE_MEM_STATE(unit, mem); 29990 entries = SOP_MEM_STATE(unit, mem).count[copyno]; 29991 break; 29992 } 29993 29994 return entries; 29995 } 29996 29997 /* 29998 * Function: 29999 * soc_mem_debug_set 30000 * Purpose: 30001 * Enable or disable MMU debug mode. 30002 * Returns: 30003 * Previous enable state, or SOC_E_XXX on error. 30004 */ 30005 30006 int 30007 soc_mem_debug_set(int unit, int enable) 30008 { 30009 schan_msg_t schan_msg; 30010 int msg, rv = SOC_E_NONE, old_enable, allow_intr=0; 30011 int dst_blk, src_blk; 30012 30013 old_enable = SOC_PERSIST(unit)->debugMode; 30014 30015 if (enable && !old_enable) { 30016 msg = ENTER_DEBUG_MODE_MSG; 30017 } else if (!enable && old_enable) { 30018 msg = EXIT_DEBUG_MODE_MSG; 30019 } else { 30020 msg = -1; 30021 } 30022 30023 if (msg >= 0) { 30024 schan_msg_clear(&schan_msg); 30025 30026 dst_blk = SOC_BLOCK2SCH(unit, MMU_BLOCK(unit)); 30027 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 30028 30029 soc_schan_header_cmd_set(unit, &schan_msg.header, msg, dst_blk, 30030 src_blk, 0, 0, 0, 0); 30031 30032 if (SOC_IS_SAND(unit)) { 30033 allow_intr = 1; 30034 } 30035 30036 if ((rv = soc_schan_op(unit, &schan_msg, 1, 0, allow_intr)) >= 0) { 30037 SOC_PERSIST(unit)->debugMode = enable; 30038 } 30039 30040 if (!enable) { 30041 /* Allow packet transfers in progress to drain */ 30042 sal_usleep(100000); 30043 } 30044 } 30045 30046 return (rv < 0) ? rv : old_enable; 30047 } 30048 30049 /* 30050 * Function: 30051 * soc_mem_debug_get 30052 * Purpose: 30053 * Return current MMU debug mode status 30054 */ 30055 30056 int 30057 soc_mem_debug_get(int unit, int *enable) 30058 { 30059 *enable = SOC_PERSIST(unit)->debugMode; 30060 return SOC_E_NONE; 30061 } 30062 30063 /* 30064 * Function: 30065 * soc_mem_iterate 30066 * Purpose: 30067 * Iterate over all the valid memories and call user 30068 * passed callback function (do_it) for each valid memory. 30069 */ 30070 int 30071 soc_mem_iterate(int unit, soc_mem_iter_f do_it, void *data) 30072 { 30073 soc_mem_t mem, mem_iter; 30074 int rv = SOC_E_NONE; 30075 30076 if (!do_it) { 30077 LOG_ERROR(BSL_LS_SOC_SOCMEM, 30078 (BSL_META_U(unit, 30079 "soc_mem_iterate: Callback function is NULL"))); 30080 return SOC_E_PARAM; 30081 } 30082 30083 for (mem_iter = 0; mem_iter < NUM_SOC_MEM; mem_iter++) { 30084 mem = mem_iter; 30085 _SOC_MEM_REPLACE_MEM(unit, mem); 30086 if (!SOC_MEM_IS_VALID(unit, mem)) { 30087 continue; 30088 } 30089 30090 #if defined(BCM_HAWKEYE_SUPPORT) 30091 if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) { 30092 continue; 30093 } 30094 #endif /* BCM_HAWKEYE_SUPPORT */ 30095 30096 /* 30097 * Call user provided callback function. 30098 */ 30099 if ((rv = do_it(unit, mem, data)) < 0) { 30100 LOG_ERROR(BSL_LS_SOC_SOCMEM, 30101 (BSL_META_U(unit, 30102 "soc_mem_iterate: Failed on memory (%s)\n"), 30103 SOC_MEM_NAME(unit, mem))); 30104 /* break; */ 30105 } 30106 } 30107 return rv; 30108 } 30109 30110 #ifdef BCM_CMICM_SUPPORT 30111 /* 30112 * Function: soc_host_ccm_copy 30113 * Purpose: Copy a range of memory from one host location to another 30114 * Primarily for Cross-Coupled Memories. 30115 * Parameters: 30116 * unit - (IN) SOC unit number. 30117 * srcbuf - (IN) Source Buffer. 30118 * dstbuf - (IN) Destination Buffer. 30119 * count - (IN) Number of dwords to transfer. 30120 * flags - (IN) 30121 * 0x01 Source and destination endian to be changed. 30122 * 0x02 Source is PCI 30123 * Returns: 30124 * SOC_E_XXX 30125 */ 30126 int 30127 soc_host_ccm_copy(int unit, void *srcbuf, void *dstbuf, 30128 int count, int flags) 30129 { 30130 int rv; 30131 30132 rv = soc_host_ccm_copy_multi_cmc(unit, srcbuf, dstbuf, 30133 count, flags, SOC_PCI_CMC(unit)); 30134 return rv; 30135 } 30136 30137 /* 30138 * Function: soc_host_ccm_copy_multi_cmc 30139 * Purpose: Copy a range of memory from one host location to another 30140 * Primarily for Cross-Coupled Memories. 30141 * With multiple CMC/channel support 30142 * Parameters: 30143 * unit - (IN) SOC unit number. 30144 * srcbuf - (IN) Source Buffer. 30145 * dstbuf - (IN) Destination Buffer. 30146 * count - (IN) Number of dwords to transfer. 30147 * flags - (IN) 30148 * 0x01 Source and destination endian to be changed. 30149 * 0x02 Source is PCI 30150 * cmc - (IN) CMC to be used. 30151 * Returns: 30152 * SOC_E_XXX 30153 */ 30154 int 30155 soc_host_ccm_copy_multi_cmc(int unit, void *srcbuf, void *dstbuf, 30156 int count, int flags, int cmc) 30157 { 30158 int i, rv; 30159 soc_control_t *soc = SOC_CONTROL(unit); 30160 uint32 *srcptr = (uint32 *)srcbuf; 30161 uint32 *dstptr = (uint32 *)dstbuf; 30162 uint32 reg, reg2; 30163 assert (srcptr && dstptr); 30164 30165 if (SOC_CONTROL(unit)->ccmDmaMutex[cmc] == 0) { 30166 /* If DMA not enabled, or short length use PIO to copy */ 30167 for (i = 0; i < count; i ++ ) { 30168 if (flags & 2) { /* Read from PCI */ 30169 reg = soc_pci_mcs_read(unit, PTR_TO_INT(srcptr)); 30170 } else { 30171 reg = *srcptr; 30172 } 30173 30174 if (flags & 1) { 30175 reg = ((reg & 0xff000000) >> 24) | 30176 ((reg & 0x00ff0000) >> 8) | 30177 ((reg & 0x0000ff00) << 8) | 30178 ((reg & 0x000000ff) << 24); 30179 } 30180 30181 if (flags & 2) { 30182 *dstptr = reg; 30183 } else { 30184 soc_pci_mcs_write(unit, PTR_TO_INT(dstptr), reg); 30185 reg2 = soc_pci_mcs_read(unit, PTR_TO_INT(dstptr)); 30186 if (reg2 != reg) { 30187 LOG_ERROR(BSL_LS_SOC_SOCMEM, 30188 (BSL_META_U(unit, 30189 "ccm_dma: compare error %x (%x %x)\n"), 30190 PTR_TO_INT(dstptr), reg, reg2)); 30191 } 30192 } 30193 30194 dstptr++; 30195 srcptr++; 30196 } 30197 return SOC_E_NONE; 30198 } 30199 30200 CCM_DMA_LOCK(unit, cmc); 30201 30202 soc_pci_write(unit, CMIC_CMCx_CCM_DMA_HOST0_MEM_START_ADDR_OFFSET(cmc), soc_cm_l2p(unit, srcbuf)); 30203 soc_pci_write(unit, CMIC_CMCx_CCM_DMA_HOST1_MEM_START_ADDR_OFFSET(cmc), soc_cm_l2p(unit, dstbuf)); 30204 soc_pci_write(unit, CMIC_CMCx_CCM_DMA_ENTRY_COUNT_OFFSET(cmc), count); 30205 /* Keep endianess default... */ 30206 reg = soc_pci_read(unit, CMIC_CMCx_CCM_DMA_CFG_OFFSET(cmc)); 30207 soc_reg_field_set(unit, CMIC_CMC0_CCM_DMA_CFGr, ®, ABORTf, 0); 30208 soc_reg_field_set(unit, CMIC_CMC0_CCM_DMA_CFGr, ®, ENf, 0); 30209 soc_pci_write(unit, CMIC_CMCx_CCM_DMA_CFG_OFFSET(cmc), reg); /* Clearing EN clears stats */ 30210 /* Start DMA */ 30211 soc_reg_field_set(unit, CMIC_CMC0_CCM_DMA_CFGr, ®, ENf, 1); 30212 soc_pci_write(unit, CMIC_CMCx_CCM_DMA_CFG_OFFSET(cmc), reg); 30213 30214 rv = SOC_E_TIMEOUT; 30215 if (soc->ccmDmaIntrEnb) { 30216 (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_CCMDMA_DONE); 30217 if (sal_sem_take(soc->ccmDmaIntr[cmc], soc->ccmDmaTimeout) < 0) { 30218 rv = SOC_E_TIMEOUT; 30219 } 30220 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_CCMDMA_DONE); 30221 30222 reg = soc_pci_read(unit, CMIC_CMCx_CCM_DMA_STAT_OFFSET(cmc)); 30223 if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr, 30224 reg, DONEf)) { 30225 rv = SOC_E_NONE; 30226 if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr, 30227 reg, ERRORf)) { 30228 rv = SOC_E_FAIL; 30229 } 30230 } 30231 } else { 30232 soc_timeout_t to; 30233 LOG_WARN(BSL_LS_SOC_SOCMEM, 30234 (BSL_META_U(unit, 30235 "using Polling mode for CCM DMA\n"))); 30236 soc_timeout_init(&to, soc->ccmDmaTimeout, 10000); 30237 do { 30238 reg = soc_pci_read(unit, CMIC_CMCx_CCM_DMA_STAT_OFFSET(cmc)); 30239 if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr, 30240 reg, DONEf)) { 30241 rv = SOC_E_NONE; 30242 if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr, 30243 reg, ERRORf)) { 30244 rv = SOC_E_FAIL; 30245 } 30246 break; 30247 } 30248 } while(!(soc_timeout_check(&to))); 30249 } 30250 30251 if (rv == SOC_E_TIMEOUT) { 30252 LOG_ERROR(BSL_LS_SOC_SOCMEM, 30253 (BSL_META_U(unit, 30254 "CcmDmaTimeout: unit %d, ccm_dma timeout\n"), unit)); 30255 30256 /* Abort CCM DMA */ 30257 30258 /* Dummy read to allow abort to finish */ 30259 30260 /* Disable CCM DMA */ 30261 30262 /* Clear ccm DMA abort bit */ 30263 } 30264 30265 CCM_DMA_UNLOCK(unit, cmc); 30266 return rv; 30267 } 30268 #endif 30269 30270 /* 30271 * @name - _soc_l3_defip_urpf_index_remap 30272 * @param - unit: unit number 30273 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30274 * @param - index: Physical index 30275 * 30276 * @purpose - Remap physical index to logical index 30277 */ 30278 STATIC int 30279 _soc_l3_defip_urpf_index_remap(int unit, int wide, int index) 30280 { 30281 int new_index = index; 30282 int num_tcams = 0; 30283 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30284 int entries_left_in_paired_tcam = 0; 30285 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2; 30286 int half_defip_size; 30287 int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit); 30288 int half_defip_index = (max_tcams * tcam_size) /2; 30289 30290 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 30291 half_defip_size = soc_mem_index_count(unit, L3_DEFIP_LEVEL1m) / 2; 30292 } else { 30293 half_defip_size = soc_mem_index_count(unit, L3_DEFIPm) / 2; 30294 } 30295 30296 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30297 return index; 30298 } 30299 30300 assert(tcam_size); 30301 30302 if (wide == 0) { 30303 num_tcams = soc_defip_index_remap / tcam_size; 30304 entries_left_in_paired_tcam = tcam_size - 30305 (soc_defip_index_remap % tcam_size); 30306 new_index = index - (num_tcams * 2 * tcam_size); 30307 30308 if (new_index >= half_defip_index) { 30309 new_index = new_index - half_defip_index; 30310 } 30311 30312 if (new_index - (soc_defip_index_remap % tcam_size) < 30313 entries_left_in_paired_tcam) { 30314 new_index = new_index - (soc_defip_index_remap % tcam_size); 30315 } else { 30316 new_index = new_index - ((soc_defip_index_remap % tcam_size) * 2); 30317 } 30318 30319 if (index >= half_defip_index) { 30320 new_index = new_index + half_defip_size; 30321 } 30322 return new_index; 30323 } 30324 30325 new_index = index; 30326 if (index >= (half_defip_index / 2)) { 30327 new_index = index - (half_defip_index / 2) + soc_defip_index_remap; 30328 } 30329 return new_index; 30330 } 30331 30332 /* 30333 * @name - soc_l3_defip_urpf_index_remap 30334 * @param - unit: unit number 30335 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30336 * @param - index: Physical index 30337 * 30338 * @purpose - Remap physical index to logical index 30339 */ 30340 int 30341 soc_l3_defip_urpf_index_remap(int unit, int wide, int index) 30342 { 30343 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30344 return index; 30345 } 30346 30347 assert(SOC_L3_DEFIP_INDEX_INIT(unit)); 30348 if (wide == 0) { 30349 return SOC_L3_DEFIP_URPF_PHY_TO_LOG_INDEX(unit, index); 30350 } 30351 return SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_INDEX(unit, index); 30352 } 30353 30354 /* 30355 * @name - _soc_l3_defip_index_remap 30356 * @param - unit: unit number 30357 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30358 * @param - index: Physical index 30359 * 30360 * @purpose - Remap physical index to logical index 30361 */ 30362 30363 STATIC int 30364 _soc_l3_defip_index_remap(int unit, int wide, int index) 30365 { 30366 int new_index = index; 30367 int num_tcams = 0; 30368 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30369 int entries_left_in_paired_tcam = 0; 30370 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit); 30371 30372 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30373 return index; 30374 } 30375 30376 assert(tcam_size); 30377 30378 if (wide == 0) { 30379 if (soc_feature(unit, soc_feature_l3_1k_defip_table)) { 30380 num_tcams = soc_defip_index_remap > 0 ? 1 : 0; 30381 new_index = index - num_tcams * 2 * tcam_size; 30382 } else { 30383 num_tcams = soc_defip_index_remap / tcam_size; 30384 entries_left_in_paired_tcam = tcam_size - 30385 (soc_defip_index_remap % tcam_size); 30386 if (index - (num_tcams * 2 * tcam_size) - 30387 (soc_defip_index_remap % tcam_size) < entries_left_in_paired_tcam) { 30388 new_index = index - (num_tcams * 2 * tcam_size) - 30389 (soc_defip_index_remap % tcam_size); 30390 } else { 30391 new_index = index - (num_tcams * 2 * tcam_size) - 30392 ((soc_defip_index_remap % tcam_size) * 2); 30393 } 30394 } 30395 return new_index; 30396 } 30397 return new_index; 30398 } 30399 30400 /* 30401 * @name - _soc_th3_l3_defip_index_remap 30402 * @param - unit: unit number 30403 * @param - wide: 0 - L3_DEFIP_LEVEL1, 1 - L3_DEFIP_PAIR_LEVEL1 30404 * @param - index: Physical index 30405 * 30406 * @purpose - Remap physical index to logical index 30407 * - (Only for TH3 ALPM2 Parallel/Mix IPv6-128b modes) 30408 * -------------- 0 30409 * L3_DEFIP_PAIR_LEVEL1 | DB0 (v6) | BLOCK_0 (TCAM0/1) 30410 * |------------| Private 30411 * L3_DEFIP_LEVEL1 | DB0 (v4) | BLOCK_1 (TCAM2/3) 30412 * |------------| 30413 * L3_DEFIP_PAIR_LEVEL1 | DB1 (v6) | BLOCK_2 (TCAM4/5) 30414 * |------------| Public 30415 * L3_DEFIP_LEVEL1 | DB1 (v4) | BLOCK_3 (TCAM6/7) 30416 * -------------- 1023 30417 */ 30418 30419 STATIC int 30420 _soc_th3_l3_defip_index_remap(int unit, int wide, int index) 30421 { 30422 int new_index; 30423 int num_tcams; 30424 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30425 int entries_left_in_paired_tcam; 30426 int entries_left_in_tcam; 30427 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit); 30428 /* DB0: Private, DB1: Public */ 30429 int per_db_pair_entries = soc_defip_index_remap / 2; 30430 30431 num_tcams = per_db_pair_entries / tcam_size; 30432 entries_left_in_paired_tcam = tcam_size - (per_db_pair_entries % tcam_size); 30433 entries_left_in_tcam = 2 * tcam_size - per_db_pair_entries; 30434 30435 if (wide == 0) { 30436 if (index - (num_tcams * 2 * tcam_size) - 30437 (per_db_pair_entries % tcam_size) < entries_left_in_paired_tcam) { 30438 new_index = index - (num_tcams * 2 * tcam_size) - 30439 (per_db_pair_entries % tcam_size); 30440 } else if (index - (num_tcams * 2 * tcam_size) - 30441 2 * (per_db_pair_entries % tcam_size) < 2 * entries_left_in_tcam) { 30442 new_index = index - (num_tcams * 2 * tcam_size) - 30443 2 * (per_db_pair_entries % tcam_size); 30444 } else if (index - 2 * (num_tcams * 2 * tcam_size) - 30445 3 * (per_db_pair_entries % tcam_size) < 30446 2 * entries_left_in_tcam + entries_left_in_paired_tcam) { 30447 new_index = index - 2 * (num_tcams * 2 * tcam_size) - 30448 3 * (per_db_pair_entries % tcam_size); 30449 } else { 30450 new_index = index - 2 * (num_tcams * 2 * tcam_size) - 30451 4 * (per_db_pair_entries % tcam_size); 30452 } 30453 } else { /* wide = 1 */ 30454 if (index < per_db_pair_entries) { 30455 new_index = index; 30456 } else { 30457 new_index = index - entries_left_in_tcam; 30458 } 30459 } 30460 30461 return new_index; 30462 } 30463 /* 30464 * @name - soc_l3_defip_index_remap 30465 * @param - unit: unit number 30466 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30467 * @param - index: Physical index 30468 * 30469 * @purpose - Remap physical index to logical index 30470 */ 30471 int 30472 soc_l3_defip_index_remap(int unit, int wide, int index) 30473 { 30474 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30475 return index; 30476 } 30477 30478 assert(SOC_L3_DEFIP_INDEX_INIT(unit)); 30479 if (wide == 0) { 30480 return SOC_L3_DEFIP_PHY_TO_LOG_INDEX(unit, index); 30481 } 30482 return SOC_L3_DEFIP_PAIR_PHY_TO_LOG_INDEX(unit, index); 30483 } 30484 30485 /* 30486 * @name - _soc_l3_reduced_defip_urpf_index_map 30487 * @param - unit: unit number 30488 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30489 * @param - index: logical index 30490 * 30491 * @purpose - Map logical to physical index 30492 */ 30493 30494 STATIC int 30495 _soc_l3_reduced_defip_urpf_index_map(int unit, int wide, int index) 30496 { 30497 int new_index = index; 30498 int num_tcams = 0; 30499 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30500 int entries_left_in_paired_tcam = 0; 30501 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2; 30502 int half_table_size = (SOC_CONTROL(unit)->l3_defip_max_tcams * 30503 tcam_size) / 2; 30504 int half_defip_size; 30505 30506 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 30507 half_defip_size = soc_mem_index_count(unit, L3_DEFIP_LEVEL1m) / 2; 30508 } else { 30509 half_defip_size = soc_mem_index_count(unit, L3_DEFIPm) / 2; 30510 } 30511 30512 if (wide == 0) { 30513 num_tcams = soc_defip_index_remap / tcam_size; 30514 entries_left_in_paired_tcam = tcam_size - 30515 (soc_defip_index_remap % tcam_size); 30516 if (index < entries_left_in_paired_tcam) { 30517 new_index = index + (num_tcams * 2 * tcam_size) + 30518 (soc_defip_index_remap % tcam_size); 30519 } else { 30520 if (index < half_defip_size) { 30521 /* Apollo 2 has 6 tcams so the v6 rpf tcams will be last two. 30522 * Therefore we will setup the defip indexes contiguous 30523 */ 30524 new_index = index + (num_tcams * 2 * tcam_size) + 30525 ((soc_defip_index_remap % tcam_size) * 2); 30526 } else { 30527 if ((index - half_defip_size) < tcam_size) { 30528 new_index = half_table_size + (index - half_defip_size); 30529 } else if ((index - half_defip_size - tcam_size) < entries_left_in_paired_tcam) { 30530 new_index = half_table_size + (index - half_defip_size) + 30531 (soc_defip_index_remap % tcam_size); 30532 } else { 30533 new_index = half_table_size + (index - half_defip_size) + 30534 ((soc_defip_index_remap % tcam_size) * 2); 30535 } 30536 } 30537 } 30538 return new_index; 30539 } 30540 30541 new_index = index; 30542 if (index >= soc_defip_index_remap) { 30543 new_index = index + LPM_INDEX_2K_ENTRIES - soc_defip_index_remap; 30544 } 30545 return new_index; 30546 } 30547 30548 /* 30549 * @name - _soc_l3_defip_urpf_index_map 30550 * @param - unit: unit number 30551 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30552 * @param - index: Logical index 30553 * 30554 * @purpose - Map logical index to physical index 30555 */ 30556 STATIC int 30557 _soc_l3_defip_urpf_index_map(int unit, int wide, int index) 30558 { 30559 int new_index = index; 30560 int num_tcams = 0; 30561 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30562 int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit); 30563 int entries_left_in_paired_tcam = 0; 30564 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2; 30565 int half_defip_size; 30566 int half_defip_index = (max_tcams * tcam_size) / 2; 30567 30568 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 30569 half_defip_size = soc_mem_index_count(unit, L3_DEFIP_LEVEL1m) / 2; 30570 } else { 30571 half_defip_size = soc_mem_index_count(unit, L3_DEFIPm) / 2; 30572 } 30573 30574 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30575 return index; 30576 } 30577 30578 assert(tcam_size); 30579 30580 if (wide == 0) { 30581 num_tcams = soc_defip_index_remap / tcam_size; 30582 entries_left_in_paired_tcam = tcam_size - 30583 (soc_defip_index_remap % tcam_size); 30584 if (index < entries_left_in_paired_tcam) { 30585 new_index = index + (num_tcams * 2 * tcam_size) + 30586 (soc_defip_index_remap % tcam_size); 30587 } else if (index >= (half_defip_size)) { 30588 if ((index - half_defip_size) < entries_left_in_paired_tcam) { 30589 new_index = (index - half_defip_size) + 30590 (num_tcams * 2 * tcam_size) + 30591 (soc_defip_index_remap % tcam_size) + 30592 half_defip_index; 30593 } else { 30594 new_index = (index - half_defip_size) + 30595 (num_tcams * 2 * tcam_size) + 30596 ((soc_defip_index_remap % tcam_size) * 2) + 30597 half_defip_index; 30598 } 30599 } else { 30600 new_index = index + (num_tcams * 2 * tcam_size) + 30601 ((soc_defip_index_remap % tcam_size) * 2); 30602 } 30603 return new_index; 30604 } 30605 30606 new_index = index; 30607 if (index >= soc_defip_index_remap) { 30608 new_index = index + (half_defip_index / 2) - soc_defip_index_remap; 30609 } 30610 return new_index; 30611 } 30612 30613 /* 30614 * @name - _soc_l3_reduced_defip_urpf_index_remap 30615 * @param - unit: unit number 30616 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30617 * @param - index: Physical index 30618 * 30619 * @purpose - Remap physical index to logical index 30620 */ 30621 STATIC int 30622 _soc_l3_reduced_defip_urpf_index_remap(int unit, int wide, int index) 30623 { 30624 int new_index = index; 30625 int num_tcams = 0; 30626 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30627 int entries_left_in_paired_tcam = 0; 30628 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2; 30629 30630 if (wide == 0) { 30631 num_tcams = soc_defip_index_remap / tcam_size; 30632 entries_left_in_paired_tcam = tcam_size - 30633 (soc_defip_index_remap % tcam_size); 30634 new_index = index - (num_tcams * 2 * tcam_size); 30635 30636 if (new_index < LPM_INDEX_4K_ENTRIES) { 30637 30638 if (new_index - (soc_defip_index_remap % tcam_size) < 30639 entries_left_in_paired_tcam) { 30640 new_index = new_index - (soc_defip_index_remap % tcam_size); 30641 } else { 30642 new_index = new_index - ((soc_defip_index_remap % tcam_size) * 2); 30643 } 30644 } else { 30645 new_index = index - LPM_INDEX_4K_ENTRIES; 30646 if (new_index - (soc_defip_index_remap % tcam_size) < 30647 entries_left_in_paired_tcam) { 30648 new_index = new_index - ((soc_defip_index_remap % tcam_size) * 3) ; 30649 } else { 30650 new_index = new_index - ((soc_defip_index_remap % tcam_size) * 4); 30651 } 30652 new_index += LPM_INDEX_4K_ENTRIES; 30653 } 30654 return new_index; 30655 } 30656 30657 new_index = index; 30658 if (index >= LPM_INDEX_2K_ENTRIES) { 30659 new_index = index - LPM_INDEX_2K_ENTRIES + soc_defip_index_remap; 30660 } 30661 return new_index; 30662 } 30663 30664 /* 30665 * @name - soc_l3_defip_urpf_index_map 30666 * @param - unit: unit number 30667 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30668 * @param - index: Logical index 30669 * 30670 * @purpose - Map logical index to physical index 30671 */ 30672 30673 int 30674 soc_l3_defip_urpf_index_map(int unit, int wide, int index) 30675 { 30676 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30677 return index; 30678 } 30679 30680 assert(SOC_L3_DEFIP_INDEX_INIT(unit)); 30681 30682 if (wide == 0) { 30683 return SOC_L3_DEFIP_URPF_LOG_TO_PHY_INDEX(unit, index); 30684 } 30685 return SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_INDEX(unit, index); 30686 } 30687 30688 /* 30689 * @name - _soc_l3_defip_index_map 30690 * @param - unit: unit number 30691 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30692 * @param - index: Logical index 30693 * 30694 * @purpose - Map logical index to physical index 30695 */ 30696 STATIC int 30697 _soc_l3_defip_index_map(int unit, int wide, int index) 30698 { 30699 int new_index = index; 30700 int num_tcams = 0; 30701 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30702 int entries_left_in_paired_tcam = 0; 30703 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit); 30704 30705 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30706 return index; 30707 } 30708 if (wide == 0) { 30709 if (soc_feature(unit, soc_feature_l3_1k_defip_table)) { 30710 num_tcams = soc_defip_index_remap > 0 ? 1: 0; 30711 new_index = index + num_tcams * 2 * tcam_size; 30712 } else { 30713 num_tcams = soc_defip_index_remap / tcam_size; 30714 entries_left_in_paired_tcam = tcam_size - 30715 (soc_defip_index_remap % tcam_size); 30716 if (index < entries_left_in_paired_tcam) { 30717 new_index = index + (num_tcams * 2 * tcam_size) + 30718 soc_defip_index_remap % tcam_size; 30719 } else { 30720 new_index = index + (num_tcams * 2 * tcam_size) + 30721 ((soc_defip_index_remap % tcam_size) * 2); 30722 } 30723 } 30724 return new_index; 30725 } 30726 return index; 30727 } 30728 30729 /* 30730 * @name - _soc_th3_l3_defip_index_map 30731 * @param - unit: unit number 30732 * @param - wide: 0 - L3_DEFIP_LEVEL1, 1 - L3_DEFIP_PAIR_LEVEL1 30733 * @param - index: Logical index 30734 * 30735 * @purpose - Map logical index to physical index 30736 * - (only for TH3 ALPM2 Parallel/Mix IPv6-128b modes) 30737 * -------------- 0 30738 * L3_DEFIP_PAIR_LEVEL1 | DB0 (v6) | BLOCK_0 (TCAM0/1) 30739 * |------------| Private 30740 * L3_DEFIP_LEVEL1 | DB0 (v4) | BLOCK_1 (TCAM2/3) 30741 * |------------| 30742 * L3_DEFIP_PAIR_LEVEL1 | DB1 (v6) | BLOCK_2 (TCAM4/5) 30743 * |------------| Public 30744 * L3_DEFIP_LEVEL1 | DB1 (v4) | BLOCK_3 (TCAM6/7) 30745 * -------------- 1023 30746 */ 30747 STATIC int 30748 _soc_th3_l3_defip_index_map(int unit, int wide, int index) 30749 { 30750 int new_index; 30751 int num_tcams; 30752 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30753 int entries_left_in_paired_tcam; 30754 int entries_left_in_tcam; 30755 int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit); 30756 /* DB0: Private, DB1: Public */ 30757 int per_db_pair_entries = soc_defip_index_remap / 2; 30758 30759 num_tcams = per_db_pair_entries / tcam_size; 30760 entries_left_in_paired_tcam = tcam_size - (per_db_pair_entries % tcam_size); 30761 entries_left_in_tcam = 2 * tcam_size - per_db_pair_entries; 30762 30763 if (wide == 0) { 30764 if (index < entries_left_in_paired_tcam) { 30765 new_index = index + (num_tcams * 2 * tcam_size) + 30766 (per_db_pair_entries % tcam_size); 30767 } else if (index < 2 * entries_left_in_tcam) { 30768 new_index = index + (num_tcams * 2 * tcam_size) + 30769 2 * (per_db_pair_entries % tcam_size); 30770 } else if (index < 2 * entries_left_in_tcam + 30771 entries_left_in_paired_tcam) { 30772 new_index = index + 2 * (num_tcams * 2 * tcam_size) + 30773 3 * (per_db_pair_entries % tcam_size); 30774 } else { 30775 new_index = index + 2 * (num_tcams * 2 * tcam_size) + 30776 4 * (per_db_pair_entries % tcam_size); 30777 } 30778 } else { /* wide = 1 */ 30779 if (index < per_db_pair_entries) { 30780 new_index = index; 30781 } else { 30782 new_index = index + entries_left_in_tcam; 30783 } 30784 } 30785 return new_index; 30786 } 30787 30788 30789 /* 30790 * @name - soc_l3_defip_index_map 30791 * @param - unit: unit number 30792 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30793 * @param - index: Logical index 30794 * 30795 * @purpose - Map logical index to physical index 30796 */ 30797 int 30798 soc_l3_defip_index_map(int unit, int wide, int index) 30799 { 30800 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30801 return index; 30802 } 30803 30804 assert(SOC_L3_DEFIP_INDEX_INIT(unit)); 30805 if (wide == 0) { 30806 return SOC_L3_DEFIP_LOG_TO_PHY_INDEX(unit, index); 30807 } 30808 return SOC_L3_DEFIP_PAIR_LOG_TO_PHY_INDEX(unit, index); 30809 } 30810 30811 /* 30812 * @name - _soc_l3_defip_alpm_urpf_index_remap 30813 * @param - unit: unit number 30814 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30815 * @param - index: Physical index 30816 * 30817 * @purpose - Remap physical index to logical index 30818 */ 30819 STATIC int 30820 _soc_l3_defip_alpm_urpf_index_remap(int unit, int wide, int index) 30821 { 30822 uint32 tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30823 uint32 num_chunks, chunk_offset; 30824 int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit); 30825 int defip128_tbl_sz = SOC_CONTROL(unit)->l3_defip_index_remap; 30826 soc_mem_t mem = L3_DEFIPm; 30827 30828 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 30829 mem = L3_DEFIP_LEVEL1m; 30830 } 30831 30832 if (wide) { 30833 num_chunks = index / tcam_size; 30834 chunk_offset = index % tcam_size; 30835 return num_chunks * defip128_tbl_sz / (max_tcams / 2) + 30836 chunk_offset; 30837 } 30838 num_chunks = index / tcam_size; 30839 chunk_offset = index % tcam_size; 30840 chunk_offset -= (defip128_tbl_sz / (max_tcams / 2)); 30841 30842 return num_chunks * soc_mem_index_count(unit, mem) / max_tcams + chunk_offset; 30843 } 30844 30845 30846 /* 30847 * @name - soc_l3_defip_alpm_urpf_index_remap 30848 * @param - unit: unit number 30849 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30850 * @param - index: Physical index 30851 * 30852 * @purpose - Remap physical index to logical index 30853 */ 30854 int 30855 soc_l3_defip_alpm_urpf_index_remap(int unit, int wide, int index) 30856 { 30857 assert(SOC_L3_DEFIP_INDEX_INIT(unit)); 30858 if (wide == 0) { 30859 return SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_INDEX(unit, index); 30860 } 30861 return SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_INDEX(unit, index); 30862 } 30863 /* 30864 * @name - _soc_l3_defip_alpm_urpf_index_map 30865 * @param - unit: unit number 30866 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30867 * @param - index: Logical index 30868 * 30869 * @purpose - Map logical index to physical index 30870 */ 30871 STATIC int 30872 _soc_l3_defip_alpm_urpf_index_map(int unit, int wide, int index) 30873 { 30874 uint32 tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30875 uint32 tcam_num, tcam_idx; 30876 int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit); 30877 uint32 incr; 30878 int defip128_tbl_sz = SOC_CONTROL(unit)->l3_defip_index_remap; 30879 soc_mem_t mem = L3_DEFIPm; 30880 30881 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 30882 mem = L3_DEFIP_LEVEL1m; 30883 } 30884 30885 if (wide) { 30886 incr = defip128_tbl_sz / (max_tcams / 2); 30887 tcam_num = index / incr; 30888 tcam_idx = index % incr; 30889 return tcam_num * tcam_size + tcam_idx; 30890 } 30891 incr = soc_mem_index_count(unit, mem) / (max_tcams / 2); 30892 30893 incr = incr / 2; 30894 tcam_num = index / incr; 30895 tcam_idx = index % incr; 30896 return tcam_num * tcam_size + tcam_idx + defip128_tbl_sz / (max_tcams / 2); 30897 } 30898 30899 30900 /* 30901 * @name - soc_l3_defip_alpm_urpf_index_map 30902 * @param - unit: unit number 30903 * @param - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128 30904 * @param - index: Logical index 30905 * 30906 * @purpose - Map logical index to physical index 30907 */ 30908 30909 int 30910 soc_l3_defip_alpm_urpf_index_map(int unit, int wide, int index) 30911 { 30912 assert(SOC_L3_DEFIP_INDEX_INIT(unit)); 30913 30914 if (wide == 0) { 30915 return SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_INDEX(unit, index); 30916 } 30917 return SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_INDEX(unit, index); 30918 } 30919 30920 /* 30921 * @name - soc_l3_defip_index_mem_map 30922 * @param - unit: unit number 30923 * @param - index: physical index 30924 * @param - (OUT)mem: name of the tcam 30925 * 30926 * @purpose - Map L3_DEFIP view using physical index 30927 */ 30928 30929 int 30930 soc_l3_defip_index_mem_map(int unit, int index, soc_mem_t* mem) 30931 { 30932 int logical_index = -1; 30933 int defip_pair_index = -1; 30934 int cam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 30935 soc_mem_t rtn_mem = L3_DEFIPm, rtn_pair_mem = L3_DEFIP_PAIR_128m; 30936 30937 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 30938 rtn_mem = L3_DEFIP_LEVEL1m; 30939 rtn_pair_mem = L3_DEFIP_PAIR_LEVEL1m; 30940 } 30941 30942 *mem = rtn_mem; 30943 30944 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 30945 return index; 30946 } 30947 30948 if (SOC_CONTROL(unit)->l3_defip_urpf && 30949 !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) { 30950 logical_index = soc_l3_defip_urpf_index_remap(unit, 0, index); 30951 30952 if (logical_index != -1) { 30953 *mem = rtn_mem; 30954 } else { 30955 *mem = rtn_pair_mem; 30956 defip_pair_index = ((index / (cam_size * 2)) * cam_size) + 30957 (index % cam_size); 30958 logical_index = soc_l3_defip_urpf_index_remap(unit, 1, 30959 defip_pair_index); 30960 } 30961 return logical_index; 30962 } 30963 30964 logical_index = soc_l3_defip_index_remap(unit, 0, index); 30965 30966 if (logical_index != -1) { 30967 *mem = rtn_mem; 30968 } else { 30969 *mem = rtn_pair_mem; 30970 defip_pair_index = ((index / (cam_size * 2)) * cam_size) + 30971 (index % cam_size); 30972 logical_index = soc_l3_defip_index_remap(unit, 1, defip_pair_index); 30973 } 30974 30975 return logical_index; 30976 } 30977 30978 int 30979 soc_l3_defip_indexes_deinit(int unit) 30980 { 30981 if (SOC_L3_DEFIP_INDEX_INIT(unit) == NULL) { 30982 return SOC_E_NONE; 30983 } 30984 30985 if (SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit)) { 30986 sal_free(SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit)); 30987 SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit) = NULL; 30988 } 30989 30990 if (SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit)) { 30991 sal_free(SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit)); 30992 SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit) = NULL; 30993 } 30994 30995 if (SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit)) { 30996 sal_free(SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit)); 30997 SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit) = NULL; 30998 } 30999 31000 if (SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit)) { 31001 sal_free(SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit)); 31002 SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit) = NULL; 31003 } 31004 31005 if (SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit)) { 31006 sal_free(SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit)); 31007 SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit) = NULL; 31008 } 31009 31010 if (SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit)) { 31011 sal_free(SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit)); 31012 SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit) = NULL; 31013 } 31014 31015 if (SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit)) { 31016 sal_free(SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit)); 31017 SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit) = NULL; 31018 } 31019 31020 if (SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit)) { 31021 sal_free(SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit)); 31022 SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit) = NULL; 31023 } 31024 31025 if (SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit)) { 31026 sal_free(SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit)); 31027 SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) = NULL; 31028 } 31029 if (SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit)) { 31030 sal_free(SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit)); 31031 SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) = NULL; 31032 } 31033 if (SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit)) { 31034 sal_free(SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit)); 31035 SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) = NULL; 31036 } 31037 if (SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit)) { 31038 sal_free(SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit)); 31039 SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) = NULL; 31040 } 31041 31042 if (SOC_L3_DEFIP_INDEX_INIT(unit)) { 31043 sal_free(SOC_L3_DEFIP_INDEX_INIT(unit)); 31044 SOC_L3_DEFIP_INDEX_INIT(unit) = NULL; 31045 } 31046 31047 return SOC_E_NONE; 31048 } 31049 31050 /* 31051 * @name - soc_l3_defip_indexes_init 31052 * @param - unit: unit number 31053 * @returns - SOC_E_MEMORY, SOC_E_NONE 31054 * 31055 * @purpose - generate a map of logical to physical and 31056 * physical to logical indexes 31057 */ 31058 int 31059 soc_l3_defip_indexes_init(int unit, int config_ipv6_entries) 31060 { 31061 int log_index; 31062 int phy_index; 31063 int temp_index; 31064 31065 int max_index = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit) * 31066 SOC_L3_DEFIP_MAX_TCAMS_GET(unit); 31067 soc_mem_t mem = L3_DEFIPm, memp = L3_DEFIP_PAIR_128m; 31068 31069 int defip_max_index; 31070 int size; 31071 int defip_table_present; 31072 int defip_pair_128_table_present; 31073 int th3_defip_map = 0; 31074 31075 #ifdef BCM_TOMAHAWK3_SUPPORT 31076 if (SOC_IS_TOMAHAWK3(unit)) { 31077 mem = L3_DEFIP_LEVEL1m; 31078 memp = L3_DEFIP_PAIR_LEVEL1m; 31079 #ifdef ALPM_ENABLE 31080 if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1) && 31081 (soc_alpm_cmn_mode_get(unit) == SOC_ALPM_MODE_PARALLEL || 31082 soc_alpm_cmn_mode_get(unit) == SOC_ALPM_MODE_TCAM_ALPM)) { 31083 th3_defip_map = 1; 31084 } 31085 #endif 31086 } 31087 #endif 31088 31089 defip_max_index = soc_mem_index_count(unit, mem); 31090 31091 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 31092 SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) = config_ipv6_entries; 31093 return SOC_E_NONE; 31094 } 31095 31096 assert(SOC_L3_DEFIP_TCAM_DEPTH_GET(unit)); 31097 assert(SOC_L3_DEFIP_MAX_TCAMS_GET(unit)); 31098 31099 SOC_IF_ERROR_RETURN(soc_l3_defip_indexes_deinit(unit)); 31100 31101 SOC_L3_DEFIP_INDEX_INIT(unit) = 31102 sal_alloc(sizeof(_soc_l3_defip_index_table_t), "defip map table"); 31103 if (SOC_L3_DEFIP_INDEX_INIT(unit) == NULL) { 31104 return SOC_E_MEMORY; 31105 } 31106 31107 sal_memset(SOC_L3_DEFIP_INDEX_INIT(unit), 0x0, 31108 sizeof(_soc_l3_defip_index_table_t)); 31109 defip_table_present = 31110 soc_mem_index_count(unit, mem) ? 1 : 0; 31111 31112 if (defip_table_present) { 31113 size = defip_max_index * sizeof(int); 31114 SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit) = 31115 sal_alloc(size, "defip log to phy index mapping"); 31116 if (SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit) == NULL) { 31117 return SOC_E_MEMORY; 31118 } 31119 sal_memset(SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit), -1, size); 31120 31121 /* required also for non-URPF ALPM Parallel/Mixed modes */ 31122 SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit) = 31123 sal_alloc(size, "urpf defip log to phy index mapping"); 31124 if (SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) { 31125 return SOC_E_MEMORY; 31126 } 31127 sal_memset(SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit), -1, size); 31128 31129 if (soc_feature(unit, soc_feature_urpf)) { 31130 SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) = 31131 sal_alloc(size, "alpm urpf defip log to phy index mapping"); 31132 if (SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) { 31133 return SOC_E_MEMORY; 31134 } 31135 sal_memset(SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit), -1, size); 31136 } 31137 size = max_index * sizeof(int); 31138 SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit) = 31139 sal_alloc(size, "defip phy to log index mapping"); 31140 if (SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit) == NULL) { 31141 return SOC_E_MEMORY; 31142 } 31143 sal_memset(SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit), -1, size); 31144 31145 /* required also for non-URPF ALPM Parallel/Mixed modes */ 31146 SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit) = 31147 sal_alloc(size, "defip phy to log index mapping"); 31148 if (SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) { 31149 return SOC_E_MEMORY; 31150 } 31151 sal_memset(SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit), -1, size); 31152 31153 if (soc_feature(unit, soc_feature_urpf)) { 31154 SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) = 31155 sal_alloc(size, "alpm urpf defip phy to log index mapping"); 31156 if (SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) { 31157 return SOC_E_MEMORY; 31158 } 31159 sal_memset(SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit), -1, size); 31160 } 31161 } 31162 31163 defip_pair_128_table_present = 31164 soc_mem_index_count(unit, memp) ? 1 : 0; 31165 31166 if (defip_pair_128_table_present) { 31167 size = soc_mem_index_count(unit, memp) * sizeof(int); 31168 SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit) = 31169 sal_alloc(size, "defip log to phy index mapping"); 31170 if (SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit) == NULL) { 31171 return SOC_E_MEMORY; 31172 } 31173 sal_memset(SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit), -1, size); 31174 31175 /* required also for non-URPF ALPM Parallel/Mixed modes */ 31176 SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit) = 31177 sal_alloc(size, "urpf defip log to phy index mapping"); 31178 if (SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) { 31179 return SOC_E_MEMORY; 31180 } 31181 sal_memset(SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit), -1, size); 31182 31183 if (soc_feature(unit, soc_feature_urpf)) { 31184 SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) = 31185 sal_alloc(size, "alpm urpf defip log to phy index mapping"); 31186 if (SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) { 31187 return SOC_E_MEMORY; 31188 } 31189 sal_memset(SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit), -1, size); 31190 } 31191 size = max_index * sizeof(int); 31192 SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit) = 31193 sal_alloc(size, "defip phy to log index mapping"); 31194 if (SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit) == NULL) { 31195 return SOC_E_MEMORY; 31196 } 31197 sal_memset(SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit), -1, size); 31198 31199 /* required also for non-URPF ALPM Parallel/Mixed modes */ 31200 SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit) = 31201 sal_alloc(size, "defip phy to log index mapping"); 31202 if (SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) { 31203 return SOC_E_MEMORY; 31204 } 31205 sal_memset(SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit), -1, size); 31206 31207 if (soc_feature(unit, soc_feature_urpf)) { 31208 SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) = 31209 sal_alloc(size, "alpm urpf defip phy to log index mapping"); 31210 if (SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) { 31211 return SOC_E_MEMORY; 31212 } 31213 sal_memset(SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit), -1, size); 31214 } 31215 } 31216 31217 for (log_index = 0; log_index < defip_max_index; log_index++) { 31218 31219 if (th3_defip_map) { 31220 phy_index = _soc_th3_l3_defip_index_map(unit, 0, log_index); 31221 } else { 31222 phy_index = _soc_l3_defip_index_map(unit, 0, log_index); 31223 } 31224 SOC_L3_DEFIP_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31225 31226 if (th3_defip_map) { 31227 temp_index = _soc_th3_l3_defip_index_remap(unit, 0, phy_index); 31228 } else { 31229 temp_index = _soc_l3_defip_index_remap(unit, 0, phy_index); 31230 } 31231 SOC_L3_DEFIP_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31232 if (log_index != temp_index || phy_index >= max_index) { 31233 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31234 (BSL_META_U(unit, 31235 "defip map/remap failed 1: " 31236 "lidx %d tidx %d pidx %d midx:%d\n"), 31237 log_index, temp_index, phy_index, max_index)); 31238 } 31239 31240 /* required also for non-URPF ALPM Parallel/Mixed modes */ 31241 if (SOC_IS_TRIUMPH3(unit) && 31242 soc_feature(unit, soc_feature_l3_reduced_defip_table)) { 31243 phy_index = _soc_l3_reduced_defip_urpf_index_map(unit, 0, log_index); 31244 SOC_L3_DEFIP_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31245 temp_index = _soc_l3_reduced_defip_urpf_index_remap(unit, 0, phy_index); 31246 SOC_L3_DEFIP_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31247 } else { 31248 phy_index = _soc_l3_defip_urpf_index_map(unit, 0, log_index); 31249 SOC_L3_DEFIP_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31250 temp_index = _soc_l3_defip_urpf_index_remap(unit, 0, phy_index); 31251 SOC_L3_DEFIP_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31252 } 31253 if (log_index != temp_index || phy_index >= max_index) { 31254 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31255 (BSL_META_U(unit, 31256 "defip map/remap failed 2: " 31257 "lidx %d tidx %d pidx %d midx:%d\n"), 31258 log_index, temp_index, phy_index, max_index)); 31259 } 31260 31261 if (!soc_feature(unit, soc_feature_urpf)) { 31262 continue; 31263 } 31264 31265 if (SOC_CONTROL(unit)->l3_defip_index_remap % 4 || 31266 SOC_L3_DEFIP_MAX_TCAMS_GET(unit) % 4 || 31267 !soc_feature(unit, soc_feature_alpm)) { 31268 /* alpm urpf will not be used */ 31269 continue; 31270 } 31271 31272 phy_index = _soc_l3_defip_alpm_urpf_index_map(unit, 0, log_index); 31273 SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31274 temp_index = _soc_l3_defip_alpm_urpf_index_remap(unit, 0, phy_index); 31275 SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31276 if (log_index != temp_index || phy_index >= max_index) { 31277 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31278 (BSL_META_U(unit, 31279 "defip map/remap failed 3: " 31280 "lidx %d tidx %d pidx %d midx:%d\n"), 31281 log_index, temp_index, phy_index, max_index)); 31282 } 31283 } 31284 31285 defip_max_index = soc_mem_index_count(unit, memp); 31286 for (log_index = 0; log_index < defip_max_index; log_index++) { 31287 31288 if (th3_defip_map) { 31289 phy_index = _soc_th3_l3_defip_index_map(unit, 1, log_index); 31290 } else { 31291 phy_index = _soc_l3_defip_index_map(unit, 1, log_index); 31292 } 31293 SOC_L3_DEFIP_PAIR_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31294 31295 if (th3_defip_map) { 31296 temp_index = _soc_th3_l3_defip_index_remap(unit, 1, phy_index); 31297 } else { 31298 temp_index = _soc_l3_defip_index_remap(unit, 1, phy_index); 31299 } 31300 SOC_L3_DEFIP_PAIR_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31301 if (log_index != temp_index || phy_index >= max_index) { 31302 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31303 (BSL_META_U(unit, 31304 "defip map/remap failed 4: " 31305 "lidx %d tidx %d pidx %d midx:%d\n"), 31306 log_index, temp_index, phy_index, max_index)); 31307 } 31308 31309 /* required also for non-URPF ALPM Parallel/Mixed modes */ 31310 if (SOC_IS_TRIUMPH3(unit) && 31311 soc_feature(unit, soc_feature_l3_reduced_defip_table)) { 31312 phy_index = _soc_l3_reduced_defip_urpf_index_map(unit, 1, log_index); 31313 SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31314 temp_index = _soc_l3_reduced_defip_urpf_index_remap(unit, 1, phy_index); 31315 SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31316 } else { 31317 phy_index = _soc_l3_defip_urpf_index_map(unit, 1, log_index); 31318 SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31319 temp_index = _soc_l3_defip_urpf_index_remap(unit, 1, phy_index); 31320 SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31321 } 31322 if (log_index != temp_index || phy_index >= max_index) { 31323 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31324 (BSL_META_U(unit, 31325 "defip map/remap failed 5: " 31326 "lidx %d tidx %d pidx %d midx:%d\n"), 31327 log_index, temp_index, phy_index, max_index)); 31328 } 31329 31330 if (!soc_feature(unit, soc_feature_urpf)) { 31331 continue; 31332 } 31333 31334 if (SOC_CONTROL(unit)->l3_defip_index_remap % 4 || 31335 SOC_L3_DEFIP_MAX_TCAMS_GET(unit) % 4 || 31336 !soc_feature(unit, soc_feature_alpm)) { 31337 /* alpm urpf will not be used */ 31338 continue; 31339 } 31340 31341 phy_index = _soc_l3_defip_alpm_urpf_index_map(unit, 1, log_index); 31342 SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index; 31343 temp_index = _soc_l3_defip_alpm_urpf_index_remap(unit, 1, phy_index); 31344 SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index; 31345 if (log_index != temp_index || phy_index >= max_index) { 31346 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31347 (BSL_META_U(unit, 31348 "defip map/remap failed 6: " 31349 "lidx %d tidx %d pidx %d midx:%d\n"), 31350 log_index, temp_index, phy_index, max_index)); 31351 } 31352 } 31353 31354 SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) = config_ipv6_entries; 31355 return SOC_E_NONE; 31356 } 31357 31358 /* 31359 * This function assumes that the lock to L3_DEFIP and 31360 * L3_DEFIP_PAIR_128 tables are already taken 31361 */ 31362 int 31363 soc_defip_tables_resize(int unit, int num_ipv6_128b_entries) 31364 { 31365 soc_persist_t *sop; 31366 int config_v6_entries = 0; 31367 int num_defip_entries = 0; 31368 int max_tcams = 0, tcam_size = 0; 31369 31370 soc_mem_t mem = L3_DEFIPm, pair_mem = L3_DEFIP_PAIR_128m; 31371 31372 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 31373 mem = L3_DEFIP_LEVEL1m; 31374 pair_mem = L3_DEFIP_PAIR_LEVEL1m; 31375 } 31376 31377 num_ipv6_128b_entries = num_ipv6_128b_entries + 31378 (num_ipv6_128b_entries % 2); 31379 31380 #if defined(BCM_TRIDENT2_SUPPORT) 31381 if (soc_feature(unit, soc_feature_alpm) && 31382 (soc_trident2_alpm_mode_get(unit) == 1 || 31383 soc_trident2_alpm_mode_get(unit) == 3)) { 31384 num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4; 31385 } 31386 #endif /* BCM_TRIDENT2_SUPPORT */ 31387 31388 if (SOC_CONTROL(unit)->tcam_protect_write) { 31389 num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4; 31390 } 31391 config_v6_entries = num_ipv6_128b_entries; 31392 31393 max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit); 31394 tcam_size = SOC_CONTROL(unit)->l3_defip_tcam_size; 31395 if (SOC_CONTROL(unit)->tcam_protect_write) { 31396 if (soc_mem_index_count(unit, pair_mem)) { 31397 tcam_size++; 31398 } 31399 if (soc_mem_index_count(unit, mem)) { 31400 tcam_size++; 31401 } 31402 } 31403 31404 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 31405 num_ipv6_128b_entries = 0; 31406 } 31407 31408 num_defip_entries = (max_tcams * tcam_size) - 31409 (num_ipv6_128b_entries * 2); 31410 if (SOC_CONTROL(unit)->tcam_protect_write) { 31411 if (num_defip_entries) { 31412 num_defip_entries -= SOC_CONTROL(unit)->l3_defip_max_tcams; 31413 /* Don't use up all entries as protect entries */ 31414 if (num_defip_entries <= 0) { 31415 return SOC_E_CONFIG; 31416 } 31417 tcam_size--; 31418 } 31419 if (num_ipv6_128b_entries) { 31420 num_ipv6_128b_entries -= SOC_CONTROL(unit)->l3_defip_max_tcams/2; 31421 /* Don't use up all entries as protect entries */ 31422 if (num_ipv6_128b_entries <= 0) { 31423 return SOC_E_CONFIG; 31424 } 31425 tcam_size--; 31426 } 31427 if (config_v6_entries) { 31428 config_v6_entries -= SOC_CONTROL(unit)->l3_defip_max_tcams/2; 31429 if (config_v6_entries < 0) { 31430 return SOC_E_CONFIG; 31431 } 31432 } 31433 } 31434 SOC_CONTROL(unit)->l3_defip_tcam_size = tcam_size; 31435 31436 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 31437 if(!soc_feature(unit, soc_feature_l3_lpm_128b_entries_reserved)) { 31438 config_v6_entries = ((config_v6_entries / 31439 SOC_CONTROL(unit)->l3_defip_tcam_size) + 31440 ((config_v6_entries % 31441 SOC_CONTROL(unit)->l3_defip_tcam_size) 31442 ? 1 : 0)) * SOC_CONTROL(unit)->l3_defip_tcam_size; 31443 } 31444 SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) = config_v6_entries; 31445 return SOC_E_NONE; 31446 } 31447 31448 sop = SOC_PERSIST(unit); 31449 sop->memState[pair_mem].index_max = 31450 num_ipv6_128b_entries - 1; 31451 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = 31452 num_ipv6_128b_entries - 1; 31453 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = 31454 num_ipv6_128b_entries - 1; 31455 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = 31456 num_ipv6_128b_entries - 1; 31457 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLY_Xm].index_max = 31458 num_ipv6_128b_entries - 1; 31459 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLY_Ym].index_max = 31460 num_ipv6_128b_entries - 1; 31461 sop->memState[mem].index_max = num_defip_entries - 1; 31462 31463 if (soc_feature(unit, soc_feature_l3_1k_defip_table)) { 31464 sop->memState[mem].index_max = 1023; 31465 } 31466 31467 sop->memState[L3_DEFIP_ONLYm].index_max = 31468 sop->memState[mem].index_max; 31469 sop->memState[L3_DEFIP_DATA_ONLYm].index_max = 31470 sop->memState[mem].index_max; 31471 sop->memState[L3_DEFIP_HIT_ONLYm].index_max = 31472 sop->memState[mem].index_max; 31473 sop->memState[L3_DEFIP_HIT_ONLY_Xm].index_max = 31474 sop->memState[mem].index_max; 31475 sop->memState[L3_DEFIP_HIT_ONLY_Ym].index_max = 31476 sop->memState[mem].index_max; 31477 SOC_CONTROL(unit)->l3_defip_index_remap = num_ipv6_128b_entries; 31478 return soc_l3_defip_indexes_init(unit, config_v6_entries); 31479 } 31480 /* 31481 * This function makes config variables unit specific and 31482 * either updates config.bcm or display on the terminal 31483 */ 31484 void 31485 soc_mem_config_save(int unit, char *config_str, char *config_value) 31486 { 31487 char local_config_str[80]; 31488 sal_sprintf(local_config_str,"%s.%d",config_str,unit); 31489 31490 if (soc_mem_config_set != NULL) { 31491 soc_mem_config_set(local_config_str,config_value); 31492 } else { 31493 if (config_value != NULL) { 31494 LOG_CLI((BSL_META_U(unit, 31495 "%s=%s #Add in config.bcm\n"), 31496 local_config_str,config_value)); 31497 } 31498 } 31499 } 31500 31501 #if defined(BCM_TRIUMPH3_SUPPORT) 31502 /* 31503 * Function: 31504 * soc_mem_field_clear_all 31505 * Purpose: 31506 * Clears a field in all entries for a memory . 31507 * Operates on all copies of the table if copyno is COPYNO_ALL. 31508 * Notes: 31509 */ 31510 31511 int 31512 soc_mem_field_clear_all(int unit, 31513 soc_mem_t mem, 31514 soc_field_t field, 31515 int copyno, 31516 int force_all) 31517 { 31518 int rv = SOC_E_NONE; 31519 int chunk_size, chunk_entries, mem_size, entry_words; 31520 int index, index_end, index_min, index_max; 31521 uint32 *buf; 31522 uint32 fval[SOC_MAX_MEM_FIELD_WORDS]; 31523 int i; 31524 31525 31526 /* Implemented for TR3 and HX4 */ 31527 if (!(SOC_IS_TRIUMPH3(unit) || SOC_IS_HELIX4(unit))) { 31528 return SOC_E_UNAVAIL; 31529 } 31530 31531 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) { 31532 return SOC_E_NONE; 31533 } 31534 31535 _SOC_MEM_REPLACE_MEM(unit, mem); 31536 if (soc_mem_index_count(unit, mem) == 0) { 31537 return SOC_E_NONE; 31538 } 31539 31540 sal_memset(fval, 0, sizeof (fval)); 31541 31542 /* check is the field is valid */ 31543 if (!SOC_MEM_FIELD_VALID(unit, mem, field)) { 31544 return SOC_E_PARAM; 31545 } 31546 31547 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE)); 31548 31549 chunk_size = SOC_MEM_CLEAR_CHUNK_SIZE_GET(unit); 31550 index_min = soc_mem_index_min(unit, mem); 31551 index_max = soc_mem_index_max(unit, mem); 31552 entry_words = soc_mem_entry_words(unit, mem); 31553 mem_size = (index_max - index_min + 1) * entry_words * 4; 31554 31555 if (mem_size < chunk_size) { 31556 chunk_size = mem_size; 31557 } 31558 31559 buf = soc_cm_salloc(unit, chunk_size, "mem_clear_buf"); 31560 if (buf == NULL) { 31561 return SOC_E_MEMORY; 31562 } 31563 31564 chunk_entries = chunk_size / (entry_words * 4); 31565 31566 rv = SOC_E_NONE; 31567 MEM_LOCK(unit, mem); 31568 for (index = index_min; index <= index_max; index += chunk_entries) { 31569 index_end = index + chunk_entries - 1; 31570 if (index_end > index_max) { 31571 LOG_CLI((BSL_META_U(unit, 31572 "index_end = %d\n"), index_end)); 31573 index_end = index_max; 31574 } 31575 31576 /* read a chunk of data from mem */ 31577 rv = soc_mem_read_range(unit, mem, copyno, index, index_end, buf); 31578 if (rv < 0) { 31579 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31580 (BSL_META_U(unit, 31581 "soc_mem_read_range: " 31582 "read %s.%s[%d-%d] failed: %s\n"), 31583 SOC_MEM_UFNAME(unit, mem), 31584 SOC_BLOCK_NAME(unit, copyno), 31585 index, index_end, soc_errmsg(rv))); 31586 break; 31587 } 31588 31589 31590 /* Clear the field in each entry */ 31591 for (i = 0; i < chunk_entries; i++) { 31592 soc_mem_field_set(unit, mem, &buf[i * entry_words], 31593 field, fval); 31594 } 31595 31596 /* Write back the entries to mem */ 31597 rv = soc_mem_write_range(unit, mem, copyno, index, index_end, buf); 31598 if (rv < 0) { 31599 LOG_ERROR(BSL_LS_SOC_SOCMEM, 31600 (BSL_META_U(unit, 31601 "soc_mem_write_range: " 31602 "write %s.%s[%d-%d] failed: %s\n"), 31603 SOC_MEM_UFNAME(unit, mem), 31604 SOC_BLOCK_NAME(unit, copyno), 31605 index, index_end, soc_errmsg(rv))); 31606 break; 31607 } 31608 } 31609 31610 MEM_UNLOCK(unit, mem); 31611 soc_cm_sfree(unit, buf); 31612 return rv; 31613 } 31614 #endif /* BCM_TRIUMPH3_SUPPORT */ 31615 31616 /* to setup L3_IIF default entries */ 31617 #if defined(BCM_HURRICANE3_SUPPORT) 31618 int 31619 _soc_hr3_l3iif_hw_mem_init(int unit, int force_init_all) 31620 { 31621 schan_msg_t schan_msg; 31622 int src_blk, dst_blk, blk, acc_type; 31623 iif_entry_t def_entry; 31624 uint8 at; 31625 uint32 maddr; 31626 int entry_dw, data_byte_len, idx; 31627 int bit_num = 0, val = 0x3f; 31628 int rv = SOC_E_NONE; 31629 31630 /* 31631 * GH2 leverage design from HR3 with the same L3_IIFm design. 31632 * - both L3_IIFm size are 512 only. 31633 */ 31634 if (!(SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) || 31635 !(SOC_MEM_IS_VALID(unit, L3_IIFm))) { 31636 return SOC_E_UNAVAIL; 31637 } 31638 sal_memcpy(&def_entry, soc_mem_entry_null(unit, L3_IIFm), 31639 sizeof(iif_entry_t)); 31640 31641 entry_dw = soc_mem_entry_words(unit, L3_IIFm); 31642 data_byte_len = entry_dw * sizeof (uint32); 31643 31644 /* 31645 * set default L3_IIFm.TRUST_DSCP_PTRf to maximum to prevent the 31646 * internal priority been changed unexpectedly. 31647 * - The L3_IIFm.TRUST_DSCP_PTRf in different ESW 31648 */ 31649 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf); 31650 switch (bit_num) { 31651 case 6: 31652 val= 0x3f; 31653 break; 31654 case 7: 31655 val = 0x7f; 31656 break; 31657 default : 31658 break; 31659 } 31660 31661 soc_mem_field32_set( 31662 unit, L3_IIFm, (uint32 *)&def_entry, TRUST_DSCP_PTRf, val); 31663 31664 /* 31665 * Performing the low level mem write operation to avoid MEM and index 31666 * validation. In many HR3 SKUs, L3_IIFm is valid but entry count is 0. 31667 * - that means "index_max" in SOC info for L3_IIFm will be -1 31668 * - soc_mem_index_max() for this case can't report HW table size. 31669 */ 31670 schan_msg_clear(&schan_msg); 31671 acc_type = SOC_MEM_ACC_TYPE(unit, L3_IIFm); 31672 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 31673 sal_memcpy( 31674 schan_msg.writecmd.data, &def_entry, entry_dw * sizeof(uint32)); 31675 31676 LOG_INFO(BSL_LS_SOC_L3, 31677 (BSL_META_U(unit, "Installing default L3_IIFm entry..\n"))); 31678 31679 MEM_LOCK(unit, L3_IIFm); 31680 if (SOC_IS_HURRICANE3(unit) && 31681 soc_feature(unit, soc_feature_l3) && 31682 soc_feature(unit, soc_feature_l3_iif_under_4k) == 0) { 31683 for (idx = 0; idx < HR3_L3_IIF_HW_SIZE; idx ++){ 31684 /* Write to one or all copies of the memory */ 31685 SOC_MEM_BLOCK_ITER(unit, L3_IIFm, blk) { 31686 31687 maddr = soc_mem_addr_get(unit, L3_IIFm, 0, blk, idx, &at); 31688 schan_msg.writecmd.address = maddr; 31689 31690 soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk); 31691 31692 soc_schan_header_cmd_set( 31693 unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG, 31694 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 31695 31696 /* Write header + address + entry_dw data DWORDs */ 31697 /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */ 31698 if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) { 31699 LOG_WARN(BSL_LS_SOC_SOCMEM, 31700 (BSL_META_U( 31701 unit, "soc_mem_write: " 31702 "assert will fail for memory %s\n"), 31703 SOC_MEM_NAME(unit, L3_IIFm))); 31704 } 31705 31706 rv = _soc_mem_write_schan_msg_send( 31707 unit, &schan_msg, L3_IIFm, blk, idx); 31708 if (SOC_FAILURE(rv)) { 31709 break; 31710 } 31711 } 31712 if (!force_init_all) { 31713 break; 31714 } 31715 } 31716 } else { 31717 for (idx = 0; idx <= soc_mem_index_max(unit, L3_IIFm); idx++) { 31718 rv = soc_mem_field32_modify( 31719 unit, L3_IIFm, idx, TRUST_DSCP_PTRf, val); 31720 } 31721 } 31722 MEM_UNLOCK(unit, L3_IIFm); 31723 31724 LOG_INFO(BSL_LS_SOC_L3, (BSL_META_U(unit, 31725 "L3_IIFm %d entries is installed(rv=%d)!\n") , idx, rv)); 31726 31727 return rv; 31728 } 31729 #endif /* BCM_HURRICANE3_SUPPORT */ 31730 31731 #if defined(BCM_TOMAHAWK3_SUPPORT) 31732 int 31733 _soc_mem_cmp_l3_tunnel(int unit, void *ent_a, void *ent_b) 31734 { 31735 uint32 val_a, val_b; 31736 uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS]; 31737 uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS]; 31738 31739 val_a = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_a, KEY_TYPEf); 31740 val_b = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_b, KEY_TYPEf); 31741 SOC_MEM_COMPARE_RETURN(val_a, val_b); 31742 31743 switch (val_a) { 31744 case TH3_TUNNEL_HASH_KEY_TYPE_MPLS: 31745 val_a = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_a, MPLS__KEYf); 31746 val_b = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_b, MPLS__KEYf); 31747 31748 SOC_MEM_COMPARE_RETURN(val_a, val_b); 31749 31750 return 0; 31751 31752 case TH3_TUNNEL_HASH_KEY_TYPE_V4: 31753 soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_a, IPV4__KEY_0f, buf_a); 31754 soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_b, IPV4__KEY_0f, buf_b); 31755 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 31756 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 31757 31758 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 31759 31760 soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_a, IPV4__KEY_1f, buf_a); 31761 soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_b, IPV4__KEY_1f, buf_b); 31762 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 31763 31764 return 0; 31765 31766 case TH3_TUNNEL_HASH_KEY_TYPE_V6: 31767 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_0f, buf_a); 31768 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_0f, buf_b); 31769 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 31770 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 31771 31772 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 31773 31774 31775 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_1f, buf_a); 31776 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_1f, buf_b); 31777 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 31778 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 31779 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 31780 31781 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_2f, buf_a); 31782 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_2f, buf_b); 31783 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 31784 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 31785 31786 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_3f, buf_a); 31787 soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_3f, buf_b); 31788 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]); 31789 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]); 31790 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]); 31791 31792 return 0; 31793 31794 default: 31795 return 1; 31796 } 31797 31798 return 0; 31799 } 31800 #endif /* BCM_TOMAHAWK3_SUPPORT */ 31801 31802 31803 31804 void 31805 soc_mem_field_acc_mode_get( 31806 int unit, 31807 soc_mem_t mem, 31808 soc_field_t field, 31809 uint32 *is_read_only, 31810 uint32 *is_write_only) 31811 { 31812 soc_field_info_t *finfop; 31813 31814 *is_read_only = 0; 31815 *is_write_only = 0; 31816 31817 if (!SOC_MEM_IS_VALID(unit, mem)) 31818 { 31819 #if !defined(SOC_NO_NAMES) 31820 LOG_CLI((BSL_META_U(unit, "msm %s is invalid\n"), soc_mem_name[mem])); 31821 #endif 31822 assert(SOC_MEM_IS_VALID(unit, mem)); 31823 } 31824 31825 SOC_FIND_FIELD(field, SOC_MEM_INFO(unit, mem).fields, SOC_MEM_INFO(unit, mem).nFields, finfop); 31826 if (finfop == NULL) 31827 { 31828 #if !defined(SOC_NO_NAMES) 31829 LOG_CLI((BSL_META_U(unit, "mem %s field %s is invalid\n"), soc_mem_name[mem], soc_fieldnames[field])); 31830 #endif 31831 assert(finfop); 31832 } 31833 31834 if (finfop->flags & SOCF_RO) 31835 { 31836 *is_read_only = 1; 31837 } 31838 31839 if (finfop->flags & SOCF_WO) 31840 { 31841 *is_write_only = 1; 31842 } 31843 31844 } 31845 31846 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) */